19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/ImmutableSet.h"
21 #include "llvm/Support/raw_ostream.h"
23 using namespace clang;
30 class Range :
public std::pair<const llvm::APSInt *, const llvm::APSInt *> {
32 Range(
const llvm::APSInt &from,
const llvm::APSInt &to)
33 : std::pair<const llvm::APSInt *, const llvm::APSInt *>(&from, &to) {
36 bool Includes(
const llvm::APSInt &
v)
const {
37 return *first <= v && v <= *second;
39 const llvm::APSInt &From()
const {
return *first; }
40 const llvm::APSInt &To()
const {
return *second; }
41 const llvm::APSInt *getConcreteValue()
const {
42 return &From() == &To() ? &From() : nullptr;
45 void Profile(llvm::FoldingSetNodeID &
ID)
const {
46 ID.AddPointer(&From());
51 class RangeTrait :
public llvm::ImutContainerInfo<Range> {
57 static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
58 return *lhs.first < *rhs.first ||
59 (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second);
72 typedef PrimRangeSet::Factory Factory;
73 typedef PrimRangeSet::iterator iterator;
75 RangeSet(PrimRangeSet RS) : ranges(RS) {}
79 RangeSet addRange(Factory &F,
const RangeSet &RS) {
80 PrimRangeSet Ranges(RS.ranges);
81 for (
const auto &range : ranges)
82 Ranges = F.add(Ranges, range);
83 return RangeSet(Ranges);
86 iterator begin()
const {
return ranges.begin(); }
87 iterator end()
const {
return ranges.end(); }
89 bool isEmpty()
const {
return ranges.isEmpty(); }
92 RangeSet(Factory &F,
const llvm::APSInt &from,
const llvm::APSInt &to)
93 : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
97 void Profile(llvm::FoldingSetNodeID &ID)
const { ranges.Profile(ID); }
102 const llvm::APSInt *getConcreteValue()
const {
103 return ranges.isSingleton() ? ranges.begin()->getConcreteValue() :
nullptr;
108 const llvm::APSInt &Lower,
const llvm::APSInt &Upper,
109 PrimRangeSet &newRanges, PrimRangeSet::iterator &i,
110 PrimRangeSet::iterator &e)
const {
119 for (; i != e; ++i) {
120 if (i->To() < Lower) {
123 if (i->From() > Upper) {
127 if (i->Includes(Lower)) {
128 if (i->Includes(Upper)) {
130 F.add(newRanges, Range(BV.getValue(Lower), BV.getValue(Upper)));
133 newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
135 if (i->Includes(Upper)) {
136 newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
139 newRanges = F.add(newRanges, *i);
144 const llvm::APSInt &getMinValue()
const {
146 return ranges.begin()->From();
149 bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper)
const {
169 Lower =
Type.getMinValue();
170 Upper =
Type.getMaxValue();
174 Lower =
Type.getMinValue();
179 Lower =
Type.getMinValue();
180 Upper =
Type.getMaxValue();
189 Upper =
Type.getMaxValue();
199 Upper =
Type.getMaxValue();
210 Lower =
Type.getMinValue();
220 Lower =
Type.getMinValue();
221 Upper =
Type.getMaxValue();
239 llvm::APSInt Upper)
const {
240 if (!pin(Lower, Upper))
241 return F.getEmptySet();
243 PrimRangeSet newRanges = F.getEmptySet();
245 PrimRangeSet::iterator i = begin(), e = end();
247 IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
252 IntersectInRange(BV, F, BV.
getMinValue(Upper), Upper, newRanges, i, e);
253 IntersectInRange(BV, F, Lower, BV.
getMaxValue(Lower), newRanges, i, e);
259 void print(raw_ostream &os)
const {
262 for (iterator i = begin(), e = end(); i != e; ++i) {
268 os <<
'[' << i->From().toString(10) <<
", " << i->To().toString(10)
274 bool operator==(
const RangeSet &other)
const {
275 return ranges == other.ranges;
294 bool canReasonAbout(
SVal X)
const override;
305 const char *sep)
override;
312 const llvm::APSInt &V,
313 const llvm::APSInt &Adjustment)
override;
316 const llvm::APSInt &V,
317 const llvm::APSInt &Adjustment)
override;
320 const llvm::APSInt &V,
321 const llvm::APSInt &Adjustment)
override;
324 const llvm::APSInt &V,
325 const llvm::APSInt &Adjustment)
override;
328 const llvm::APSInt &V,
329 const llvm::APSInt &Adjustment)
override;
332 const llvm::APSInt &V,
333 const llvm::APSInt &Adjustment)
override;
337 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
341 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
349 const llvm::APSInt &Int,
350 const llvm::APSInt &Adjustment);
352 const llvm::APSInt &Int,
353 const llvm::APSInt &Adjustment);
355 const llvm::APSInt &Int,
356 const llvm::APSInt &Adjustment);
357 RangeSet getSymLERange(
const RangeSet &RS,
const llvm::APSInt &Int,
358 const llvm::APSInt &Adjustment);
360 const llvm::APSInt &Int,
361 const llvm::APSInt &Adjustment);
366 std::unique_ptr<ConstraintManager>
368 return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
371 bool RangeConstraintManager::canReasonAbout(
SVal X)
const {
373 if (SymVal && SymVal->isExpression()) {
374 const SymExpr *SE = SymVal->getSymbol();
376 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
377 switch (SIE->getOpcode()) {
397 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
415 const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
422 if (
const llvm::APSInt *
Value = Ranges->getConcreteValue())
430 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
437 const llvm::APSInt *RangeConstraintManager::getSymVal(
ProgramStateRef St,
439 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(Sym);
440 return T ? T->getConcreteValue() :
nullptr;
448 bool Changed =
false;
449 ConstraintRangeTy CR = State->get<ConstraintRange>();
450 ConstraintRangeTy::Factory &CRFactory = State->get_context<ConstraintRange>();
452 for (ConstraintRangeTy::iterator
I = CR.begin(),
E = CR.end();
I !=
E; ++
I) {
456 CR = CRFactory.remove(CR, Sym);
460 return Changed ? State->set<ConstraintRange>(CR) : State;
465 if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
499 const llvm::APSInt &Int,
500 const llvm::APSInt &Adjustment) {
506 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment;
507 llvm::APSInt Upper = Lower;
513 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
514 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
519 const llvm::APSInt &Int,
520 const llvm::APSInt &Adjustment) {
527 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
528 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
529 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
534 const llvm::APSInt &Int,
535 const llvm::APSInt &Adjustment) {
538 switch (AdjustmentType.testInRange(Int,
true)) {
540 return F.getEmptySet();
544 return getRange(St, Sym);
548 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
549 llvm::APSInt Min = AdjustmentType.getMinValue();
550 if (ComparisonVal == Min)
551 return F.getEmptySet();
553 llvm::APSInt Lower = Min - Adjustment;
554 llvm::APSInt Upper = ComparisonVal - Adjustment;
557 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
562 const llvm::APSInt &Int,
563 const llvm::APSInt &Adjustment) {
564 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
565 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
570 const llvm::APSInt &Int,
571 const llvm::APSInt &Adjustment) {
574 switch (AdjustmentType.testInRange(Int,
true)) {
576 return getRange(St, Sym);
580 return F.getEmptySet();
584 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
585 llvm::APSInt Max = AdjustmentType.getMaxValue();
586 if (ComparisonVal == Max)
587 return F.getEmptySet();
589 llvm::APSInt Lower = ComparisonVal - Adjustment;
590 llvm::APSInt Upper = Max - Adjustment;
593 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
598 const llvm::APSInt &Int,
599 const llvm::APSInt &Adjustment) {
600 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
601 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
606 const llvm::APSInt &Int,
607 const llvm::APSInt &Adjustment) {
610 switch (AdjustmentType.testInRange(Int,
true)) {
612 return getRange(St, Sym);
616 return F.getEmptySet();
620 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
621 llvm::APSInt Min = AdjustmentType.getMinValue();
622 if (ComparisonVal == Min)
623 return getRange(St, Sym);
625 llvm::APSInt Max = AdjustmentType.getMaxValue();
626 llvm::APSInt Lower = ComparisonVal - Adjustment;
627 llvm::APSInt Upper = Max - Adjustment;
629 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
634 const llvm::APSInt &Int,
635 const llvm::APSInt &Adjustment) {
636 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
637 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
640 RangeSet RangeConstraintManager::getSymLERange(
const RangeSet &RS,
641 const llvm::APSInt &Int,
642 const llvm::APSInt &Adjustment) {
645 switch (AdjustmentType.testInRange(Int,
true)) {
647 return F.getEmptySet();
655 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
656 llvm::APSInt Max = AdjustmentType.getMaxValue();
657 if (ComparisonVal == Max)
660 llvm::APSInt Min = AdjustmentType.getMinValue();
661 llvm::APSInt Lower = Min - Adjustment;
662 llvm::APSInt Upper = ComparisonVal - Adjustment;
664 return RS.Intersect(getBasicVals(), F, Lower, Upper);
669 const llvm::APSInt &Int,
670 const llvm::APSInt &Adjustment) {
673 switch (AdjustmentType.testInRange(Int,
true)) {
675 return F.getEmptySet();
679 return getRange(St, Sym);
683 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
684 llvm::APSInt Max = AdjustmentType.getMaxValue();
685 if (ComparisonVal == Max)
686 return getRange(St, Sym);
688 llvm::APSInt Min = AdjustmentType.getMinValue();
689 llvm::APSInt Lower = Min - Adjustment;
690 llvm::APSInt Upper = ComparisonVal - Adjustment;
692 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
697 const llvm::APSInt &Int,
698 const llvm::APSInt &Adjustment) {
699 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
700 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
705 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
706 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
709 New = getSymLERange(New, To, Adjustment);
710 return New.isEmpty() ?
nullptr : State->set<ConstraintRange>(Sym, New);
713 ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
715 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
716 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
717 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
718 RangeSet New(RangeLT.addRange(F, RangeGT));
719 return New.isEmpty() ?
nullptr : State->set<ConstraintRange>(Sym, New);
726 void RangeConstraintManager::print(
ProgramStateRef St, raw_ostream &Out,
727 const char *nl,
const char *sep) {
729 ConstraintRangeTy Ranges = St->get<ConstraintRange>();
731 if (Ranges.isEmpty()) {
732 Out << nl << sep <<
"Ranges are empty." << nl;
736 Out << nl << sep <<
"Ranges of symbol values:";
737 for (ConstraintRangeTy::iterator
I = Ranges.begin(),
E = Ranges.end();
I !=
E;
739 Out << nl <<
' ' <<
I.getKey() <<
" : ";
740 I.getData().print(Out);
A (possibly-)qualified type.
Value is less than the minimum representable value.
bool operator==(CanQual< T > x, CanQual< U > y)
bool maybeDead(SymbolRef sym)
If a symbol is known to be live, marks the symbol as live.
std::unique_ptr< ConstraintManager > CreateRangeConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine)
The base class of the type hierarchy.
bool isComparisonOp() const
bool isReferenceType() const
SValBuilder & getSValBuilder()
static bool isLocType(QualType T)
Value is representable using this type.
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
detail::InMemoryDirectory::const_iterator I
llvm::APSInt getZeroValue() const LLVM_READONLY
Returns an all-zero value for this type.
virtual QualType getType() const =0
REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange, CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, RangeSet)) namespace
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
#define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)
Helper for registering a map trait.
A class responsible for cleaning up unused symbols.
Value is greater than the maximum representable value.
RangeTestResultKind
Used to classify whether a value is representable using this type.
Represents symbolic expression.
detail::InMemoryDirectory::const_iterator E
const llvm::APSInt & getMinValue(const llvm::APSInt &v)
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
Represents a symbolic expression like 'x' + 'y'.