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;
82 RangeSet(PrimRangeSet RS) : ranges(RS) {}
86 RangeSet addRange(Factory &F,
const RangeSet &RS) {
87 PrimRangeSet Ranges(RS.ranges);
88 for (
const auto &range : ranges)
89 Ranges = F.add(Ranges, range);
90 return RangeSet(Ranges);
96 bool isEmpty()
const {
return ranges.isEmpty(); }
99 RangeSet(Factory &F,
const llvm::APSInt &from,
const llvm::APSInt &to)
100 : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
104 void Profile(llvm::FoldingSetNodeID &ID)
const { ranges.Profile(ID); }
109 const llvm::APSInt* getConcreteValue()
const {
110 return ranges.isSingleton() ? ranges.begin()->getConcreteValue() :
nullptr;
115 const llvm::APSInt &Lower,
116 const llvm::APSInt &Upper,
117 PrimRangeSet &newRanges,
128 for (; i != e; ++i) {
129 if (i->To() < Lower) {
132 if (i->From() > Upper) {
136 if (i->Includes(Lower)) {
137 if (i->Includes(Upper)) {
138 newRanges = F.add(newRanges, Range(BV.getValue(Lower),
139 BV.getValue(Upper)));
142 newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
144 if (i->Includes(Upper)) {
145 newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
148 newRanges = F.add(newRanges, *i);
153 const llvm::APSInt &getMinValue()
const {
155 return ranges.begin()->From();
158 bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper)
const {
178 Lower =
Type.getMinValue();
179 Upper =
Type.getMaxValue();
183 Lower =
Type.getMinValue();
188 Lower =
Type.getMinValue();
189 Upper =
Type.getMaxValue();
198 Upper =
Type.getMaxValue();
208 Upper =
Type.getMaxValue();
219 Lower =
Type.getMinValue();
229 Lower =
Type.getMinValue();
230 Upper =
Type.getMaxValue();
248 llvm::APSInt Lower, llvm::APSInt Upper)
const {
249 if (!pin(Lower, Upper))
250 return F.getEmptySet();
252 PrimRangeSet newRanges = F.getEmptySet();
256 IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
261 IntersectInRange(BV, F, BV.
getMinValue(Upper), Upper, newRanges, i, e);
262 IntersectInRange(BV, F, Lower, BV.
getMaxValue(Lower), newRanges, i, e);
268 void print(raw_ostream &os)
const {
277 os <<
'[' << i->From().toString(10) <<
", " << i->To().toString(10)
283 bool operator==(
const RangeSet &other)
const {
284 return ranges == other.ranges;
301 const llvm::APSInt& Int,
302 const llvm::APSInt& Adjustment)
override;
305 const llvm::APSInt& Int,
306 const llvm::APSInt& Adjustment)
override;
309 const llvm::APSInt& Int,
310 const llvm::APSInt& Adjustment)
override;
313 const llvm::APSInt& Int,
314 const llvm::APSInt& Adjustment)
override;
317 const llvm::APSInt& Int,
318 const llvm::APSInt& Adjustment)
override;
321 const llvm::APSInt& Int,
322 const llvm::APSInt& Adjustment)
override;
326 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
330 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
340 const char* nl,
const char *sep)
override;
345 const llvm::APSInt &Int,
346 const llvm::APSInt &Adjustment);
348 const llvm::APSInt &Int,
349 const llvm::APSInt &Adjustment);
351 const llvm::APSInt &Int,
352 const llvm::APSInt &Adjustment);
353 RangeSet getSymLERange(
const RangeSet &RS,
const llvm::APSInt &Int,
354 const llvm::APSInt &Adjustment);
356 const llvm::APSInt &Int,
357 const llvm::APSInt &Adjustment);
362 std::unique_ptr<ConstraintManager>
364 return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
367 const llvm::APSInt* RangeConstraintManager::getSymVal(
ProgramStateRef St,
369 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
370 return T ? T->getConcreteValue() :
nullptr;
375 const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
382 if (
const llvm::APSInt *
Value = Ranges->getConcreteValue())
390 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
403 ConstraintRangeTy CR = state->get<ConstraintRange>();
404 ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
409 CR = CRFactory.remove(CR, sym);
412 return state->set<ConstraintRange>(CR);
417 if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
451 const llvm::APSInt &Int,
452 const llvm::APSInt &Adjustment) {
458 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment;
459 llvm::APSInt Upper = Lower;
465 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
466 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
471 const llvm::APSInt &Int,
472 const llvm::APSInt &Adjustment) {
479 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
480 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
481 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
486 const llvm::APSInt &Int,
487 const llvm::APSInt &Adjustment) {
490 switch (AdjustmentType.testInRange(Int,
true)) {
492 return F.getEmptySet();
496 return GetRange(St, Sym);
500 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
501 llvm::APSInt Min = AdjustmentType.getMinValue();
502 if (ComparisonVal == Min)
503 return F.getEmptySet();
505 llvm::APSInt Lower = Min - Adjustment;
506 llvm::APSInt Upper = ComparisonVal - Adjustment;
509 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
514 const llvm::APSInt &Int,
515 const llvm::APSInt &Adjustment) {
516 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
517 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
522 const llvm::APSInt &Int,
523 const llvm::APSInt &Adjustment) {
526 switch (AdjustmentType.testInRange(Int,
true)) {
528 return GetRange(St, Sym);
532 return F.getEmptySet();
536 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
537 llvm::APSInt Max = AdjustmentType.getMaxValue();
538 if (ComparisonVal == Max)
539 return F.getEmptySet();
541 llvm::APSInt Lower = ComparisonVal - Adjustment;
542 llvm::APSInt Upper = Max - Adjustment;
545 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
550 const llvm::APSInt &Int,
551 const llvm::APSInt &Adjustment) {
552 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
553 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
558 const llvm::APSInt &Int,
559 const llvm::APSInt &Adjustment) {
562 switch (AdjustmentType.testInRange(Int,
true)) {
564 return GetRange(St, Sym);
568 return F.getEmptySet();
572 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
573 llvm::APSInt Min = AdjustmentType.getMinValue();
574 if (ComparisonVal == Min)
575 return GetRange(St, Sym);
577 llvm::APSInt Max = AdjustmentType.getMaxValue();
578 llvm::APSInt Lower = ComparisonVal - Adjustment;
579 llvm::APSInt Upper = Max - Adjustment;
581 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
586 const llvm::APSInt &Int,
587 const llvm::APSInt &Adjustment) {
588 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
589 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
593 RangeConstraintManager::getSymLERange(
const RangeSet &RS,
594 const llvm::APSInt &Int,
595 const llvm::APSInt &Adjustment) {
598 switch (AdjustmentType.testInRange(Int,
true)) {
600 return F.getEmptySet();
608 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
609 llvm::APSInt Max = AdjustmentType.getMaxValue();
610 if (ComparisonVal == Max)
613 llvm::APSInt Min = AdjustmentType.getMinValue();
614 llvm::APSInt Lower = Min - Adjustment;
615 llvm::APSInt Upper = ComparisonVal - Adjustment;
617 return RS.Intersect(getBasicVals(), F, Lower, Upper);
622 const llvm::APSInt &Int,
623 const llvm::APSInt &Adjustment) {
626 switch (AdjustmentType.testInRange(Int,
true)) {
628 return F.getEmptySet();
632 return GetRange(St, Sym);
636 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
637 llvm::APSInt Max = AdjustmentType.getMaxValue();
638 if (ComparisonVal == Max)
639 return GetRange(St, Sym);
641 llvm::APSInt Min = AdjustmentType.getMinValue();
642 llvm::APSInt Lower = Min - Adjustment;
643 llvm::APSInt Upper = ComparisonVal - Adjustment;
645 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
650 const llvm::APSInt &Int,
651 const llvm::APSInt &Adjustment) {
652 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
653 return New.isEmpty() ?
nullptr : St->set<ConstraintRange>(Sym, New);
657 RangeConstraintManager::assumeSymbolWithinInclusiveRange(
659 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
660 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
663 New = getSymLERange(New, To, Adjustment);
664 return New.isEmpty() ?
nullptr : State->set<ConstraintRange>(Sym, New);
668 RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
670 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
671 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
672 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
673 RangeSet New(RangeLT.addRange(F, RangeGT));
674 return New.isEmpty() ?
nullptr : State->set<ConstraintRange>(Sym, New);
681 void RangeConstraintManager::print(
ProgramStateRef St, raw_ostream &Out,
682 const char* nl,
const char *sep) {
684 ConstraintRangeTy Ranges = St->get<ConstraintRange>();
686 if (Ranges.isEmpty()) {
687 Out << nl << sep <<
"Ranges are empty." << nl;
691 Out << nl << sep <<
"Ranges of symbol values:";
693 Out << nl <<
' ' <<
I.getKey() <<
" : ";
694 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 isReferenceType() const
SValBuilder & getSValBuilder()
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
Value is representable using this type.
A record of the "type" of an APSInt, used for conversions.
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
The result type of a method or function.
const TemplateArgument * iterator
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
#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 a template argument.
detail::InMemoryDirectory::const_iterator E
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.