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(llvm::function_ref<RangeSet()> RS,
358 const llvm::APSInt &Int,
359 const llvm::APSInt &Adjustment);
361 const llvm::APSInt &Int,
362 const llvm::APSInt &Adjustment);
367 std::unique_ptr<ConstraintManager>
369 return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
372 bool RangeConstraintManager::canReasonAbout(
SVal X)
const {
374 if (SymVal && SymVal->isExpression()) {
375 const SymExpr *SE = SymVal->getSymbol();
377 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
378 switch (SIE->getOpcode()) {
398 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
418 const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
425 if (
const llvm::APSInt *
Value = Ranges->getConcreteValue())
433 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
440 const llvm::APSInt *RangeConstraintManager::getSymVal(
ProgramStateRef St,
442 const ConstraintRangeTy::data_type *
T = St->get<ConstraintRange>(Sym);
443 return T ? T->getConcreteValue() :
nullptr;
451 bool Changed =
false;
452 ConstraintRangeTy CR = State->get<ConstraintRange>();
453 ConstraintRangeTy::Factory &CRFactory = State->get_context<ConstraintRange>();
455 for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
459 CR = CRFactory.remove(CR, Sym);
463 return Changed ? State->set<ConstraintRange>(CR) : State;
469 RangeSet::Factory &F,
473 return Domain.Intersect(BV, F, ++IntType.
getZeroValue(),
487 RangeSet::Factory &F,
492 const llvm::APSInt &RHS = SIE->
getRHS();
497 if (Operator == BO_Or && IsUnsigned)
498 return Input.Intersect(BV, F, RHS, BV.
getMaxValue(T));
501 if (Operator == BO_Or && RHS != Zero)
507 if (Operator == BO_And && (IsUnsigned || RHS >= Zero))
508 return Input.Intersect(BV, F, BV.
getMinValue(T), RHS);
515 if (ConstraintRangeTy::data_type *V = State->get<ConstraintRange>(Sym))
530 if (
const SymIntExpr* SIE = dyn_cast<SymIntExpr>(Sym))
550 const llvm::APSInt &Int,
551 const llvm::APSInt &Adjustment) {
557 llvm::APSInt Lower = AdjustmentType.
convert(Int) - Adjustment;
558 llvm::APSInt Upper = Lower;
564 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
565 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
570 const llvm::APSInt &Int,
571 const llvm::APSInt &Adjustment) {
578 llvm::APSInt AdjInt = AdjustmentType.
convert(Int) - Adjustment;
579 RangeSet New = getRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
580 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
585 const llvm::APSInt &Int,
586 const llvm::APSInt &Adjustment) {
591 return F.getEmptySet();
595 return getRange(St, Sym);
599 llvm::APSInt ComparisonVal = AdjustmentType.
convert(Int);
601 if (ComparisonVal == Min)
602 return F.getEmptySet();
604 llvm::APSInt Lower = Min - Adjustment;
605 llvm::APSInt Upper = ComparisonVal - Adjustment;
608 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
613 const llvm::APSInt &Int,
614 const llvm::APSInt &Adjustment) {
615 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
616 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
621 const llvm::APSInt &Int,
622 const llvm::APSInt &Adjustment) {
627 return getRange(St, Sym);
631 return F.getEmptySet();
635 llvm::APSInt ComparisonVal = AdjustmentType.
convert(Int);
637 if (ComparisonVal == Max)
638 return F.getEmptySet();
640 llvm::APSInt Lower = ComparisonVal - Adjustment;
641 llvm::APSInt Upper = Max - Adjustment;
644 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
649 const llvm::APSInt &Int,
650 const llvm::APSInt &Adjustment) {
651 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
652 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
657 const llvm::APSInt &Int,
658 const llvm::APSInt &Adjustment) {
663 return getRange(St, Sym);
667 return F.getEmptySet();
671 llvm::APSInt ComparisonVal = AdjustmentType.
convert(Int);
673 if (ComparisonVal == Min)
674 return getRange(St, Sym);
677 llvm::APSInt Lower = ComparisonVal - Adjustment;
678 llvm::APSInt Upper = Max - Adjustment;
680 return getRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
685 const llvm::APSInt &Int,
686 const llvm::APSInt &Adjustment) {
687 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
688 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
691 RangeSet RangeConstraintManager::getSymLERange(
692 llvm::function_ref<RangeSet()> RS,
693 const llvm::APSInt &Int,
694 const llvm::APSInt &Adjustment) {
699 return F.getEmptySet();
707 llvm::APSInt ComparisonVal = AdjustmentType.
convert(Int);
709 if (ComparisonVal == Max)
713 llvm::APSInt Lower = Min - Adjustment;
714 llvm::APSInt Upper = ComparisonVal - Adjustment;
716 return RS().Intersect(getBasicVals(), F, Lower, Upper);
721 const llvm::APSInt &Int,
722 const llvm::APSInt &Adjustment) {
723 return getSymLERange([&] {
return getRange(St, Sym); }, Int, Adjustment);
728 const llvm::APSInt &Int,
729 const llvm::APSInt &Adjustment) {
730 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
731 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
736 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
737 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
740 RangeSet Out = getSymLERange([&] {
return New; }, To, Adjustment);
741 return Out.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, Out);
744 ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
746 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
747 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
748 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
749 RangeSet New(RangeLT.addRange(F, RangeGT));
750 return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
757 void RangeConstraintManager::print(
ProgramStateRef St, raw_ostream &Out,
758 const char *nl,
const char *sep) {
760 ConstraintRangeTy Ranges = St->get<ConstraintRange>();
762 if (Ranges.isEmpty()) {
763 Out << nl << sep <<
"Ranges are empty." << nl;
767 Out << nl << sep <<
"Ranges of symbol values:";
768 for (ConstraintRangeTy::iterator I = Ranges.begin(), E = Ranges.end(); I != E;
770 Out << nl <<
' ' << I.getKey() <<
" : ";
771 I.getData().print(Out);
A (possibly-)qualified type.
Value is less than the minimum representable value.
bool operator==(CanQual< T > x, CanQual< U > y)
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
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 isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isEqualityOp() 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.
bool isRelationalOp() const
RangeTestResultKind testInRange(const llvm::APSInt &Val, bool AllowMixedSign) const LLVM_READONLY
Tests whether a given value is losslessly representable using this type.
llvm::APSInt getZeroValue() const LLVM_READONLY
Returns an all-zero value for this type.
virtual QualType getType() const =0
llvm::APSInt getMinValue() const LLVM_READONLY
Returns the minimum value for this type.
const FunctionProtoType * T
REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange, CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, RangeSet)) namespace
static RangeSet assumeNonZero(BasicValueFactory &BV, RangeSet::Factory &F, SymbolRef Sym, RangeSet Domain)
Return a range set subtracting zero from Domain.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
llvm::APSInt getMaxValue() const LLVM_READONLY
Returns the maximum value for this 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.
QualType getType() const override
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.
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Convert and return a new APSInt with the given value, but this type's bit width and signedness...
Dataflow Directional Tag Classes.
const llvm::APSInt & getRHS() const
Represents symbolic expression.
const llvm::APSInt & getMinValue(const llvm::APSInt &v)
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
static RangeSet applyBitwiseConstraints(BasicValueFactory &BV, RangeSet::Factory &F, RangeSet Input, const SymIntExpr *SIE)
Apply implicit constraints for bitwise OR- and AND-.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
BinaryOperator::Opcode getOpcode() const
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
Represents a symbolic expression like 'x' + 'y'.