;
37 static_assert(BO_LT < BO_GT && BO_GT < BO_LE && BO_LE < BO_GE &&
38BO_GE < BO_EQ && BO_EQ < BO_NE,
39 "This class relies on operators order. Rework it otherwise.");
76 static constexpr size_tCmpOpCount = BO_NE - BO_LT + 1;
77 const TriStateKindCmpOpTable[CmpOpCount][CmpOpCount + 1] = {
88 return static_cast<size_t>(OP - BO_LT);
100 returnCmpOpTable[getIndexFromOp(CurrentOP)][getIndexFromOp(QueriedOP)];
104 returnCmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
112RangeSet::ContainerType RangeSet::Factory::EmptySet{};
118std::back_inserter(
Result));
119 returnmakePersistent(std::move(
Result));
124 Result.reserve(Original.size() + 1);
127 Result.insert(
Result.end(), Original.begin(), Lower);
128 Result.push_back(Element);
131 returnmakePersistent(std::move(
Result));
135 returnadd(Original,
Range(Point));
139ContainerType
Result= unite(*LHS.Impl, *RHS.Impl);
140 returnmakePersistent(std::move(
Result));
147 returnmakePersistent(std::move(
Result));
151 returnunite(Original,
Range(ValueFactory.getValue(Point)));
156 returnunite(Original,
157 Range(ValueFactory.getValue(From), ValueFactory.getValue(To)));
160template<
typenameT>
162std::swap(
First, Second);
163std::swap(FirstEnd, SecondEnd);
167 constContainerType &RHS) {
174 usingiterator = ContainerType::const_iterator;
176iterator
First= LHS.begin();
177iterator FirstEnd = LHS.end();
178iterator Second = RHS.begin();
179iterator SecondEnd = RHS.end();
187 if(
Min==
First->From() &&
Min== Second->From()) {
188 if(
First->To() > Second->To()) {
195 if(++Second == SecondEnd)
209 if(++
First== FirstEnd)
224 const autoAppendTheRest = [&
Result](iterator I, iterator
E) {
233 if(
First->From() > Second->From())
241 constllvm::APSInt &UnionStart =
First->From();
248 while(
First->To() >= Second->To()) {
250 if(++Second == SecondEnd) {
260 returnAppendTheRest(++
First, FirstEnd);
269 if(
First->To() < Second->From() - One)
277 if(++
First== FirstEnd) {
283 Result.emplace_back(UnionStart, Second->To());
287 returnAppendTheRest(++Second, SecondEnd);
308 if(++
First== FirstEnd)
312 returnAppendTheRest(Second, SecondEnd);
315llvm_unreachable(
"Normally, we should not reach here");
321 returnmakePersistent(std::move(
Result));
324RangeSetRangeSet::Factory::makePersistent(ContainerType &&From) {
325llvm::FoldingSetNodeID ID;
329ContainerType *
Result=
Cache.FindNodeOrInsertPos(ID, InsertPos);
335 Result= construct(std::move(From));
342RangeSet::ContainerType *RangeSet::Factory::construct(ContainerType &&From) {
343 void*Buffer = Arena.Allocate();
344 return new(Buffer) ContainerType(std::move(From));
349 return begin()->From();
354 returnstd::prev(
end())->To();
359 return begin()->From().isUnsigned();
364 return begin()->From().getBitWidth();
372boolRangeSet::containsImpl(llvm::APSInt &Point)
const{
373 if(
isEmpty() || !pin(Point))
381 returnstd::prev(It)->Includes(Point);
384boolRangeSet::pin(llvm::APSInt &Point)
const{
393boolRangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper)
const{
413Lower =
Type.getMinValue();
414Upper =
Type.getMaxValue();
418Lower =
Type.getMinValue();
423Lower =
Type.getMinValue();
424Upper =
Type.getMaxValue();
433Upper =
Type.getMaxValue();
443Upper =
Type.getMaxValue();
454Lower =
Type.getMinValue();
464Lower =
Type.getMinValue();
465Upper =
Type.getMaxValue();
475llvm::APSInt Upper) {
476 if(What.
isEmpty() || !What.pin(Lower, Upper))
477 returngetEmptySet();
479ContainerType DummyContainer;
481 if(Lower <= Upper) {
493 returngetEmptySet();
495DummyContainer.push_back(
496 Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
506 returngetEmptySet();
508DummyContainer.push_back(
509 Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
510DummyContainer.push_back(
511 Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
514 returnintersect(*What.Impl, DummyContainer);
518 constRangeSet::ContainerType &RHS) {
520 Result.reserve(std::max(LHS.size(), RHS.size()));
523FirstEnd = LHS.end(), SecondEnd = RHS.end();
528 while(
First!= FirstEnd && Second != SecondEnd) {
533 if(Second->From() <
First->From())
544 if(Second->From() >
First->To()) {
560 constllvm::APSInt &IntersectionStart = Second->From();
565 if(Second->To() >
First->To()) {
582 Result.push_back(
Range(IntersectionStart, Second->To()));
586}
while(Second != SecondEnd);
590 returngetEmptySet();
592 returnmakePersistent(std::move(
Result));
599 returngetEmptySet();
601 returnintersect(*LHS.Impl, *RHS.Impl);
605 if(LHS.containsImpl(Point))
606 returngetRangeSet(ValueFactory.getValue(Point));
608 returngetEmptySet();
613 returngetEmptySet();
615 constllvm::APSInt SampleValue = What.
getMinValue();
616 constllvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
617 constllvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
620 Result.reserve(What.
size() + (SampleValue == MIN));
626 constllvm::APSInt &From = It->From();
627 constllvm::APSInt &To = It->To();
639 if(
Last->To() == MAX) {
643 Result.emplace_back(MIN, ValueFactory.getValue(-
Last->From()));
648 Result.emplace_back(MIN, MIN);
653 Result.emplace_back(ValueFactory.getValue(-To), MAX);
661 for(; It != End; ++It) {
663 constllvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
664 constllvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
667 Result.emplace_back(NewFrom, NewTo);
671 returnmakePersistent(std::move(
Result));
686 returnmakePersistent(truncateTo(What, Ty));
700 if(IsConversion && (!IsPromotion || !What.
isUnsigned()))
701 returnmakePersistent(convertTo(What, Ty));
703assert(IsPromotion &&
"Only promotion operation from unsigneds left.");
704 returnmakePersistent(promoteTo(What, Ty));
712RangeSet::ContainerType RangeSet::Factory::truncateTo(
RangeSetWhat,
725uint64_t CastRangeSize = APInt::getMaxValue(Ty.
getBitWidth()).getZExtValue();
726 for(
const Range&R : What) {
728 APSIntFromInt = R.From();
732uint64_t CurrentRangeSize = (ToInt - FromInt).getZExtValue();
736 if(CurrentRangeSize >= CastRangeSize) {
737Dummy.emplace_back(ValueFactory.getMinValue(Ty),
738ValueFactory.getMaxValue(Ty));
739 Result= std::move(Dummy);
745 const APSInt&PersistentFrom = ValueFactory.getValue(FromInt);
746 const APSInt&PersistentTo = ValueFactory.getValue(ToInt);
747 if(FromInt > ToInt) {
748Dummy.emplace_back(ValueFactory.getMinValue(Ty), PersistentTo);
749Dummy.emplace_back(PersistentFrom, ValueFactory.getMaxValue(Ty));
751Dummy.emplace_back(PersistentFrom, PersistentTo);
778RangeSet::ContainerType RangeSet::Factory::convertTo(
RangeSetWhat,
782 usingBounds = std::pair<const APSInt &, const APSInt &>;
783ContainerType AscendArray;
784ContainerType DescendArray;
785 autoCastRange = [Ty, &VF = ValueFactory](
const Range&R) -> Bounds {
787 APSIntFromInt = R.From();
792 return{VF.getValue(FromInt), VF.getValue(ToInt)};
796 const auto*It = What.
begin();
797 const auto*
E= What.
end();
799Bounds NewBounds = CastRange(*(It++));
801 if(NewBounds.first < LastConvertedInt) {
802DescendArray.emplace_back(NewBounds.first, NewBounds.second);
809 if(NewBounds.first > NewBounds.second) {
810DescendArray.emplace_back(ValueFactory.getMinValue(Ty), NewBounds.second);
811AscendArray.emplace_back(NewBounds.first, ValueFactory.getMaxValue(Ty));
814AscendArray.emplace_back(NewBounds.first, NewBounds.second);
815LastConvertedInt = NewBounds.first;
819Bounds NewBounds = CastRange(*(It++));
820DescendArray.emplace_back(NewBounds.first, NewBounds.second);
823 returnunite(AscendArray, DescendArray);
827RangeSet::ContainerType RangeSet::Factory::promoteTo(
RangeSetWhat,
836 for(
const Range&R : What) {
838llvm::APSInt FromInt = R.From();
839llvm::APSInt ToInt = R.To();
843 Result.emplace_back(ValueFactory.getValue(FromInt),
844ValueFactory.getValue(ToInt));
850 constllvm::APSInt &Point) {
854llvm::APSInt Upper = Point;
855llvm::APSInt Lower = Point;
861 returnintersect(From, Upper, Lower);
871llvm::interleaveComma(*
this,
OS, [&
OS](
const Range&R) { R.
dump(
OS); });
879classEquivalenceClass;
914classEquivalenceClass :
publicllvm::FoldingSetNode {
917[[nodiscard]]
static inlineEquivalenceClass find(
ProgramStateRefState,
954EquivalenceClass
First, EquivalenceClass Second);
957EquivalenceClass
Other)
const;
958[[nodiscard]]
static inlineClassSet getDisequalClasses(
ProgramStateRefState,
960[[nodiscard]]
inlineClassSet getDisequalClasses(
ProgramStateRefState)
const;
961[[nodiscard]]
inlineClassSet
962getDisequalClasses(DisequalityMapTy Map, ClassSet::Factory &Factory)
const;
964[[nodiscard]]
static inlinestd::optional<bool>
966EquivalenceClass Second);
967[[nodiscard]]
static inlinestd::optional<bool>
978EquivalenceClass Class);
982dumpToStream(State, llvm::errs());
986[[nodiscard]] LLVM_ATTRIBUTE_UNUSED
static bool 989[[nodiscard]]
QualTypegetType()
const{
990 returngetRepresentativeSymbol()->getType();
993EquivalenceClass() =
delete;
994EquivalenceClass(
constEquivalenceClass &) =
default;
995EquivalenceClass &operator=(
constEquivalenceClass &) =
delete;
996EquivalenceClass(EquivalenceClass &&) =
default;
997EquivalenceClass &operator=(EquivalenceClass &&) =
delete;
1007 static voidProfile(llvm::FoldingSetNodeID &
ID,
uintptr_tCID) {
1008 ID.AddInteger(CID);
1011 voidProfile(llvm::FoldingSetNodeID &
ID)
const{ Profile(
ID, this->ID); }
1022 SymbolRefgetRepresentativeSymbol()
const{
1025 static inlineSymbolSet::Factory &getMembersFactory(
ProgramStateRefState);
1032addToDisequalityInfo(DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
1034EquivalenceClass
First, EquivalenceClass Second);
1044[[nodiscard]] LLVM_ATTRIBUTE_UNUSED
bool 1045areFeasible(ConstraintRangeTy Constraints) {
1046 returnllvm::none_of(
1048[](
conststd::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1049 returnClassConstraint.second.isEmpty();
1054EquivalenceClass Class) {
1055 returnState->get<ConstraintRange>(
Class);
1060 returngetConstraint(State, EquivalenceClass::find(State, Sym));
1064EquivalenceClass Class,
1066 returnState->set<ConstraintRange>(
Class, Constraint);
1070ConstraintRangeTy Constraints) {
1071 returnState->set<ConstraintRange>(Constraints);
1087std::optional<bool> meansEquality(
const SymSymExpr*Sym) {
1099 returnstd::nullopt;
1107template<
classSecondTy,
class... RestTy>
1109SecondTy Second, RestTy... Tail);
1111template<
class... RangeTy>
structIntersectionTraits;
1113template<
class... TailTy>
structIntersectionTraits<
RangeSet, TailTy...> {
1118template<>
structIntersectionTraits<> {
1121 using Type= std::optional<RangeSet>;
1124template<
classOptionalOrPointer,
class... TailTy>
1125structIntersectionTraits<OptionalOrPointer, TailTy...> {
1127 using Type=
typenameIntersectionTraits<TailTy...>
::Type;
1130template<
classEndTy>
1137[[nodiscard]] LLVM_ATTRIBUTE_UNUSED
inlinestd::optional<RangeSet>
1144 returnstd::nullopt;
1147template<
class... RestTy>
1152 returnintersect(F, F.
intersect(Head, Second), Tail...);
1155template<
classSecondTy,
class... RestTy>
1157SecondTy Second, RestTy... Tail) {
1160 returnintersect(F, Head, *Second, Tail...);
1164 returnintersect(F, Head, Tail...);
1188template<
classHeadTy,
classSecondTy,
class... RestTy>
1189[[nodiscard]]
inline 1190 typenameIntersectionTraits<HeadTy, SecondTy, RestTy...>
::Type 1194 returnintersect(F, *Head, Second, Tail...);
1196 returnintersect(F, Second, Tail...);
1208classSymbolicRangeInferrer
1211 template<
classSourceType>
1213SourceType Origin) {
1214SymbolicRangeInferrer Inferrer(F, State);
1215 returnInferrer.infer(Origin);
1219 if(std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1225 returninfer(Sym->
getType());
1229 if(std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1231 returninfer(USE->
getType());
1235 returnVisitBinaryOperator(Sym);
1239 returnVisitBinaryOperator(Sym);
1251getRangeForNegatedSymSym(SSE),
1253getRangeCommutativeSymSym(SSE),
1257getRangeForComparisonSymbol(SSE),
1260getRangeForEqualities(SSE),
1262VisitBinaryOperator(SSE));
1267: ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
1274 return{RangeFactory, Val};
1287 returninfer(DestType);
1291 returnintersect(RangeFactory,
1294getConstraint(State, Sym),
1300 RangeSetinfer(EquivalenceClass Class) {
1301 if(
const RangeSet*AssociatedConstraint = getConstraint(State, Class))
1302 return*AssociatedConstraint;
1304 returninfer(
Class.getType());
1311 RangeSetResult(RangeFactory, ValueFactory.getMinValue(
T),
1312ValueFactory.getMaxValue(
T));
1316 returnassumeNonZero(Result,
T);
1321 template<
classBinarySymExprTy>
1322 RangeSetVisitBinaryOperator(
constBinarySymExprTy *Sym) {
1334 QualTypeResultType = Sym->getType();
1335 returnVisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1337inferAs(Sym->getRHS(), ResultType), ResultType);
1363 returnstd::nullopt;
1365 return Range(ValueFactory.Convert(To, Origin.
From()),
1366ValueFactory.Convert(To, Origin.
To()));
1369 template<BinaryOperator::Opcode Op>
1373 RangeCoarseLHS = fillGaps(LHS);
1374 RangeCoarseRHS = fillGaps(RHS);
1376 APSIntTypeResultType = ValueFactory.getAPSIntType(
T);
1380 autoConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1381 autoConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1385 if(!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1389 returnVisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS,
T);
1392 template<BinaryOperator::Opcode Op>
1406 APSIntTypeRangeType = ValueFactory.getAPSIntType(
T);
1409 return Range(ValueFactory.getMinValue(RangeType), Origin.
To());
1412 if(Origin.
From().isMinSignedValue()) {
1416 return{ValueFactory.getMinValue(RangeType),
1417ValueFactory.getMaxValue(RangeType)};
1431llvm::APSInt AbsMax = std::max(-Origin.
From(), Origin.
To());
1434 return{ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
1439 APSIntTypeIntType = ValueFactory.getAPSIntType(
T);
1443 template<
typenameProduceNegatedSymFunc>
1444std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1449 returnstd::nullopt;
1452 if(
const RangeSet*NegatedRange = getConstraint(State, NegatedSym))
1453 returnRangeFactory.negate(*NegatedRange);
1455 returnstd::nullopt;
1458std::optional<RangeSet> getRangeForNegatedUnarySym(
const UnarySymExpr*USE) {
1461 returngetRangeForNegatedExpr(
1470std::optional<RangeSet> getRangeForNegatedSymSym(
const SymSymExpr*SSE) {
1471 returngetRangeForNegatedExpr(
1472[SSE, State = this->State]() ->
SymbolRef{
1474 returnState->getSymbolManager().acquire<
SymSymExpr>(
1481std::optional<RangeSet> getRangeForNegatedSym(
SymbolRefSym) {
1482 returngetRangeForNegatedExpr(
1483[Sym, State = this->State]() {
1484 returnState->getSymbolManager().acquire<UnarySymExpr>(
1485Sym, UO_Minus, Sym->
getType());
1490std::optional<RangeSet> getRangeCommutativeSymSym(
const SymSymExpr*SSE) {
1492 boolIsCommutative = llvm::is_contained(
1494{BO_EQ, BO_NE, BO_Or, BO_And, BO_Add, BO_Mul, BO_Xor}, Op);
1496 returnstd::nullopt;
1500 if(
const RangeSet*
Range= getConstraint(State, Commuted))
1502 returnstd::nullopt;
1515std::optional<RangeSet> getRangeForComparisonSymbol(
const SymSymExpr*SSE) {
1520 returnstd::nullopt;
1539 for(
size_ti = 0; i < CmpOpTable.getCmpOpCount(); ++i) {
1545 const RangeSet*QueriedRangeSet = getConstraint(State, SymSym);
1549 if(!QueriedRangeSet) {
1553QueriedRangeSet = getConstraint(State, SymSym);
1556 if(!QueriedRangeSet || QueriedRangeSet->isEmpty())
1559 constllvm::APSInt *ConcreteValue = QueriedRangeSet->getConcreteValue();
1560 const boolisInFalseBranch =
1561ConcreteValue ? (*ConcreteValue == 0) :
false;
1566 if(isInFalseBranch)
1570CmpOpTable.getCmpOpState(CurrentOP, QueriedOP);
1573 if(LastQueriedOpToUnknown != CurrentOP &&
1574LastQueriedOpToUnknown != QueriedOP) {
1580BranchState = CmpOpTable.getCmpOpStateForUnknownX2(CurrentOP);
1582LastQueriedOpToUnknown = QueriedOP;
1588: getFalseRange(
T);
1591 returnstd::nullopt;
1594std::optional<RangeSet> getRangeForEqualities(
const SymSymExpr*Sym) {
1595std::optional<bool>
Equality= meansEquality(Sym);
1598 returnstd::nullopt;
1600 if(std::optional<bool> AreEqual =
1601EquivalenceClass::areEqual(State, Sym->
getLHS(), Sym->
getRHS())) {
1605 if(*AreEqual == *Equality) {
1606 returngetTrueRange(Sym->
getType());
1609 returngetFalseRange(Sym->
getType());
1612 returnstd::nullopt;
1617 returnassumeNonZero(TypeRange,
T);
1621 constllvm::APSInt &
Zero= ValueFactory.getValue(0,
T);
1622 return RangeSet(RangeFactory, Zero);
1641 if(intersect(RangeFactory, LHS, RHS).isEmpty())
1642 returngetTrueRange(
T);
1661 returngetTrueRange(
T);
1666 returngetTrueRange(
T);
1674 RangeSetCastedLHS = RangeFactory.castTo(LHS, CastingType);
1675 RangeSetCastedRHS = RangeFactory.castTo(RHS, CastingType);
1677 if(intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1678 returngetTrueRange(
T);
1688 APSIntTypeResultType = ValueFactory.getAPSIntType(
T);
1691 boolIsLHSPositiveOrZero = LHS.
From() >=
Zero;
1692 boolIsRHSPositiveOrZero = RHS.
From() >=
Zero;
1694 boolIsLHSNegative = LHS.
To() <
Zero;
1695 boolIsRHSNegative = RHS.
To() <
Zero;
1698 if((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1699(IsLHSNegative && IsRHSNegative)) {
1701 constllvm::APSInt &
Min= std::max(LHS.
From(), RHS.
From());
1714 constllvm::APSInt &
Max= IsLHSNegative
1715? ValueFactory.getValue(--Zero)
1716: ValueFactory.getMaxValue(ResultType);
1718 return{RangeFactory, ValueFactory.getValue(
Min),
Max};
1722 if(IsLHSNegative || IsRHSNegative) {
1724 return{RangeFactory, ValueFactory.getMinValue(ResultType),
1725ValueFactory.getValue(--Zero)};
1735 returnassumeNonZero(DefaultRange,
T);
1739 returnDefaultRange;
1743RangeSetSymbolicRangeInferrer::VisitBinaryOperator<BO_And>(
RangeLHS,
1746 APSIntTypeResultType = ValueFactory.getAPSIntType(
T);
1749 boolIsLHSPositiveOrZero = LHS.
From() >=
Zero;
1750 boolIsRHSPositiveOrZero = RHS.
From() >=
Zero;
1752 boolIsLHSNegative = LHS.
To() <
Zero;
1753 boolIsRHSNegative = RHS.
To() <
Zero;
1756 if((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1757(IsLHSNegative && IsRHSNegative)) {
1759 constllvm::APSInt &
Max= std::min(LHS.
To(), RHS.
To());
1763 constllvm::APSInt &
Min= IsLHSNegative
1764? ValueFactory.getMinValue(ResultType)
1765: ValueFactory.getValue(Zero);
1767 return{RangeFactory,
Min,
Max};
1771 if(IsLHSPositiveOrZero || IsRHSPositiveOrZero) {
1776 constllvm::APSInt &
Max= IsLHSPositiveOrZero ? LHS.
To() : RHS.
To();
1780 return{RangeFactory, ValueFactory.getValue(Zero),
1781ValueFactory.getValue(
Max)};
1789RangeSetSymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(
RangeLHS,
1792llvm::APSInt
Zero= ValueFactory.getAPSIntType(
T).getZeroValue();
1794 RangeConservativeRange = getSymmetricalRange(RHS,
T);
1796llvm::APSInt
Max= ConservativeRange.
To();
1797llvm::APSInt
Min= ConservativeRange.
From();
1803 returnRangeFactory.getEmptySet();
1816 if(
Min.isSigned()) {
1821 boolIsLHSPositiveOrZero = LHS.
From() >=
Zero;
1822 boolIsRHSPositiveOrZero = RHS.
From() >=
Zero;
1826 if(IsLHSPositiveOrZero && IsRHSPositiveOrZero) {
1842 return{RangeFactory, ValueFactory.getValue(
Min), ValueFactory.getValue(
Max)};
1851 returnRangeFactory.getEmptySet();
1856 returnVisitBinaryOperator<BO_NE>(LHS, RHS,
T);
1858 returnVisitBinaryOperator<BO_Or>(LHS, RHS,
T);
1860 returnVisitBinaryOperator<BO_And>(LHS, RHS,
T);
1862 returnVisitBinaryOperator<BO_Rem>(LHS, RHS,
T);
1886 returnS1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1887S1->get<ClassMap>() == S2->get<ClassMap>();
1890 boolcanReasonAbout(
SVal X)
const override;
1906 voidprintJson(raw_ostream &Out,
ProgramStateRefState,
const char*NL =
"\n",
1907 unsigned intSpace = 0,
boolIsDot =
false)
const override;
1911 const char*NL =
"\n",
unsigned intSpace = 0,
1912 boolIsDot =
false)
const;
1914 const char*NL =
"\n",
unsigned intSpace = 0,
1915 boolIsDot =
false)
const;
1917 const char*NL =
"\n",
unsigned intSpace = 0,
1918 boolIsDot =
false)
const;
1925 constllvm::APSInt &
V,
1926 constllvm::APSInt &Adjustment)
override;
1929 constllvm::APSInt &
V,
1930 constllvm::APSInt &Adjustment)
override;
1933 constllvm::APSInt &
V,
1934 constllvm::APSInt &Adjustment)
override;
1937 constllvm::APSInt &
V,
1938 constllvm::APSInt &Adjustment)
override;
1941 constllvm::APSInt &
V,
1942 constllvm::APSInt &Adjustment)
override;
1945 constllvm::APSInt &
V,
1946 constllvm::APSInt &Adjustment)
override;
1950 constllvm::APSInt &To,
constllvm::APSInt &Adjustment)
override;
1954 constllvm::APSInt &To,
constllvm::APSInt &Adjustment)
override;
1964 constllvm::APSInt &Int,
1965 constllvm::APSInt &Adjustment)
const;
1967 constllvm::APSInt &Int,
1968 constllvm::APSInt &Adjustment)
const;
1970 constllvm::APSInt &Int,
1971 constllvm::APSInt &Adjustment)
const;
1973 constllvm::APSInt &Int,
1974 constllvm::APSInt &Adjustment)
const;
1976 constllvm::APSInt &Int,
1977 constllvm::APSInt &Adjustment)
const;
1998template<
classDerived>
classConstraintAssignorBase {
2000 using Const=
constllvm::APSInt &;
2002#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint) 2004#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \ 2005 if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \ 2009assignImpl(Sym, Constraint);
2014#define SYMBOL(Id, Parent) \ 2015 case SymExpr::Id##Kind: \ 2017#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" 2019llvm_unreachable(
"Unknown SymExpr kind!");
2022#define DEFAULT_ASSIGN(Id) \ 2023 bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \ 2026 bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \ 2027 bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; } 2033#define CONSTRAINT_DISPATCH(Id) \ 2034 if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \ 2035 ASSIGN(Id, Const, Sym, *Const); \ 2037 if (Constraint.size() == 1) { \ 2038 ASSIGN(Id, Range, Sym, *Constraint.begin()); \ 2040 ASSIGN(Id, RangeSet, Sym, Constraint) 2045#define SYMBOL(Id, Parent) \ 2046 bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \ 2047 CONSTRAINT_DISPATCH(Id); \ 2051#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent) 2052#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" 2062#undef CONSTRAINT_DISPATCH 2063#undef DEFAULT_ASSIGN 2078classConstraintAssignor :
publicConstraintAssignorBase<ConstraintAssignor> {
2080 template<
classClassOrSymbol>
2083ClassOrSymbol CoS,
RangeSetNewConstraint) {
2084 if(!State || NewConstraint.
isEmpty())
2087ConstraintAssignor Assignor{State, Builder, F};
2088 returnAssignor.assign(CoS, NewConstraint);
2092 template<
typenameSymT>
2093 boolhandleRemainderOp(
constSymT *Sym,
RangeSetConstraint) {
2094 if(Sym->getOpcode() != BO_Rem)
2098 SValSymSVal = Builder.makeSymbolVal(Sym->getLHS());
2100State = State->assume(*NonLocSymSVal,
true);
2108 inline boolassignSymExprToConst(
const SymExpr*Sym, Const Constraint);
2109 inline boolassignSymIntExprToRangeSet(
const SymIntExpr*Sym,
2111 returnhandleRemainderOp(Sym, Constraint);
2113 inline boolassignSymSymExprToRangeSet(
const SymSymExpr*Sym,
2119: State(State), Builder(Builder), RangeFactory(F) {}
2120 using Base= ConstraintAssignorBase<ConstraintAssignor>;
2126State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2132Base::assign(Sym, NewConstraint);
2146ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2147ConstraintRangeTy::Factory &
CF= State->get_context<ConstraintRange>();
2150Constraints =
CF.add(Constraints, Class, NewConstraint);
2152 for(EquivalenceClass DisequalClass :
Class.getDisequalClasses(State)) {
2153 RangeSetUpdatedConstraint = SymbolicRangeInferrer::inferRange(
2154RangeFactory, State, DisequalClass);
2156UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2160 if(UpdatedConstraint.
isEmpty())
2163Constraints =
CF.add(Constraints, DisequalClass, UpdatedConstraint);
2165assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce " 2166 "a state with infeasible constraints");
2168 returnsetConstraints(State, Constraints);
2171 returnsetConstraint(State, Class, NewConstraint);
2176 returnEquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2181 returnEquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2184[[nodiscard]] std::optional<bool> interpreteAsBool(
RangeSetConstraint) {
2185assert(!Constraint.
isEmpty() &&
"Empty ranges shouldn't get here");
2193 returnstd::nullopt;
2201boolConstraintAssignor::assignSymExprToConst(
const SymExpr*Sym,
2202 constllvm::APSInt &Constraint) {
2203llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2205ClassMembersTy Members = State->get<ClassMembers>();
2206 for(std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2207EquivalenceClass
Class= ClassToSymbolSet.first;
2208State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2211SimplifiedClasses.insert(Class);
2217ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2218 for(std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2219EquivalenceClass
Class= ClassConstraint.first;
2220 if(SimplifiedClasses.count(Class))
2222State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2229DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2230 for(std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2232EquivalenceClass
Class= DisequalityEntry.first;
2233ClassSet DisequalClasses = DisequalityEntry.second;
2234State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2242boolConstraintAssignor::assignSymSymExprToRangeSet(
const SymSymExpr*Sym,
2244 if(!handleRemainderOp(Sym, Constraint))
2247std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2249 if(!ConstraintAsBool)
2252 if(std::optional<bool> Equality = meansEquality(Sym)) {
2258 if(*Equality == *ConstraintAsBool) {
2259State = trackEquality(State, Sym->
getLHS(), Sym->
getRHS());
2262State = trackDisequality(State, Sym->
getLHS(), Sym->
getRHS());
2274std::unique_ptr<ConstraintManager>
2277 returnstd::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
2281ConstraintMap::Factory &F = State->get_context<
ConstraintMap>();
2284ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2285 for(std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2286EquivalenceClass
Class= ClassConstraint.first;
2288assert(!ClassMembers.isEmpty() &&
2289 "Class must always have at least one member!");
2291 SymbolRefRepresentative = *ClassMembers.begin();
2292 Result= F.add(
Result, Representative, ClassConstraint.second);
2302LLVM_DUMP_METHOD
voidEquivalenceClass::dumpToStream(
ProgramStateRefState,
2303raw_ostream &os)
const{
2304 SymbolSetClassMembers = getClassMembers(State);
2305 for(
const SymbolRef&MemberSym : ClassMembers) {
2313assert(State &&
"State should not be null");
2314assert(Sym &&
"Symbol should not be null");
2316 if(
constEquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2317 return*NontrivialClass;
2327EquivalenceClass FirstClass = find(State,
First);
2328EquivalenceClass SecondClass = find(State, Second);
2330 returnFirstClass.merge(F, State, SecondClass);
2335EquivalenceClass
Other) {
2337 if(*
this==
Other)
2351 if(getType()->getCanonicalTypeUnqualified() !=
2352 Other.getType()->getCanonicalTypeUnqualified())
2355 SymbolSetMembers = getClassMembers(State);
2361 if(Members.getHeight() >= OtherMembers.getHeight()) {
2362 returnmergeImpl(F, State, Members,
Other, OtherMembers);
2364 return Other.mergeImpl(F, State, OtherMembers, *
this, Members);
2383ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2384ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2391 if(std::optional<RangeSet> NewClassConstraint =
2392intersect(RangeFactory, getConstraint(State, *
this),
2393getConstraint(State,
Other))) {
2399 if(NewClassConstraint->isEmpty())
2404Constraints = CRF.remove(Constraints,
Other);
2406Constraints = CRF.add(Constraints, *
this, *NewClassConstraint);
2408assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce " 2409 "a state with infeasible constraints");
2411State = State->set<ConstraintRange>(Constraints);
2415ClassMapTy Classes = State->get<ClassMap>();
2416ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2418ClassMembersTy Members = State->get<ClassMembers>();
2419ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2421DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2422DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2424ClassSet::Factory &
CF= State->get_context<ClassSet>();
2425SymbolSet::Factory &F = getMembersFactory(State);
2430NewClassMembers = F.add(NewClassMembers, Sym);
2432Classes = CMF.add(Classes, Sym, *
this);
2438Members = MF.remove(Members,
Other);
2440Members = MF.add(Members, *
this, NewClassMembers);
2443ClassSet DisequalToOther =
Other.getDisequalClasses(DisequalityInfo,
CF);
2446 if(DisequalToOther.contains(*
this))
2449 if(!DisequalToOther.isEmpty()) {
2450ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo,
CF);
2451DisequalityInfo = DF.remove(DisequalityInfo,
Other);
2453 for(EquivalenceClass DisequalClass : DisequalToOther) {
2454DisequalToThis =
CF.add(DisequalToThis, DisequalClass);
2459ClassSet OriginalSetLinkedToOther =
2460*DisequalityInfo.lookup(DisequalClass);
2464ClassSet NewSet =
CF.remove(OriginalSetLinkedToOther,
Other);
2465NewSet =
CF.add(NewSet, *
this);
2467DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2470DisequalityInfo = DF.add(DisequalityInfo, *
this, DisequalToThis);
2471State = State->set<DisequalityMap>(DisequalityInfo);
2475State = State->set<ClassMap>(Classes);
2476State = State->set<ClassMembers>(Members);
2481inlineSymbolSet::Factory &
2483 returnState->get_context<
SymbolSet>();
2487 if(
const SymbolSet*Members = State->get<ClassMembers>(*
this))
2492SymbolSet::Factory &F = getMembersFactory(State);
2493 returnF.add(F.getEmptySet(), getRepresentativeSymbol());
2497 returnState->get<ClassMembers>(*this) ==
nullptr;
2502 return isTrivial(State) && Reaper.
isDead(getRepresentativeSymbol());
2509 returnmarkDisequal(RF, State, find(State,
First), find(State, Second));
2514EquivalenceClass
First,
2515EquivalenceClass Second) {
2516 return First.markDisequal(RF, State, Second);
2521EquivalenceClass
Other)
const{
2524 if(*
this==
Other) {
2528DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2529ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2533 if(!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *
this,
2535!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State,
Other,
2539assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce " 2540 "a state with infeasible constraints");
2542State = State->set<DisequalityMap>(DisequalityInfo);
2543State = State->set<ConstraintRange>(Constraints);
2548inline boolEquivalenceClass::addToDisequalityInfo(
2549DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2551EquivalenceClass Second) {
2554DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2555ClassSet::Factory &
CF= State->get_context<ClassSet>();
2556ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2559 constClassSet *CurrentSet = Info.lookup(
First);
2560ClassSet NewSet = CurrentSet ? *CurrentSet :
CF.getEmptySet();
2561NewSet =
CF.add(NewSet, Second);
2563Info = F.add(Info,
First, NewSet);
2570 if(
const RangeSet*SecondConstraint = Constraints.lookup(Second))
2571 if(
constllvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2573 RangeSetFirstConstraint = SymbolicRangeInferrer::inferRange(
2574RF, State,
First.getRepresentativeSymbol());
2576FirstConstraint = RF.
deletePoint(FirstConstraint, *Point);
2580 if(FirstConstraint.
isEmpty())
2583Constraints = CRF.add(Constraints,
First, FirstConstraint);
2589inlinestd::optional<bool> EquivalenceClass::areEqual(
ProgramStateRefState,
2592 returnEquivalenceClass::areEqual(State, find(State, FirstSym),
2593find(State, SecondSym));
2596inlinestd::optional<bool> EquivalenceClass::areEqual(
ProgramStateRefState,
2597EquivalenceClass
First,
2598EquivalenceClass Second) {
2600 if(
First== Second)
2605ClassSet DisequalToFirst =
First.getDisequalClasses(State);
2606 if(DisequalToFirst.contains(Second))
2610 returnstd::nullopt;
2616 SymbolSetClsMembers = getClassMembers(State);
2617assert(ClsMembers.contains(Old));
2620SymbolSet::Factory &F = getMembersFactory(State);
2621ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2622ClsMembers = F.remove(ClsMembers, Old);
2625assert(!ClsMembers.isEmpty() &&
2626 "Class should have had at least two members before member removal");
2628ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2629ClassMembersMap = EMFactory.add(ClassMembersMap, *
this, ClsMembers);
2630State = State->set<ClassMembers>(ClassMembersMap);
2633ClassMapTy Classes = State->get<ClassMap>();
2634ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2635Classes = CMF.remove(Classes, Old);
2636State = State->set<ClassMap>(Classes);
2651 returnState->assume(DefinedVal,
false);
2656State = State->assume(DefinedVal,
true);
2663 returnState->assumeInclusiveRange(DefinedVal, Constraint->
getMinValue(),
2676 for(
const SymbolRef&MemberSym : ClassMembers) {
2684 constllvm::APSInt &SV = CI->getValue();
2685 const RangeSet*ClassConstraint = getConstraint(State,
Class);
2687 if(ClassConstraint && !ClassConstraint->
contains(SV))
2691 if(SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
2696State = merge(F, State, MemberSym, SimplifiedMemberSym);
2700 if(OldState == State)
2716State = find(State, MemberSym).removeMember(State, MemberSym);
2720 const RangeSet*ClassConstraint = getConstraint(State,
Class);
2741State =
reAssume(State, ClassConstraint, SimplifiedMemberVal);
2749inlineClassSet EquivalenceClass::getDisequalClasses(
ProgramStateRefState,
2751 returnfind(State, Sym).getDisequalClasses(State);
2756 returngetDisequalClasses(State->get<DisequalityMap>(),
2757State->get_context<ClassSet>());
2761EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2762ClassSet::Factory &Factory)
const{
2763 if(
constClassSet *DisequalClasses = Map.lookup(*
this))
2764 return*DisequalClasses;
2766 returnFactory.getEmptySet();
2770ClassMembersTy Members = State->get<ClassMembers>();
2772 for(std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2775 if(find(State,
Member) == ClassMembersPair.first) {
2783DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2784 for(std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2785EquivalenceClass
Class= DisequalityInfo.first;
2786ClassSet DisequalClasses = DisequalityInfo.second;
2789 if(DisequalClasses.isEmpty())
2794 for(EquivalenceClass DisequalClass : DisequalClasses) {
2795 constClassSet *DisequalToDisequalClasses =
2796Disequalities.lookup(DisequalClass);
2799 if(!DisequalToDisequalClasses ||
2800!DisequalToDisequalClasses->contains(
Class))
2812boolRangeConstraintManager::canReasonAbout(
SVal X)
const{
2814 if(SymVal && SymVal->isExpression()) {
2815 const SymExpr*SE = SymVal->getSymbol();
2817 if(
const SymIntExpr*SIE = dyn_cast<SymIntExpr>(SE)) {
2818 switch(SIE->getOpcode()) {
2838 if(
const SymSymExpr*SSE = dyn_cast<SymSymExpr>(SE)) {
2860 const RangeSet*Ranges = getConstraint(State, Sym);
2868 return*
Value== 0;
2882constllvm::APSInt *RangeConstraintManager::getSymVal(
ProgramStateRefSt,
2884 return getRange(St, Sym).getConcreteValue();
2887constllvm::APSInt *RangeConstraintManager::getSymMinVal(
ProgramStateRefSt,
2890 return Range.isEmpty() ? nullptr : &
Range.getMinValue();
2893constllvm::APSInt *RangeConstraintManager::getSymMaxVal(
ProgramStateRefSt,
2896 return Range.isEmpty() ? nullptr : &
Range.getMaxValue();
2908ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2909ClassMembersTy NewClassMembersMap = ClassMembersMap;
2910ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2911SymbolSet::Factory &SetFactory = State->get_context<
SymbolSet>();
2913ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2914ConstraintRangeTy NewConstraints = Constraints;
2915ConstraintRangeTy::Factory &ConstraintFactory =
2916State->get_context<ConstraintRange>();
2918ClassMapTy Map = State->get<ClassMap>();
2919ClassMapTy NewMap = Map;
2920ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2922DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2923DisequalityMapTy::Factory &DisequalityFactory =
2924State->get_context<DisequalityMap>();
2925ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
2927 boolClassMapChanged =
false;
2928 boolMembersMapChanged =
false;
2929 boolConstraintMapChanged =
false;
2930 boolDisequalitiesChanged =
false;
2932 autoremoveDeadClass = [&](EquivalenceClass
Class) {
2934Constraints = ConstraintFactory.remove(Constraints,
Class);
2935ConstraintMapChanged =
true;
2939ClassSet DisequalClasses =
2940 Class.getDisequalClasses(Disequalities, ClassSetFactory);
2941 if(!DisequalClasses.isEmpty()) {
2942 for(EquivalenceClass DisequalClass : DisequalClasses) {
2943ClassSet DisequalToDisequalSet =
2944DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
2947assert(!DisequalToDisequalSet.isEmpty());
2948ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet,
Class);
2951 if(NewSet.isEmpty()) {
2953DisequalityFactory.remove(Disequalities, DisequalClass);
2956DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
2960Disequalities = DisequalityFactory.remove(Disequalities,
Class);
2961DisequalitiesChanged =
true;
2966 for(std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
2968EquivalenceClass
Class= ClassConstraintPair.first;
2969 if(
Class.isTriviallyDead(State, SymReaper)) {
2971removeDeadClass(
Class);
2976 for(std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
2979 if(SymReaper.
isDead(Sym)) {
2980ClassMapChanged =
true;
2981NewMap = ClassFactory.remove(NewMap, Sym);
2987 for(std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
2989EquivalenceClass
Class= ClassMembersPair.first;
2990 SymbolSetLiveMembers = ClassMembersPair.second;
2991 boolMembersChanged =
false;
2995MembersChanged =
true;
2996LiveMembers = SetFactory.remove(LiveMembers,
Member);
3001 if(!MembersChanged)
3004MembersMapChanged =
true;
3006 if(LiveMembers.isEmpty()) {
3008NewClassMembersMap = EMFactory.remove(NewClassMembersMap,
Class);
3011removeDeadClass(
Class);
3014NewClassMembersMap =
3015EMFactory.add(NewClassMembersMap,
Class, LiveMembers);
3022 if(ClassMapChanged)
3023State = State->set<ClassMap>(NewMap);
3025 if(MembersMapChanged)
3026State = State->set<ClassMembers>(NewClassMembersMap);
3028 if(ConstraintMapChanged)
3029State = State->set<ConstraintRange>(Constraints);
3031 if(DisequalitiesChanged)
3032State = State->set<DisequalityMap>(Disequalities);
3034assert(EquivalenceClass::isClassDataConsistent(State));
3041 returnSymbolicRangeInferrer::inferRange(F, State, Sym);
3047 returnConstraintAssignor::assign(State, getSValBuilder(), F, Sym,
Range);
3064 constllvm::APSInt &Int,
3065 constllvm::APSInt &Adjustment) {
3071llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3075 returnsetRange(St, Sym, New);
3080 constllvm::APSInt &Int,
3081 constllvm::APSInt &Adjustment) {
3088llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3092 returnsetRange(St, Sym, New);
3097 constllvm::APSInt &Int,
3098 constllvm::APSInt &Adjustment)
const{
3101 switch(AdjustmentType.testInRange(Int,
true)) {
3111llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3112llvm::APSInt
Min= AdjustmentType.getMinValue();
3113 if(ComparisonVal ==
Min)
3116llvm::APSInt Lower =
Min- Adjustment;
3117llvm::APSInt Upper = ComparisonVal - Adjustment;
3126 constllvm::APSInt &Int,
3127 constllvm::APSInt &Adjustment) {
3128 RangeSetNew = getSymLTRange(St, Sym, Int, Adjustment);
3129 returnsetRange(St, Sym, New);
3134 constllvm::APSInt &Int,
3135 constllvm::APSInt &Adjustment)
const{
3138 switch(AdjustmentType.testInRange(Int,
true)) {
3148llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3149llvm::APSInt
Max= AdjustmentType.getMaxValue();
3150 if(ComparisonVal ==
Max)
3153llvm::APSInt Lower = ComparisonVal - Adjustment;
3154llvm::APSInt Upper =
Max- Adjustment;
3158 returnF.
intersect(SymRange, Lower, Upper);
3163 constllvm::APSInt &Int,
3164 constllvm::APSInt &Adjustment) {
3165 RangeSetNew = getSymGTRange(St, Sym, Int, Adjustment);
3166 returnsetRange(St, Sym, New);
3171 constllvm::APSInt &Int,
3172 constllvm::APSInt &Adjustment)
const{
3175 switch(AdjustmentType.testInRange(Int,
true)) {
3185llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3186llvm::APSInt
Min= AdjustmentType.getMinValue();
3187 if(ComparisonVal ==
Min)
3190llvm::APSInt
Max= AdjustmentType.getMaxValue();
3191llvm::APSInt Lower = ComparisonVal - Adjustment;
3192llvm::APSInt Upper =
Max- Adjustment;
3195 returnF.
intersect(SymRange, Lower, Upper);
3200 constllvm::APSInt &Int,
3201 constllvm::APSInt &Adjustment) {
3202 RangeSetNew = getSymGERange(St, Sym, Int, Adjustment);
3203 returnsetRange(St, Sym, New);
3207RangeConstraintManager::getSymLERange(llvm::function_ref<
RangeSet()> RS,
3208 constllvm::APSInt &Int,
3209 constllvm::APSInt &Adjustment)
const{
3212 switch(AdjustmentType.testInRange(Int,
true)) {
3222llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3223llvm::APSInt
Max= AdjustmentType.getMaxValue();
3224 if(ComparisonVal ==
Max)
3227llvm::APSInt
Min= AdjustmentType.getMinValue();
3228llvm::APSInt Lower =
Min- Adjustment;
3229llvm::APSInt Upper = ComparisonVal - Adjustment;
3237 constllvm::APSInt &Int,
3238 constllvm::APSInt &Adjustment)
const{
3239 returngetSymLERange([&] {
return getRange(St, Sym); },
Int, Adjustment);
3244 constllvm::APSInt &Int,
3245 constllvm::APSInt &Adjustment) {
3246 RangeSetNew = getSymLERange(St, Sym, Int, Adjustment);
3247 returnsetRange(St, Sym, New);
3252 constllvm::APSInt &To,
constllvm::APSInt &Adjustment) {
3253 RangeSetNew = getSymGERange(State, Sym, From, Adjustment);
3256 RangeSetOut = getSymLERange([&] {
returnNew; }, To, Adjustment);
3257 returnsetRange(State, Sym, Out);
3260ProgramStateRefRangeConstraintManager::assumeSymOutsideInclusiveRange(
3262 constllvm::APSInt &To,
constllvm::APSInt &Adjustment) {
3263 RangeSetRangeLT = getSymLTRange(State, Sym, From, Adjustment);
3264 RangeSetRangeGT = getSymGTRange(State, Sym, To, Adjustment);
3266 returnsetRange(State, Sym, New);
3273voidRangeConstraintManager::printJson(raw_ostream &Out,
ProgramStateRefState,
3274 const char*NL,
unsigned intSpace,
3276printConstraints(Out, State, NL, Space, IsDot);
3277printEquivalenceClasses(Out, State, NL, Space, IsDot);
3278printDisequalities(Out, State, NL, Space, IsDot);
3281voidRangeConstraintManager::printValue(raw_ostream &Out,
ProgramStateRefState,
3285Out <<
"<empty rangeset>";
3294llvm::raw_string_ostream O(S);
3299voidRangeConstraintManager::printConstraints(raw_ostream &Out,
3304ConstraintRangeTy Constraints = State->get<ConstraintRange>();
3306Indent(Out, Space, IsDot) <<
"\"constraints\": ";
3307 if(Constraints.isEmpty()) {
3308Out <<
"null,"<< NL;
3312std::map<std::string, RangeSet> OrderedConstraints;
3313 for(std::pair<EquivalenceClass, RangeSet>
P: Constraints) {
3314 SymbolSetClassMembers =
P.first.getClassMembers(State);
3315 for(
const SymbolRef&ClassMember : ClassMembers) {
3316 boolinsertion_took_place;
3317std::tie(std::ignore, insertion_took_place) =
3318OrderedConstraints.insert({
toString(ClassMember),
P.second});
3319assert(insertion_took_place &&
3320 "two symbols should not have the same dump");
3327 for(std::pair<std::string, RangeSet>
P: OrderedConstraints) {
3334Indent(Out, Space, IsDot)
3335<<
"{ \"symbol\": \""<<
P.first <<
"\", \"range\": \"";
3336 P.second.dump(Out);
3342Indent(Out, Space, IsDot) <<
"],"<< NL;
3348ClassMembers.end());
3349llvm::sort(ClassMembersSorted,
3354 boolFirstMember =
true;
3357llvm::raw_string_ostream Out(Str);
3359 for(
SymbolRefClassMember : ClassMembersSorted) {
3361FirstMember =
false;
3364Out <<
"\""<< ClassMember <<
"\"";
3370voidRangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3375ClassMembersTy Members = State->get<ClassMembers>();
3377Indent(Out, Space, IsDot) <<
"\"equivalence_classes\": ";
3378 if(Members.isEmpty()) {
3379Out <<
"null,"<< NL;
3383std::set<std::string> MembersStr;
3384 for(std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3385MembersStr.insert(
toString(State, ClassToSymbolSet.first));
3389 boolFirstClass =
true;
3390 for(
conststd::string &Str : MembersStr) {
3392FirstClass =
false;
3397Indent(Out, Space, IsDot);
3403Indent(Out, Space, IsDot) <<
"],"<< NL;
3406voidRangeConstraintManager::printDisequalities(raw_ostream &Out,
3411DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3413Indent(Out, Space, IsDot) <<
"\"disequality_info\": ";
3414 if(Disequalities.isEmpty()) {
3415Out <<
"null,"<< NL;
3421 usingEqClassesStrTy = std::set<std::string>;
3422 usingDisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3423DisequalityInfoStrTy DisequalityInfoStr;
3424 for(std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3425EquivalenceClass
Class= ClassToDisEqSet.first;
3426ClassSet DisequalClasses = ClassToDisEqSet.second;
3427EqClassesStrTy MembersStr;
3428 for(EquivalenceClass DisEqClass : DisequalClasses)
3429MembersStr.insert(
toString(State, DisEqClass));
3430DisequalityInfoStr.insert({
toString(State,
Class), MembersStr});
3435 boolFirstClass =
true;
3436 for(std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3437DisequalityInfoStr) {
3438 conststd::string &
Class= ClassToDisEqSet.first;
3440FirstClass =
false;
3445Indent(Out, Space, IsDot) <<
"{"<< NL;
3446 unsigned intDisEqSpace = Space + 1;
3447Indent(Out, DisEqSpace, IsDot) <<
"\"class\": ";
3449 constEqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3450 if(!DisequalClasses.empty()) {
3452Indent(Out, DisEqSpace, IsDot) <<
"\"disequal_to\": ["<< NL;
3453 unsigned intDisEqClassSpace = DisEqSpace + 1;
3454Indent(Out, DisEqClassSpace, IsDot);
3455 boolFirstDisEqClass =
true;
3456 for(
conststd::string &DisEqClass : DisequalClasses) {
3457 if(FirstDisEqClass) {
3458FirstDisEqClass =
false;
3461Indent(Out, DisEqClassSpace, IsDot);
3467Indent(Out, Space, IsDot) <<
"}";
3472Indent(Out, Space, IsDot) <<
"],"<< NL;
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
llvm::MachO::SymbolSet SymbolSet
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set type Name and registers the factory for such sets in the program state,...
#define CONSTRAINT_DISPATCH(Id)
static void swapIterators(T &First, T &FirstEnd, T &Second, T &SecondEnd)
static ProgramStateRef reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue)
#define DEFAULT_ASSIGN(Id)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
static BinaryOperatorKind getOpFromIndex(size_t Index)
constexpr size_t getCmpOpCount() const
TriStateKind getCmpOpState(BinaryOperatorKind CurrentOP, BinaryOperatorKind QueriedOP) const
TriStateKind getCmpOpStateForUnknownX2(BinaryOperatorKind CurrentOP) const
bool isComparisonOp() const
bool isRelationalOp() const
static Opcode negateComparisonOp(Opcode Opc)
static Opcode reverseComparisonOp(Opcode Opc)
bool isEqualityOp() const
A (possibly-)qualified type.
The base class of the type hierarchy.
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
bool isReferenceType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration 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.
RangeTestResultKind
Used to classify whether a value is representable using this type.
@ RTR_Within
Value is representable using this type.
@ RTR_Below
Value is less than the minimum representable value.
@ RTR_Above
Value is greater than the maximum representable value.
uint32_t getBitWidth() const
RangeTestResultKind testInRange(const llvm::APSInt &Val, bool AllowMixedSign) const LLVM_READONLY
Tests whether a given value is losslessly representable using this type.
void apply(llvm::APSInt &Value) const
Convert a given APSInt, in place, to match this type.
llvm::APSInt getMinValue() const LLVM_READONLY
Returns the minimum value for 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.
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
Template implementation for all binary symbolic expressions.
QualType getType() const override
BinaryOperator::Opcode getOpcode() const
static bool isLocType(QualType T)
SValBuilder & getSValBuilder()
RangeSet unite(RangeSet LHS, RangeSet RHS)
Create a new set which is a union of two given ranges.
RangeSet negate(RangeSet What)
Negate the given range set.
RangeSet intersect(RangeSet LHS, RangeSet RHS)
Intersect the given range sets.
RangeSet deletePoint(RangeSet From, const llvm::APSInt &Point)
Delete the given point from the range set.
RangeSet getRangeSet(Range Origin)
Create a new set with just one range.
RangeSet add(RangeSet LHS, RangeSet RHS)
Create a new set with all ranges from both LHS and RHS.
RangeSet castTo(RangeSet What, APSIntType Ty)
Performs promotions, truncations and conversions of the given set.
persistent set of non-overlapping ranges.
const_iterator end() const
APSIntType getAPSIntType() const
const llvm::APSInt & getMaxValue() const
Get the maximal value covered by the ranges in the set.
bool encodesTrueRange() const
Test if the range doesn't contain zero.
bool encodesFalseRange() const
Test if the range is the [0,0] range.
const_iterator begin() const
const llvm::APSInt & getMinValue() const
Get the minimal value covered by the ranges in the set.
ImplType::const_iterator const_iterator
bool contains(llvm::APSInt Point) const
Test whether the given point is contained by any of the ranges.
void dump(raw_ostream &OS) const
bool containsZero() const
uint32_t getBitWidth() const
const llvm::APSInt * getConcreteValue() const
getConcreteValue - If a symbol is constrained to equal a specific integer constant then this method r...
A Range represents the closed range [from, to].
const llvm::APSInt & From() const
void dump(raw_ostream &OS) const
bool Includes(const llvm::APSInt &Point) const
const llvm::APSInt & To() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SymExprVisitor - this class implements a simple visitor for SymExpr subclasses.
virtual void dumpToStream(raw_ostream &os) const
virtual QualType getType() const =0
const SymExprT * acquire(Args &&...args)
Create or retrieve a SymExpr of type SymExprT for the given arguments.
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
Represents a symbolic expression involving a unary operator.
QualType getType() const override
UnaryOperator::Opcode getOpcode() const
const SymExpr * getOperand() const
Value representing integer constant.
Represents symbolic expression that isn't a location.
SVal simplifyToSVal(ProgramStateRef State, SymbolRef Sym)
Try to simplify a given symbolic expression's associated SVal based on the constraints in State.
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintMap
SymbolRef simplify(ProgramStateRef State, SymbolRef Sym)
Try to simplify a given symbolic expression based on the constraints in State.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ CF
Indicates that the tracked object is a CF object.
std::unique_ptr< ConstraintManager > CreateRangeConstraintManager(ProgramStateManager &statemgr, ExprEngine *exprengine)
ConstraintMap getConstraintMap(ProgramStateRef State)
bool Zero(InterpState &S, CodePtr OpPC)
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
The JSON file list parser is used to communicate input to InstallAPI.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Result
The result type of a method or function.
bool operator!=(CanQual< T > x, CanQual< U > y)
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ Other
Other implicit parameter.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4