19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/ImmutableSet.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/raw_ostream.h"
24 using namespace clang;
31 class Range :
public std::pair<const llvm::APSInt*,
32 const llvm::APSInt*> {
34 Range(
const llvm::APSInt &from,
const llvm::APSInt &to)
35 : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) {
38 bool Includes(
const llvm::APSInt &
v)
const {
39 return *first <= v && v <= *second;
41 const llvm::APSInt &From()
const {
44 const llvm::APSInt &To()
const {
47 const llvm::APSInt *getConcreteValue()
const {
48 return &From() == &To() ? &From() : nullptr;
51 void Profile(llvm::FoldingSetNodeID &
ID)
const {
52 ID.AddPointer(&From());
58 class RangeTrait :
public llvm::ImutContainerInfo<Range> {
64 static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
65 return *lhs.first < *rhs.first || (!(*rhs.first < *lhs.first) &&
66 *lhs.second < *rhs.second);
79 typedef PrimRangeSet::Factory Factory;
80 typedef PrimRangeSet::iterator iterator;
82 RangeSet(PrimRangeSet RS) : ranges(RS) {}
84 iterator begin()
const {
return ranges.begin(); }
85 iterator end()
const {
return ranges.end(); }
87 bool isEmpty()
const {
return ranges.isEmpty(); }
90 RangeSet(Factory &F,
const llvm::APSInt &from,
const llvm::APSInt &to)
91 : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
95 void Profile(llvm::FoldingSetNodeID &ID)
const { ranges.Profile(ID); }
100 const llvm::APSInt* getConcreteValue()
const {
101 return ranges.isSingleton() ? ranges.begin()->getConcreteValue() :
nullptr;
106 const llvm::APSInt &Lower,
107 const llvm::APSInt &Upper,
108 PrimRangeSet &newRanges,
109 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)) {
129 newRanges = F.add(newRanges, Range(BV.getValue(Lower),
130 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 Lower, 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;
292 const llvm::APSInt& Int,
293 const llvm::APSInt& Adjustment)
override;
296 const llvm::APSInt& Int,
297 const llvm::APSInt& Adjustment)
override;
300 const llvm::APSInt& Int,
301 const llvm::APSInt& Adjustment)
override;
304 const llvm::APSInt& Int,
305 const llvm::APSInt& Adjustment)
override;
308 const llvm::APSInt& Int,
309 const llvm::APSInt& Adjustment)
override;
312 const llvm::APSInt& Int,
313 const llvm::APSInt& Adjustment)
override;
323 const char* nl,
const char *sep)
override;
331 std::unique_ptr<ConstraintManager>
333 return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
336 const llvm::APSInt* RangeConstraintManager::getSymVal(
ProgramStateRef St,
338 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
339 return T ? T->getConcreteValue() :
nullptr;
344 const RangeSet *
Ranges = State->get<ConstraintRange>(Sym);
351 if (
const llvm::APSInt *
Value = Ranges->getConcreteValue())
359 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
372 ConstraintRangeTy CR = state->get<ConstraintRange>();
373 ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
375 for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
378 CR = CRFactory.remove(CR, sym);
381 return state->set<ConstraintRange>(CR);
386 if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
420 const llvm::APSInt &Int,
421 const llvm::APSInt &Adjustment) {
427 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment;
428 llvm::APSInt Upper = Lower;
434 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
435 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
440 const llvm::APSInt &Int,
441 const llvm::APSInt &Adjustment) {
448 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
449 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
450 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
455 const llvm::APSInt &Int,
456 const llvm::APSInt &Adjustment) {
459 switch (AdjustmentType.testInRange(Int,
true)) {
469 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
470 llvm::APSInt Min = AdjustmentType.getMinValue();
471 if (ComparisonVal == Min)
474 llvm::APSInt Lower = Min-Adjustment;
475 llvm::APSInt Upper = ComparisonVal-Adjustment;
478 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
479 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
484 const llvm::APSInt &Int,
485 const llvm::APSInt &Adjustment) {
488 switch (AdjustmentType.testInRange(Int,
true)) {
498 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
499 llvm::APSInt Max = AdjustmentType.getMaxValue();
500 if (ComparisonVal == Max)
503 llvm::APSInt Lower = ComparisonVal-Adjustment;
504 llvm::APSInt Upper = Max-Adjustment;
507 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
508 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
513 const llvm::APSInt &Int,
514 const llvm::APSInt &Adjustment) {
517 switch (AdjustmentType.testInRange(Int,
true)) {
527 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
528 llvm::APSInt Min = AdjustmentType.getMinValue();
529 if (ComparisonVal == Min)
532 llvm::APSInt Max = AdjustmentType.getMaxValue();
533 llvm::APSInt Lower = ComparisonVal-Adjustment;
534 llvm::APSInt Upper = Max-Adjustment;
536 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
537 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
542 const llvm::APSInt &Int,
543 const llvm::APSInt &Adjustment) {
546 switch (AdjustmentType.testInRange(Int,
true)) {
556 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
557 llvm::APSInt Max = AdjustmentType.getMaxValue();
558 if (ComparisonVal == Max)
561 llvm::APSInt Min = AdjustmentType.getMinValue();
562 llvm::APSInt Lower = Min-Adjustment;
563 llvm::APSInt Upper = ComparisonVal-Adjustment;
565 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
566 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
573 void RangeConstraintManager::print(
ProgramStateRef St, raw_ostream &Out,
574 const char* nl,
const char *sep) {
576 ConstraintRangeTy Ranges = St->get<ConstraintRange>();
578 if (Ranges.isEmpty()) {
579 Out << nl << sep <<
"Ranges are empty." << nl;
583 Out << nl << sep <<
"Ranges of symbol values:";
584 for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){
585 Out << nl <<
' ' << I.getKey() <<
" : ";
586 I.getData().print(Out);
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)
Symbolic value. These values used to capture symbolic execution of the program.
bool isReferenceType() const
SValBuilder & getSValBuilder()
Value is representable using this type.
A record of the "type" of an APSInt, used for conversions.
llvm::APSInt getZeroValue() const LLVM_READONLY
Returns an all-zero value for this type.
virtual QualType getType() const =0
ID
Defines the set of possible language-specific address spaces.
REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange, CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, RangeSet)) namespace
The result type of a method or function.
#define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)
A class responsible for cleaning up unused symbols.
Value is greater than the maximum representable value.
const llvm::APSInt & getMinValue(const llvm::APSInt &v)
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.