20#include "llvm/ADT/FoldingSet.h"
21#include "llvm/ADT/ImmutableSet.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/SmallSet.h"
24#include "llvm/ADT/StringExtras.h"
25#include "llvm/Support/Compiler.h"
26#include "llvm/Support/raw_ostream.h"
37 static_assert(BO_LT < BO_GT && BO_GT < BO_LE && BO_LE < BO_GE &&
38 BO_GE < BO_EQ && BO_EQ < BO_NE,
39 "This class relies on operators order. Rework it otherwise.");
76 static constexpr size_t CmpOpCount = BO_NE - BO_LT + 1;
77 const TriStateKind CmpOpTable[CmpOpCount][CmpOpCount + 1] = {
88 return static_cast<size_t>(OP - BO_LT);
100 return CmpOpTable[getIndexFromOp(CurrentOP)][getIndexFromOp(QueriedOP)];
104 return CmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
112RangeSet::ContainerType RangeSet::Factory::EmptySet{};
118 std::back_inserter(
Result));
119 return makePersistent(std::move(
Result));
124 Result.reserve(Original.size() + 1);
128 Result.push_back(Element);
131 return makePersistent(std::move(
Result));
135 return add(Original,
Range(Point));
139 ContainerType
Result = unite(*LHS.Impl, *RHS.Impl);
140 return makePersistent(std::move(
Result));
147 return makePersistent(std::move(
Result));
151 return unite(Original,
Range(ValueFactory.getValue(Point)));
156 return unite(Original,
157 Range(ValueFactory.getValue(From), ValueFactory.getValue(To)));
162 std::swap(
First, Second);
163 std::swap(FirstEnd, SecondEnd);
167 const ContainerType &RHS) {
174 using iterator = ContainerType::const_iterator;
176 iterator
First = LHS.begin();
177 iterator FirstEnd = LHS.end();
178 iterator Second = RHS.begin();
179 iterator 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 auto AppendTheRest = [&
Result](iterator I, iterator
E) {
233 if (
First->From() > Second->From())
241 const llvm::APSInt &UnionStart =
First->From();
248 while (
First->To() >= Second->To()) {
250 if (++Second == SecondEnd) {
260 return AppendTheRest(++
First, FirstEnd);
269 if (
First->To() < Second->From() - One)
277 if (++
First == FirstEnd) {
283 Result.emplace_back(UnionStart, Second->To());
287 return AppendTheRest(++Second, SecondEnd);
308 if (++
First == FirstEnd)
312 return AppendTheRest(Second, SecondEnd);
315 llvm_unreachable(
"Normally, we should not reach here");
321 return makePersistent(std::move(
Result));
324RangeSet RangeSet::Factory::makePersistent(ContainerType &&From) {
325 llvm::FoldingSetNodeID ID;
329 ContainerType *
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 return std::prev(
end())->To();
359 return begin()->From().isUnsigned();
364 return begin()->From().getBitWidth();
372bool RangeSet::containsImpl(llvm::APSInt &Point)
const {
381 return std::prev(It)->Includes(Point);
384bool RangeSet::pin(llvm::APSInt &Point)
const {
393bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper)
const {
413 Lower =
Type.getMinValue();
414 Upper =
Type.getMaxValue();
418 Lower =
Type.getMinValue();
423 Lower =
Type.getMinValue();
424 Upper =
Type.getMaxValue();
433 Upper =
Type.getMaxValue();
443 Upper =
Type.getMaxValue();
454 Lower =
Type.getMinValue();
464 Lower =
Type.getMinValue();
465 Upper =
Type.getMaxValue();
475 llvm::APSInt Upper) {
476 if (What.
isEmpty() || !What.pin(Lower, Upper))
477 return getEmptySet();
479 ContainerType DummyContainer;
481 if (Lower <= Upper) {
493 return getEmptySet();
495 DummyContainer.push_back(
496 Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
506 return getEmptySet();
508 DummyContainer.push_back(
509 Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
510 DummyContainer.push_back(
511 Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
514 return intersect(*What.Impl, DummyContainer);
518 const RangeSet::ContainerType &RHS) {
520 Result.reserve(std::max(LHS.size(), RHS.size()));
523 FirstEnd = LHS.end(), SecondEnd = RHS.end();
528 while (
First != FirstEnd && Second != SecondEnd) {
533 if (Second->From() <
First->From())
544 if (Second->From() >
First->To()) {
560 const llvm::APSInt &IntersectionStart = Second->From();
565 if (Second->To() >
First->To()) {
582 Result.push_back(
Range(IntersectionStart, Second->To()));
586 }
while (Second != SecondEnd);
590 return getEmptySet();
592 return makePersistent(std::move(
Result));
599 return getEmptySet();
601 return intersect(*LHS.Impl, *RHS.Impl);
605 if (LHS.containsImpl(Point))
606 return getRangeSet(ValueFactory.getValue(Point));
608 return getEmptySet();
613 return getEmptySet();
615 const llvm::APSInt SampleValue = What.
getMinValue();
616 const llvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
617 const llvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
620 Result.reserve(What.
size() + (SampleValue == MIN));
626 const llvm::APSInt &From = It->From();
627 const llvm::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 const llvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
664 const llvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
667 Result.emplace_back(NewFrom, NewTo);
671 return makePersistent(std::move(
Result));
686 return makePersistent(truncateTo(What, Ty));
700 if (IsConversion && (!IsPromotion || !What.
isUnsigned()))
701 return makePersistent(convertTo(What, Ty));
703 assert(IsPromotion &&
"Only promotion operation from unsigneds left.");
704 return makePersistent(promoteTo(What, Ty));
712RangeSet::ContainerType RangeSet::Factory::truncateTo(
RangeSet What,
725 uint64_t CastRangeSize = APInt::getMaxValue(Ty.
getBitWidth()).getZExtValue();
726 for (
const Range &R : What) {
728 APSInt FromInt = R.From();
732 uint64_t CurrentRangeSize = (ToInt - FromInt).getZExtValue();
736 if (CurrentRangeSize >= CastRangeSize) {
737 Dummy.emplace_back(ValueFactory.getMinValue(Ty),
738 ValueFactory.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) {
748 Dummy.emplace_back(ValueFactory.getMinValue(Ty), PersistentTo);
749 Dummy.emplace_back(PersistentFrom, ValueFactory.getMaxValue(Ty));
751 Dummy.emplace_back(PersistentFrom, PersistentTo);
778RangeSet::ContainerType RangeSet::Factory::convertTo(
RangeSet What,
782 using Bounds = std::pair<const APSInt &, const APSInt &>;
783 ContainerType AscendArray;
784 ContainerType DescendArray;
785 auto CastRange = [Ty, &VF = ValueFactory](
const Range &R) -> Bounds {
787 APSInt FromInt = R.From();
792 return {VF.getValue(FromInt), VF.getValue(ToInt)};
796 const auto *It = What.
begin();
797 const auto *
E = What.
end();
799 Bounds NewBounds = CastRange(*(It++));
801 if (NewBounds.first < LastConvertedInt) {
802 DescendArray.emplace_back(NewBounds.first, NewBounds.second);
809 if (NewBounds.first > NewBounds.second) {
810 DescendArray.emplace_back(ValueFactory.getMinValue(Ty), NewBounds.second);
811 AscendArray.emplace_back(NewBounds.first, ValueFactory.getMaxValue(Ty));
814 AscendArray.emplace_back(NewBounds.first, NewBounds.second);
815 LastConvertedInt = NewBounds.first;
819 Bounds NewBounds = CastRange(*(It++));
820 DescendArray.emplace_back(NewBounds.first, NewBounds.second);
823 return unite(AscendArray, DescendArray);
827RangeSet::ContainerType RangeSet::Factory::promoteTo(
RangeSet What,
836 for (
const Range &R : What) {
838 llvm::APSInt FromInt = R.From();
839 llvm::APSInt ToInt = R.To();
843 Result.emplace_back(ValueFactory.getValue(FromInt),
844 ValueFactory.getValue(ToInt));
850 const llvm::APSInt &Point) {
854 llvm::APSInt Upper = Point;
855 llvm::APSInt Lower = Point;
861 return intersect(From, Upper, Lower);
871 llvm::interleaveComma(*
this,
OS, [&
OS](
const Range &R) { R.
dump(
OS); });
879class EquivalenceClass;
914class EquivalenceClass :
public llvm::FoldingSetNode {
917 [[nodiscard]]
static inline EquivalenceClass find(
ProgramStateRef State,
954 EquivalenceClass
First, EquivalenceClass Second);
957 EquivalenceClass
Other)
const;
958 [[nodiscard]]
static inline ClassSet getDisequalClasses(
ProgramStateRef State,
960 [[nodiscard]]
inline ClassSet getDisequalClasses(
ProgramStateRef State)
const;
961 [[nodiscard]]
inline ClassSet
962 getDisequalClasses(DisequalityMapTy Map, ClassSet::Factory &Factory)
const;
964 [[nodiscard]]
static inline std::optional<bool>
966 EquivalenceClass Second);
967 [[nodiscard]]
static inline std::optional<bool>
978 EquivalenceClass Class);
982 dumpToStream(State, llvm::errs());
986 [[nodiscard]] LLVM_ATTRIBUTE_UNUSED
static bool
989 [[nodiscard]]
QualType getType()
const {
990 return getRepresentativeSymbol()->getType();
993 EquivalenceClass() =
delete;
994 EquivalenceClass(
const EquivalenceClass &) =
default;
995 EquivalenceClass &operator=(
const EquivalenceClass &) =
delete;
996 EquivalenceClass(EquivalenceClass &&) =
default;
997 EquivalenceClass &operator=(EquivalenceClass &&) =
delete;
1007 static void Profile(llvm::FoldingSetNodeID &
ID,
uintptr_t CID) {
1011 void Profile(llvm::FoldingSetNodeID &
ID)
const { Profile(
ID, this->ID); }
1022 SymbolRef getRepresentativeSymbol()
const {
1025 static inline SymbolSet::Factory &getMembersFactory(
ProgramStateRef State);
1032 addToDisequalityInfo(DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
1034 EquivalenceClass
First, EquivalenceClass Second);
1044[[nodiscard]] LLVM_ATTRIBUTE_UNUSED
bool
1045areFeasible(ConstraintRangeTy Constraints) {
1046 return llvm::none_of(
1048 [](
const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1049 return ClassConstraint.second.isEmpty();
1054 EquivalenceClass Class) {
1055 return State->get<ConstraintRange>(
Class);
1060 return getConstraint(State, EquivalenceClass::find(State, Sym));
1064 EquivalenceClass Class,
1066 return State->set<ConstraintRange>(
Class, Constraint);
1070 ConstraintRangeTy Constraints) {
1071 return State->set<ConstraintRange>(Constraints);
1087std::optional<bool> meansEquality(
const SymSymExpr *Sym) {
1099 return std::nullopt;
1107template <
class SecondTy,
class... RestTy>
1109 SecondTy Second, RestTy... Tail);
1111template <
class... RangeTy>
struct IntersectionTraits;
1113template <
class... TailTy>
struct IntersectionTraits<
RangeSet, TailTy...> {
1118template <>
struct IntersectionTraits<> {
1121 using Type = std::optional<RangeSet>;
1124template <
class OptionalOrPointer,
class... TailTy>
1125struct IntersectionTraits<OptionalOrPointer, TailTy...> {
1127 using Type =
typename IntersectionTraits<TailTy...>
::Type;
1130template <
class EndTy>
1137[[nodiscard]] LLVM_ATTRIBUTE_UNUSED
inline std::optional<RangeSet>
1144 return std::nullopt;
1147template <
class... RestTy>
1152 return intersect(F, F.
intersect(Head, Second), Tail...);
1155template <
class SecondTy,
class... RestTy>
1157 SecondTy Second, RestTy... Tail) {
1160 return intersect(F, Head, *Second, Tail...);
1164 return intersect(F, Head, Tail...);
1188template <
class HeadTy,
class SecondTy,
class... RestTy>
1190 typename IntersectionTraits<HeadTy, SecondTy, RestTy...>
::Type
1194 return intersect(F, *Head, Second, Tail...);
1196 return intersect(F, Second, Tail...);
1208class SymbolicRangeInferrer
1211 template <
class SourceType>
1213 SourceType Origin) {
1214 SymbolicRangeInferrer Inferrer(F, State);
1215 return Inferrer.infer(Origin);
1219 if (std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1229 if (std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1235 return VisitBinaryOperator(Sym);
1239 return VisitBinaryOperator(Sym);
1251 getRangeForNegatedSymSym(SSE),
1253 getRangeCommutativeSymSym(SSE),
1257 getRangeForComparisonSymbol(SSE),
1260 getRangeForEqualities(SSE),
1262 VisitBinaryOperator(SSE));
1267 : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
1274 return {RangeFactory, Val};
1287 return infer(DestType);
1291 return intersect(RangeFactory,
1294 getConstraint(State, Sym),
1300 RangeSet infer(EquivalenceClass Class) {
1301 if (
const RangeSet *AssociatedConstraint = getConstraint(State, Class))
1302 return *AssociatedConstraint;
1304 return infer(
Class.getType());
1311 RangeSet Result(RangeFactory, ValueFactory.getMinValue(
T),
1312 ValueFactory.getMaxValue(
T));
1316 return assumeNonZero(Result,
T);
1321 template <
class BinarySymExprTy>
1322 RangeSet VisitBinaryOperator(
const BinarySymExprTy *Sym) {
1334 QualType ResultType = Sym->getType();
1335 return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1337 inferAs(Sym->getRHS(), ResultType), ResultType);
1363 return std::nullopt;
1365 return Range(ValueFactory.Convert(To, Origin.
From()),
1366 ValueFactory.Convert(To, Origin.
To()));
1369 template <BinaryOperator::Opcode Op>
1373 Range CoarseLHS = fillGaps(LHS);
1374 Range CoarseRHS = fillGaps(RHS);
1376 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1380 auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1381 auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1385 if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1389 return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS,
T);
1392 template <BinaryOperator::Opcode Op>
1406 APSIntType RangeType = ValueFactory.getAPSIntType(
T);
1409 return Range(ValueFactory.getMinValue(RangeType), Origin.
To());
1412 if (Origin.
From().isMinSignedValue()) {
1416 return {ValueFactory.getMinValue(RangeType),
1417 ValueFactory.getMaxValue(RangeType)};
1431 llvm::APSInt AbsMax = std::max(-Origin.
From(), Origin.
To());
1434 return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
1439 APSIntType IntType = ValueFactory.getAPSIntType(
T);
1443 template <
typename ProduceNegatedSymFunc>
1444 std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1449 return std::nullopt;
1452 if (
const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1453 return RangeFactory.negate(*NegatedRange);
1455 return std::nullopt;
1458 std::optional<RangeSet> getRangeForNegatedUnarySym(
const UnarySymExpr *USE) {
1461 return getRangeForNegatedExpr(
1470 std::optional<RangeSet> getRangeForNegatedSymSym(
const SymSymExpr *SSE) {
1471 return getRangeForNegatedExpr(
1472 [SSE, State = this->State]() ->
SymbolRef {
1474 return State->getSymbolManager().getSymSymExpr(
1481 std::optional<RangeSet> getRangeForNegatedSym(
SymbolRef Sym) {
1482 return getRangeForNegatedExpr(
1483 [Sym, State = this->State]() {
1484 return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus,
1490 std::optional<RangeSet> getRangeCommutativeSymSym(
const SymSymExpr *SSE) {
1492 bool IsCommutative = llvm::is_contained(
1494 {BO_EQ, BO_NE, BO_Or, BO_And, BO_Add, BO_Mul, BO_Xor}, Op);
1496 return std::nullopt;
1498 SymbolRef Commuted = State->getSymbolManager().getSymSymExpr(
1502 return std::nullopt;
1515 std::optional<RangeSet> getRangeForComparisonSymbol(
const SymSymExpr *SSE) {
1520 return std::nullopt;
1539 for (
size_t i = 0; i < CmpOpTable.getCmpOpCount(); ++i) {
1544 const RangeSet *QueriedRangeSet = getConstraint(State, SymSym);
1548 if (!QueriedRangeSet) {
1552 QueriedRangeSet = getConstraint(State, SymSym);
1555 if (!QueriedRangeSet || QueriedRangeSet->
isEmpty())
1559 const bool isInFalseBranch =
1560 ConcreteValue ? (*ConcreteValue == 0) :
false;
1565 if (isInFalseBranch)
1569 CmpOpTable.getCmpOpState(CurrentOP, QueriedOP);
1572 if (LastQueriedOpToUnknown != CurrentOP &&
1573 LastQueriedOpToUnknown != QueriedOP) {
1579 BranchState = CmpOpTable.getCmpOpStateForUnknownX2(CurrentOP);
1581 LastQueriedOpToUnknown = QueriedOP;
1590 return std::nullopt;
1593 std::optional<RangeSet> getRangeForEqualities(
const SymSymExpr *Sym) {
1594 std::optional<bool>
Equality = meansEquality(Sym);
1597 return std::nullopt;
1599 if (std::optional<bool> AreEqual =
1600 EquivalenceClass::areEqual(State, Sym->
getLHS(), Sym->
getRHS())) {
1604 if (*AreEqual == *Equality) {
1605 return getTrueRange(Sym->
getType());
1608 return getFalseRange(Sym->
getType());
1611 return std::nullopt;
1616 return assumeNonZero(TypeRange,
T);
1620 const llvm::APSInt &
Zero = ValueFactory.getValue(0,
T);
1621 return RangeSet(RangeFactory, Zero);
1640 if (intersect(RangeFactory, LHS, RHS).isEmpty())
1641 return getTrueRange(
T);
1660 return getTrueRange(
T);
1665 return getTrueRange(
T);
1673 RangeSet CastedLHS = RangeFactory.castTo(LHS, CastingType);
1674 RangeSet CastedRHS = RangeFactory.castTo(RHS, CastingType);
1676 if (intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1677 return getTrueRange(
T);
1687 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1690 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1691 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1693 bool IsLHSNegative = LHS.
To() <
Zero;
1694 bool IsRHSNegative = RHS.
To() <
Zero;
1697 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1698 (IsLHSNegative && IsRHSNegative)) {
1700 const llvm::APSInt &
Min = std::max(LHS.
From(), RHS.
From());
1713 const llvm::APSInt &
Max = IsLHSNegative
1714 ? ValueFactory.getValue(--Zero)
1715 : ValueFactory.getMaxValue(ResultType);
1717 return {RangeFactory, ValueFactory.getValue(
Min),
Max};
1721 if (IsLHSNegative || IsRHSNegative) {
1723 return {RangeFactory, ValueFactory.getMinValue(ResultType),
1724 ValueFactory.getValue(--Zero)};
1734 return assumeNonZero(DefaultRange,
T);
1738 return DefaultRange;
1742RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(
Range LHS,
1745 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1748 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1749 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1751 bool IsLHSNegative = LHS.
To() <
Zero;
1752 bool IsRHSNegative = RHS.
To() <
Zero;
1755 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1756 (IsLHSNegative && IsRHSNegative)) {
1758 const llvm::APSInt &
Max = std::min(LHS.
To(), RHS.
To());
1762 const llvm::APSInt &
Min = IsLHSNegative
1763 ? ValueFactory.getMinValue(ResultType)
1764 : ValueFactory.getValue(Zero);
1766 return {RangeFactory,
Min,
Max};
1770 if (IsLHSPositiveOrZero || IsRHSPositiveOrZero) {
1775 const llvm::APSInt &
Max = IsLHSPositiveOrZero ? LHS.
To() : RHS.
To();
1779 return {RangeFactory, ValueFactory.getValue(Zero),
1780 ValueFactory.getValue(
Max)};
1788RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(
Range LHS,
1791 llvm::APSInt
Zero = ValueFactory.getAPSIntType(
T).getZeroValue();
1793 Range ConservativeRange = getSymmetricalRange(RHS,
T);
1795 llvm::APSInt
Max = ConservativeRange.
To();
1796 llvm::APSInt
Min = ConservativeRange.
From();
1802 return RangeFactory.getEmptySet();
1815 if (
Min.isSigned()) {
1820 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1821 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1825 if (IsLHSPositiveOrZero && IsRHSPositiveOrZero) {
1841 return {RangeFactory, ValueFactory.getValue(
Min), ValueFactory.getValue(
Max)};
1850 return RangeFactory.getEmptySet();
1855 return VisitBinaryOperator<BO_NE>(LHS, RHS,
T);
1857 return VisitBinaryOperator<BO_Or>(LHS, RHS,
T);
1859 return VisitBinaryOperator<BO_And>(LHS, RHS,
T);
1861 return VisitBinaryOperator<BO_Rem>(LHS, RHS,
T);
1885 return S1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1886 S1->get<ClassMap>() == S2->get<ClassMap>();
1889 bool canReasonAbout(
SVal X)
const override;
1905 void printJson(raw_ostream &Out,
ProgramStateRef State,
const char *NL =
"\n",
1906 unsigned int Space = 0,
bool IsDot =
false)
const override;
1910 const char *NL =
"\n",
unsigned int Space = 0,
1911 bool IsDot =
false)
const;
1913 const char *NL =
"\n",
unsigned int Space = 0,
1914 bool IsDot =
false)
const;
1916 const char *NL =
"\n",
unsigned int Space = 0,
1917 bool IsDot =
false)
const;
1924 const llvm::APSInt &
V,
1925 const llvm::APSInt &Adjustment)
override;
1928 const llvm::APSInt &
V,
1929 const llvm::APSInt &Adjustment)
override;
1932 const llvm::APSInt &
V,
1933 const llvm::APSInt &Adjustment)
override;
1936 const llvm::APSInt &
V,
1937 const llvm::APSInt &Adjustment)
override;
1940 const llvm::APSInt &
V,
1941 const llvm::APSInt &Adjustment)
override;
1944 const llvm::APSInt &
V,
1945 const llvm::APSInt &Adjustment)
override;
1949 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
1953 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
1963 const llvm::APSInt &Int,
1964 const llvm::APSInt &Adjustment)
const;
1966 const llvm::APSInt &Int,
1967 const llvm::APSInt &Adjustment)
const;
1969 const llvm::APSInt &Int,
1970 const llvm::APSInt &Adjustment)
const;
1972 const llvm::APSInt &Int,
1973 const llvm::APSInt &Adjustment)
const;
1975 const llvm::APSInt &Int,
1976 const llvm::APSInt &Adjustment)
const;
1997template <
class Derived>
class ConstraintAssignorBase {
1999 using Const =
const llvm::APSInt &;
2001#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
2003#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \
2004 if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \
2008 assignImpl(Sym, Constraint);
2013#define SYMBOL(Id, Parent) \
2014 case SymExpr::Id##Kind: \
2016#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2018 llvm_unreachable(
"Unknown SymExpr kind!");
2021#define DEFAULT_ASSIGN(Id) \
2022 bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \
2025 bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
2026 bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
2032#define CONSTRAINT_DISPATCH(Id) \
2033 if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \
2034 ASSIGN(Id, Const, Sym, *Const); \
2036 if (Constraint.size() == 1) { \
2037 ASSIGN(Id, Range, Sym, *Constraint.begin()); \
2039 ASSIGN(Id, RangeSet, Sym, Constraint)
2044#define SYMBOL(Id, Parent) \
2045 bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \
2046 CONSTRAINT_DISPATCH(Id); \
2050#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
2051#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2061#undef CONSTRAINT_DISPATCH
2062#undef DEFAULT_ASSIGN
2077class ConstraintAssignor :
public ConstraintAssignorBase<ConstraintAssignor> {
2079 template <
class ClassOrSymbol>
2082 ClassOrSymbol CoS,
RangeSet NewConstraint) {
2083 if (!State || NewConstraint.
isEmpty())
2086 ConstraintAssignor Assignor{State, Builder, F};
2087 return Assignor.assign(CoS, NewConstraint);
2091 template <
typename SymT>
2092 bool handleRemainderOp(
const SymT *Sym,
RangeSet Constraint) {
2093 if (Sym->getOpcode() != BO_Rem)
2097 SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2099 State = State->assume(*NonLocSymSVal,
true);
2107 inline bool assignSymExprToConst(
const SymExpr *Sym, Const Constraint);
2108 inline bool assignSymIntExprToRangeSet(
const SymIntExpr *Sym,
2110 return handleRemainderOp(Sym, Constraint);
2112 inline bool assignSymSymExprToRangeSet(
const SymSymExpr *Sym,
2118 : State(State), Builder(Builder), RangeFactory(F) {}
2119 using Base = ConstraintAssignorBase<ConstraintAssignor>;
2125 State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2131 Base::assign(Sym, NewConstraint);
2145 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2146 ConstraintRangeTy::Factory &
CF = State->get_context<ConstraintRange>();
2149 Constraints =
CF.add(Constraints, Class, NewConstraint);
2151 for (EquivalenceClass DisequalClass :
Class.getDisequalClasses(State)) {
2152 RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
2153 RangeFactory, State, DisequalClass);
2155 UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2159 if (UpdatedConstraint.
isEmpty())
2162 Constraints =
CF.add(Constraints, DisequalClass, UpdatedConstraint);
2164 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2165 "a state with infeasible constraints");
2167 return setConstraints(State, Constraints);
2170 return setConstraint(State, Class, NewConstraint);
2175 return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2180 return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2183 [[nodiscard]] std::optional<bool> interpreteAsBool(
RangeSet Constraint) {
2184 assert(!Constraint.
isEmpty() &&
"Empty ranges shouldn't get here");
2192 return std::nullopt;
2200bool ConstraintAssignor::assignSymExprToConst(
const SymExpr *Sym,
2201 const llvm::APSInt &Constraint) {
2202 llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2204 ClassMembersTy Members = State->get<ClassMembers>();
2205 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2206 EquivalenceClass
Class = ClassToSymbolSet.first;
2207 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2210 SimplifiedClasses.insert(Class);
2216 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2217 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2218 EquivalenceClass
Class = ClassConstraint.first;
2219 if (SimplifiedClasses.count(Class))
2221 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2228 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2229 for (std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2231 EquivalenceClass
Class = DisequalityEntry.first;
2232 ClassSet DisequalClasses = DisequalityEntry.second;
2233 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2241bool ConstraintAssignor::assignSymSymExprToRangeSet(
const SymSymExpr *Sym,
2243 if (!handleRemainderOp(Sym, Constraint))
2246 std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2248 if (!ConstraintAsBool)
2251 if (std::optional<bool> Equality = meansEquality(Sym)) {
2257 if (*Equality == *ConstraintAsBool) {
2258 State = trackEquality(State, Sym->
getLHS(), Sym->
getRHS());
2261 State = trackDisequality(State, Sym->
getLHS(), Sym->
getRHS());
2273std::unique_ptr<ConstraintManager>
2276 return std::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
2280 ConstraintMap::Factory &F = State->get_context<
ConstraintMap>();
2283 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2284 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2285 EquivalenceClass
Class = ClassConstraint.first;
2287 assert(!ClassMembers.isEmpty() &&
2288 "Class must always have at least one member!");
2290 SymbolRef Representative = *ClassMembers.begin();
2291 Result = F.add(
Result, Representative, ClassConstraint.second);
2301LLVM_DUMP_METHOD
void EquivalenceClass::dumpToStream(
ProgramStateRef State,
2302 raw_ostream &os)
const {
2303 SymbolSet ClassMembers = getClassMembers(State);
2304 for (
const SymbolRef &MemberSym : ClassMembers) {
2312 assert(State &&
"State should not be null");
2313 assert(Sym &&
"Symbol should not be null");
2315 if (
const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2316 return *NontrivialClass;
2326 EquivalenceClass FirstClass = find(State,
First);
2327 EquivalenceClass SecondClass = find(State, Second);
2329 return FirstClass.merge(F, State, SecondClass);
2334 EquivalenceClass
Other) {
2350 if (getType()->getCanonicalTypeUnqualified() !=
2351 Other.getType()->getCanonicalTypeUnqualified())
2354 SymbolSet Members = getClassMembers(State);
2360 if (Members.getHeight() >= OtherMembers.getHeight()) {
2361 return mergeImpl(F, State, Members,
Other, OtherMembers);
2363 return Other.mergeImpl(F, State, OtherMembers, *
this, Members);
2382 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2383 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2390 if (std::optional<RangeSet> NewClassConstraint =
2391 intersect(RangeFactory, getConstraint(State, *
this),
2392 getConstraint(State,
Other))) {
2398 if (NewClassConstraint->isEmpty())
2403 Constraints = CRF.remove(Constraints,
Other);
2405 Constraints = CRF.add(Constraints, *
this, *NewClassConstraint);
2407 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2408 "a state with infeasible constraints");
2410 State = State->set<ConstraintRange>(Constraints);
2414 ClassMapTy Classes = State->get<ClassMap>();
2415 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2417 ClassMembersTy Members = State->get<ClassMembers>();
2418 ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2420 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2421 DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2423 ClassSet::Factory &
CF = State->get_context<ClassSet>();
2424 SymbolSet::Factory &F = getMembersFactory(State);
2429 NewClassMembers = F.add(NewClassMembers, Sym);
2431 Classes = CMF.add(Classes, Sym, *
this);
2437 Members = MF.remove(Members,
Other);
2439 Members = MF.add(Members, *
this, NewClassMembers);
2442 ClassSet DisequalToOther =
Other.getDisequalClasses(DisequalityInfo,
CF);
2445 if (DisequalToOther.contains(*
this))
2448 if (!DisequalToOther.isEmpty()) {
2449 ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo,
CF);
2450 DisequalityInfo = DF.remove(DisequalityInfo,
Other);
2452 for (EquivalenceClass DisequalClass : DisequalToOther) {
2453 DisequalToThis =
CF.add(DisequalToThis, DisequalClass);
2458 ClassSet OriginalSetLinkedToOther =
2459 *DisequalityInfo.lookup(DisequalClass);
2463 ClassSet NewSet =
CF.remove(OriginalSetLinkedToOther,
Other);
2464 NewSet =
CF.add(NewSet, *
this);
2466 DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2469 DisequalityInfo = DF.add(DisequalityInfo, *
this, DisequalToThis);
2470 State = State->set<DisequalityMap>(DisequalityInfo);
2474 State = State->set<ClassMap>(Classes);
2475 State = State->set<ClassMembers>(Members);
2480inline SymbolSet::Factory &
2486 if (
const SymbolSet *Members = State->get<ClassMembers>(*
this))
2491 SymbolSet::Factory &F = getMembersFactory(State);
2492 return F.add(F.getEmptySet(), getRepresentativeSymbol());
2496 return State->get<ClassMembers>(*this) ==
nullptr;
2508 return markDisequal(RF, State, find(State,
First), find(State, Second));
2513 EquivalenceClass
First,
2514 EquivalenceClass Second) {
2515 return First.markDisequal(RF, State, Second);
2520 EquivalenceClass
Other)
const {
2523 if (*
this ==
Other) {
2527 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2528 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2532 if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *
this,
2534 !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State,
Other,
2538 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2539 "a state with infeasible constraints");
2541 State = State->set<DisequalityMap>(DisequalityInfo);
2542 State = State->set<ConstraintRange>(Constraints);
2547inline bool EquivalenceClass::addToDisequalityInfo(
2548 DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2550 EquivalenceClass Second) {
2553 DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2554 ClassSet::Factory &
CF = State->get_context<ClassSet>();
2555 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2558 const ClassSet *CurrentSet = Info.lookup(
First);
2559 ClassSet NewSet = CurrentSet ? *CurrentSet :
CF.getEmptySet();
2560 NewSet =
CF.add(NewSet, Second);
2562 Info = F.add(Info,
First, NewSet);
2569 if (
const RangeSet *SecondConstraint = Constraints.lookup(Second))
2570 if (
const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2572 RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
2573 RF, State,
First.getRepresentativeSymbol());
2575 FirstConstraint = RF.
deletePoint(FirstConstraint, *Point);
2579 if (FirstConstraint.
isEmpty())
2582 Constraints = CRF.add(Constraints,
First, FirstConstraint);
2588inline std::optional<bool> EquivalenceClass::areEqual(
ProgramStateRef State,
2591 return EquivalenceClass::areEqual(State, find(State, FirstSym),
2592 find(State, SecondSym));
2595inline std::optional<bool> EquivalenceClass::areEqual(
ProgramStateRef State,
2596 EquivalenceClass
First,
2597 EquivalenceClass Second) {
2599 if (
First == Second)
2604 ClassSet DisequalToFirst =
First.getDisequalClasses(State);
2605 if (DisequalToFirst.contains(Second))
2609 return std::nullopt;
2615 SymbolSet ClsMembers = getClassMembers(State);
2616 assert(ClsMembers.contains(Old));
2619 SymbolSet::Factory &F = getMembersFactory(State);
2620 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2621 ClsMembers = F.remove(ClsMembers, Old);
2624 assert(!ClsMembers.isEmpty() &&
2625 "Class should have had at least two members before member removal");
2627 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2628 ClassMembersMap = EMFactory.add(ClassMembersMap, *
this, ClsMembers);
2629 State = State->set<ClassMembers>(ClassMembersMap);
2632 ClassMapTy Classes = State->get<ClassMap>();
2633 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2634 Classes = CMF.remove(Classes, Old);
2635 State = State->set<ClassMap>(Classes);
2650 return State->assume(DefinedVal,
false);
2655 State = State->assume(DefinedVal,
true);
2662 return State->assumeInclusiveRange(DefinedVal, Constraint->
getMinValue(),
2675 for (
const SymbolRef &MemberSym : ClassMembers) {
2683 const llvm::APSInt &SV = CI->getValue();
2684 const RangeSet *ClassConstraint = getConstraint(State,
Class);
2686 if (ClassConstraint && !ClassConstraint->
contains(SV))
2690 if (SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
2695 State = merge(F, State, MemberSym, SimplifiedMemberSym);
2699 if (OldState == State)
2715 State = find(State, MemberSym).removeMember(State, MemberSym);
2719 const RangeSet *ClassConstraint = getConstraint(State,
Class);
2740 State =
reAssume(State, ClassConstraint, SimplifiedMemberVal);
2748inline ClassSet EquivalenceClass::getDisequalClasses(
ProgramStateRef State,
2750 return find(State, Sym).getDisequalClasses(State);
2755 return getDisequalClasses(State->get<DisequalityMap>(),
2756 State->get_context<ClassSet>());
2760EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2761 ClassSet::Factory &Factory)
const {
2762 if (
const ClassSet *DisequalClasses = Map.lookup(*
this))
2763 return *DisequalClasses;
2765 return Factory.getEmptySet();
2769 ClassMembersTy Members = State->get<ClassMembers>();
2771 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2774 if (find(State,
Member) == ClassMembersPair.first) {
2782 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2783 for (std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2784 EquivalenceClass
Class = DisequalityInfo.first;
2785 ClassSet DisequalClasses = DisequalityInfo.second;
2788 if (DisequalClasses.isEmpty())
2793 for (EquivalenceClass DisequalClass : DisequalClasses) {
2794 const ClassSet *DisequalToDisequalClasses =
2795 Disequalities.lookup(DisequalClass);
2798 if (!DisequalToDisequalClasses ||
2799 !DisequalToDisequalClasses->contains(
Class))
2811bool RangeConstraintManager::canReasonAbout(
SVal X)
const {
2813 if (SymVal && SymVal->isExpression()) {
2814 const SymExpr *SE = SymVal->getSymbol();
2816 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
2817 switch (SIE->getOpcode()) {
2837 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
2859 const RangeSet *Ranges = getConstraint(State, Sym);
2881const llvm::APSInt *RangeConstraintManager::getSymVal(
ProgramStateRef St,
2883 return getRange(St, Sym).getConcreteValue();
2886const llvm::APSInt *RangeConstraintManager::getSymMinVal(
ProgramStateRef St,
2889 return Range.isEmpty() ? nullptr : &
Range.getMinValue();
2892const llvm::APSInt *RangeConstraintManager::getSymMaxVal(
ProgramStateRef St,
2895 return Range.isEmpty() ? nullptr : &
Range.getMaxValue();
2907 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2908 ClassMembersTy NewClassMembersMap = ClassMembersMap;
2909 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2910 SymbolSet::Factory &SetFactory = State->get_context<
SymbolSet>();
2912 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2913 ConstraintRangeTy NewConstraints = Constraints;
2914 ConstraintRangeTy::Factory &ConstraintFactory =
2915 State->get_context<ConstraintRange>();
2917 ClassMapTy Map = State->get<ClassMap>();
2918 ClassMapTy NewMap = Map;
2919 ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2921 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2922 DisequalityMapTy::Factory &DisequalityFactory =
2923 State->get_context<DisequalityMap>();
2924 ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
2926 bool ClassMapChanged =
false;
2927 bool MembersMapChanged =
false;
2928 bool ConstraintMapChanged =
false;
2929 bool DisequalitiesChanged =
false;
2931 auto removeDeadClass = [&](EquivalenceClass
Class) {
2933 Constraints = ConstraintFactory.remove(Constraints,
Class);
2934 ConstraintMapChanged =
true;
2938 ClassSet DisequalClasses =
2939 Class.getDisequalClasses(Disequalities, ClassSetFactory);
2940 if (!DisequalClasses.isEmpty()) {
2941 for (EquivalenceClass DisequalClass : DisequalClasses) {
2942 ClassSet DisequalToDisequalSet =
2943 DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
2946 assert(!DisequalToDisequalSet.isEmpty());
2947 ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet,
Class);
2950 if (NewSet.isEmpty()) {
2952 DisequalityFactory.remove(Disequalities, DisequalClass);
2955 DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
2959 Disequalities = DisequalityFactory.remove(Disequalities,
Class);
2960 DisequalitiesChanged =
true;
2965 for (std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
2967 EquivalenceClass
Class = ClassConstraintPair.first;
2968 if (
Class.isTriviallyDead(State, SymReaper)) {
2970 removeDeadClass(
Class);
2975 for (std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
2978 if (SymReaper.
isDead(Sym)) {
2979 ClassMapChanged =
true;
2980 NewMap = ClassFactory.remove(NewMap, Sym);
2986 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
2988 EquivalenceClass
Class = ClassMembersPair.first;
2989 SymbolSet LiveMembers = ClassMembersPair.second;
2990 bool MembersChanged =
false;
2994 MembersChanged =
true;
2995 LiveMembers = SetFactory.remove(LiveMembers,
Member);
3000 if (!MembersChanged)
3003 MembersMapChanged =
true;
3005 if (LiveMembers.isEmpty()) {
3007 NewClassMembersMap = EMFactory.remove(NewClassMembersMap,
Class);
3010 removeDeadClass(
Class);
3013 NewClassMembersMap =
3014 EMFactory.add(NewClassMembersMap,
Class, LiveMembers);
3021 if (ClassMapChanged)
3022 State = State->set<ClassMap>(NewMap);
3024 if (MembersMapChanged)
3025 State = State->set<ClassMembers>(NewClassMembersMap);
3027 if (ConstraintMapChanged)
3028 State = State->set<ConstraintRange>(Constraints);
3030 if (DisequalitiesChanged)
3031 State = State->set<DisequalityMap>(Disequalities);
3033 assert(EquivalenceClass::isClassDataConsistent(State));
3040 return SymbolicRangeInferrer::inferRange(F, State, Sym);
3046 return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym,
Range);
3063 const llvm::APSInt &Int,
3064 const llvm::APSInt &Adjustment) {
3070 llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3074 return setRange(St, Sym, New);
3079 const llvm::APSInt &Int,
3080 const llvm::APSInt &Adjustment) {
3087 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3091 return setRange(St, Sym, New);
3096 const llvm::APSInt &Int,
3097 const llvm::APSInt &Adjustment)
const {
3100 switch (AdjustmentType.testInRange(Int,
true)) {
3110 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3111 llvm::APSInt
Min = AdjustmentType.getMinValue();
3112 if (ComparisonVal ==
Min)
3115 llvm::APSInt Lower =
Min - Adjustment;
3116 llvm::APSInt Upper = ComparisonVal - Adjustment;
3125 const llvm::APSInt &Int,
3126 const llvm::APSInt &Adjustment) {
3127 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
3128 return setRange(St, Sym, New);
3133 const llvm::APSInt &Int,
3134 const llvm::APSInt &Adjustment)
const {
3137 switch (AdjustmentType.testInRange(Int,
true)) {
3147 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3148 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3149 if (ComparisonVal ==
Max)
3152 llvm::APSInt Lower = ComparisonVal - Adjustment;
3153 llvm::APSInt Upper =
Max - Adjustment;
3157 return F.
intersect(SymRange, Lower, Upper);
3162 const llvm::APSInt &Int,
3163 const llvm::APSInt &Adjustment) {
3164 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
3165 return setRange(St, Sym, New);
3170 const llvm::APSInt &Int,
3171 const llvm::APSInt &Adjustment)
const {
3174 switch (AdjustmentType.testInRange(Int,
true)) {
3184 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3185 llvm::APSInt
Min = AdjustmentType.getMinValue();
3186 if (ComparisonVal ==
Min)
3189 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3190 llvm::APSInt Lower = ComparisonVal - Adjustment;
3191 llvm::APSInt Upper =
Max - Adjustment;
3194 return F.
intersect(SymRange, Lower, Upper);
3199 const llvm::APSInt &Int,
3200 const llvm::APSInt &Adjustment) {
3201 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
3202 return setRange(St, Sym, New);
3206RangeConstraintManager::getSymLERange(llvm::function_ref<
RangeSet()> RS,
3207 const llvm::APSInt &Int,
3208 const llvm::APSInt &Adjustment)
const {
3211 switch (AdjustmentType.testInRange(Int,
true)) {
3221 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3222 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3223 if (ComparisonVal ==
Max)
3226 llvm::APSInt
Min = AdjustmentType.getMinValue();
3227 llvm::APSInt Lower =
Min - Adjustment;
3228 llvm::APSInt Upper = ComparisonVal - Adjustment;
3236 const llvm::APSInt &Int,
3237 const llvm::APSInt &Adjustment)
const {
3238 return getSymLERange([&] {
return getRange(St, Sym); },
Int, Adjustment);
3243 const llvm::APSInt &Int,
3244 const llvm::APSInt &Adjustment) {
3245 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
3246 return setRange(St, Sym, New);
3251 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
3252 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
3255 RangeSet Out = getSymLERange([&] {
return New; }, To, Adjustment);
3256 return setRange(State, Sym, Out);
3259ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
3261 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
3262 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
3263 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
3265 return setRange(State, Sym, New);
3272void RangeConstraintManager::printJson(raw_ostream &Out,
ProgramStateRef State,
3273 const char *NL,
unsigned int Space,
3275 printConstraints(Out, State, NL, Space, IsDot);
3276 printEquivalenceClasses(Out, State, NL, Space, IsDot);
3277 printDisequalities(Out, State, NL, Space, IsDot);
3280void RangeConstraintManager::printValue(raw_ostream &Out,
ProgramStateRef State,
3284 Out <<
"<empty rangeset>";
3293 llvm::raw_string_ostream O(S);
3298void RangeConstraintManager::printConstraints(raw_ostream &Out,
3303 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
3305 Indent(Out, Space, IsDot) <<
"\"constraints\": ";
3306 if (Constraints.isEmpty()) {
3307 Out <<
"null," << NL;
3311 std::map<std::string, RangeSet> OrderedConstraints;
3312 for (std::pair<EquivalenceClass, RangeSet>
P : Constraints) {
3313 SymbolSet ClassMembers =
P.first.getClassMembers(State);
3314 for (
const SymbolRef &ClassMember : ClassMembers) {
3315 bool insertion_took_place;
3316 std::tie(std::ignore, insertion_took_place) =
3317 OrderedConstraints.insert({
toString(ClassMember),
P.second});
3318 assert(insertion_took_place &&
3319 "two symbols should not have the same dump");
3326 for (std::pair<std::string, RangeSet>
P : OrderedConstraints) {
3333 Indent(Out, Space, IsDot)
3334 <<
"{ \"symbol\": \"" <<
P.first <<
"\", \"range\": \"";
3341 Indent(Out, Space, IsDot) <<
"]," << NL;
3347 ClassMembers.end());
3348 llvm::sort(ClassMembersSorted,
3353 bool FirstMember =
true;
3356 llvm::raw_string_ostream Out(Str);
3358 for (
SymbolRef ClassMember : ClassMembersSorted) {
3360 FirstMember =
false;
3363 Out <<
"\"" << ClassMember <<
"\"";
3369void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3374 ClassMembersTy Members = State->get<ClassMembers>();
3376 Indent(Out, Space, IsDot) <<
"\"equivalence_classes\": ";
3377 if (Members.isEmpty()) {
3378 Out <<
"null," << NL;
3382 std::set<std::string> MembersStr;
3383 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3384 MembersStr.insert(
toString(State, ClassToSymbolSet.first));
3388 bool FirstClass =
true;
3389 for (
const std::string &Str : MembersStr) {
3396 Indent(Out, Space, IsDot);
3402 Indent(Out, Space, IsDot) <<
"]," << NL;
3405void RangeConstraintManager::printDisequalities(raw_ostream &Out,
3410 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3412 Indent(Out, Space, IsDot) <<
"\"disequality_info\": ";
3413 if (Disequalities.isEmpty()) {
3414 Out <<
"null," << NL;
3420 using EqClassesStrTy = std::set<std::string>;
3421 using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3422 DisequalityInfoStrTy DisequalityInfoStr;
3423 for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3424 EquivalenceClass
Class = ClassToDisEqSet.first;
3425 ClassSet DisequalClasses = ClassToDisEqSet.second;
3426 EqClassesStrTy MembersStr;
3427 for (EquivalenceClass DisEqClass : DisequalClasses)
3428 MembersStr.insert(
toString(State, DisEqClass));
3429 DisequalityInfoStr.insert({
toString(State,
Class), MembersStr});
3434 bool FirstClass =
true;
3435 for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3436 DisequalityInfoStr) {
3437 const std::string &
Class = ClassToDisEqSet.first;
3444 Indent(Out, Space, IsDot) <<
"{" << NL;
3445 unsigned int DisEqSpace = Space + 1;
3446 Indent(Out, DisEqSpace, IsDot) <<
"\"class\": ";
3448 const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3449 if (!DisequalClasses.empty()) {
3451 Indent(Out, DisEqSpace, IsDot) <<
"\"disequal_to\": [" << NL;
3452 unsigned int DisEqClassSpace = DisEqSpace + 1;
3453 Indent(Out, DisEqClassSpace, IsDot);
3454 bool FirstDisEqClass =
true;
3455 for (
const std::string &DisEqClass : DisequalClasses) {
3456 if (FirstDisEqClass) {
3457 FirstDisEqClass =
false;
3460 Indent(Out, DisEqClassSpace, IsDot);
3466 Indent(Out, Space, IsDot) <<
"}";
3471 Indent(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 SymSymExpr * getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
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...