@@ -174,6 +174,38 @@ RangeSet RangeSet::Intersect(BasicValueFactory &BV, Factory &F,
174
174
return newRanges;
175
175
}
176
176
177
+ // Turn all [A, B] ranges to [-B, -A]. Ranges [MIN, B] are turned to range set
178
+ // [MIN, MIN] U [-B, MAX], when MIN and MAX are the minimal and the maximal
179
+ // signed values of the type.
180
+ RangeSet RangeSet::Negate (BasicValueFactory &BV, Factory &F) const {
181
+ PrimRangeSet newRanges = F.getEmptySet ();
182
+
183
+ for (iterator i = begin (), e = end (); i != e; ++i) {
184
+ const llvm::APSInt &from = i->From (), &to = i->To ();
185
+ const llvm::APSInt &newTo = (from.isMinSignedValue () ?
186
+ BV.getMaxValue (from) :
187
+ BV.getValue (- from));
188
+ if (to.isMaxSignedValue () && !newRanges.isEmpty () &&
189
+ newRanges.begin ()->From ().isMinSignedValue ()) {
190
+ assert (newRanges.begin ()->To ().isMinSignedValue () &&
191
+ " Ranges should not overlap" );
192
+ assert (!from.isMinSignedValue () && " Ranges should not overlap" );
193
+ const llvm::APSInt &newFrom = newRanges.begin ()->From ();
194
+ newRanges =
195
+ F.add (F.remove (newRanges, *newRanges.begin ()), Range (newFrom, newTo));
196
+ } else if (!to.isMinSignedValue ()) {
197
+ const llvm::APSInt &newFrom = BV.getValue (- to);
198
+ newRanges = F.add (newRanges, Range (newFrom, newTo));
199
+ }
200
+ if (from.isMinSignedValue ()) {
201
+ newRanges = F.add (newRanges, Range (BV.getMinValue (from),
202
+ BV.getMinValue (from)));
203
+ }
204
+ }
205
+
206
+ return newRanges;
207
+ }
208
+
177
209
void RangeSet::print (raw_ostream &os) const {
178
210
bool isFirst = true ;
179
211
os << " { " ;
@@ -252,6 +284,8 @@ class RangeConstraintManager : public RangedConstraintManager {
252
284
RangeSet::Factory F;
253
285
254
286
RangeSet getRange (ProgramStateRef State, SymbolRef Sym);
287
+ const RangeSet* getRangeForMinusSymbol (ProgramStateRef State,
288
+ SymbolRef Sym);
255
289
256
290
RangeSet getSymLTRange (ProgramStateRef St, SymbolRef Sym,
257
291
const llvm::APSInt &Int,
@@ -268,6 +302,7 @@ class RangeConstraintManager : public RangedConstraintManager {
268
302
RangeSet getSymGERange (ProgramStateRef St, SymbolRef Sym,
269
303
const llvm::APSInt &Int,
270
304
const llvm::APSInt &Adjustment);
305
+
271
306
};
272
307
273
308
} // end anonymous namespace
@@ -423,9 +458,15 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
423
458
if (ConstraintRangeTy::data_type *V = State->get <ConstraintRange>(Sym))
424
459
return *V;
425
460
461
+ BasicValueFactory &BV = getBasicVals ();
462
+
463
+ // If Sym is a difference of symbols A - B, then maybe we have range set
464
+ // stored for B - A.
465
+ if (const RangeSet *R = getRangeForMinusSymbol (State, Sym))
466
+ return R->Negate (BV, F);
467
+
426
468
// Lazily generate a new RangeSet representing all possible values for the
427
469
// given symbol type.
428
- BasicValueFactory &BV = getBasicVals ();
429
470
QualType T = Sym->getType ();
430
471
431
472
RangeSet Result (F, BV.getMinValue (T), BV.getMaxValue (T));
@@ -441,6 +482,32 @@ RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
441
482
return Result;
442
483
}
443
484
485
+ // FIXME: Once SValBuilder supports unary minus, we should use SValBuilder to
486
+ // obtain the negated symbolic expression instead of constructing the
487
+ // symbol manually. This will allow us to support finding ranges of not
488
+ // only negated SymSymExpr-type expressions, but also of other, simpler
489
+ // expressions which we currently do not know how to negate.
490
+ const RangeSet*
491
+ RangeConstraintManager::getRangeForMinusSymbol (ProgramStateRef State,
492
+ SymbolRef Sym) {
493
+ if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(Sym)) {
494
+ if (SSE->getOpcode () == BO_Sub) {
495
+ QualType T = Sym->getType ();
496
+ SymbolManager &SymMgr = State->getSymbolManager ();
497
+ SymbolRef negSym = SymMgr.getSymSymExpr (SSE->getRHS (), BO_Sub,
498
+ SSE->getLHS (), T);
499
+ if (const RangeSet *negV = State->get <ConstraintRange>(negSym)) {
500
+ // Unsigned range set cannot be negated, unless it is [0, 0].
501
+ if ((negV->getConcreteValue () &&
502
+ (*negV->getConcreteValue () == 0 )) ||
503
+ T->isSignedIntegerOrEnumerationType ())
504
+ return negV;
505
+ }
506
+ }
507
+ }
508
+ return nullptr ;
509
+ }
510
+
444
511
// ===------------------------------------------------------------------------===
445
512
// assumeSymX methods: protected interface for RangeConstraintManager.
446
513
// ===------------------------------------------------------------------------===/
0 commit comments