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];
112const RangeSet::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));
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;
177 iterator FirstEnd = LHS.end();
178 iterator Second = RHS.begin();
179 iterator SecondEnd = RHS.end();
180 APSIntType Ty = APSIntType(
First->From());
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))
479 ContainerType DummyContainer;
481 if (Lower <= Upper) {
495 DummyContainer.push_back(
496 Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
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));
605 if (LHS.containsImpl(Point))
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));
708 assert(
T->isIntegralOrEnumerationType() &&
"T shall be an integral type.");
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();
729 APSInt ToInt = R.To();
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 {
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;
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]] [[maybe_unused]]
static bool
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]] [[maybe_unused]]
bool areFeasible(ConstraintRangeTy Constraints) {
1045 return llvm::none_of(
1047 [](
const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1048 return ClassConstraint.second.isEmpty();
1052[[nodiscard]]
inline const RangeSet *getConstraint(
ProgramStateRef State,
1053 EquivalenceClass
Class) {
1054 return State->get<ConstraintRange>(
Class);
1057[[nodiscard]]
inline const RangeSet *getConstraint(
ProgramStateRef State,
1059 return getConstraint(State, EquivalenceClass::find(State, Sym));
1063 EquivalenceClass
Class,
1064 RangeSet Constraint) {
1065 return State->set<ConstraintRange>(
Class, Constraint);
1069 ConstraintRangeTy Constraints) {
1070 return State->set<ConstraintRange>(Constraints);
1086std::optional<bool> meansEquality(
const SymSymExpr *Sym) {
1098 return std::nullopt;
1106template <
class SecondTy,
class... RestTy>
1108 SecondTy Second, RestTy... Tail);
1110template <
class... RangeTy>
struct IntersectionTraits;
1112template <
class... TailTy>
struct IntersectionTraits<RangeSet, TailTy...> {
1114 using Type = RangeSet;
1117template <>
struct IntersectionTraits<> {
1120 using Type = std::optional<RangeSet>;
1123template <
class OptionalOrPointer,
class... TailTy>
1124struct IntersectionTraits<OptionalOrPointer, TailTy...> {
1126 using Type =
typename IntersectionTraits<TailTy...>
::Type;
1129template <
class EndTy>
1136[[nodiscard]] [[maybe_unused]]
inline std::optional<RangeSet>
1143 return std::nullopt;
1146template <
class... RestTy>
1148 RangeSet Second, RestTy... Tail) {
1151 return intersect(F, F.
intersect(Head, Second), Tail...);
1154template <
class SecondTy,
class... RestTy>
1156 SecondTy Second, RestTy... Tail) {
1159 return intersect(F, Head, *Second, Tail...);
1163 return intersect(F, Head, Tail...);
1187template <
class HeadTy,
class SecondTy,
class... RestTy>
1189 typename IntersectionTraits<HeadTy, SecondTy, RestTy...>
::Type
1193 return intersect(F, *Head, Second, Tail...);
1195 return intersect(F, Second, Tail...);
1207class SymbolicRangeInferrer
1208 :
public SymExprVisitor<SymbolicRangeInferrer, RangeSet> {
1210 template <
class SourceType>
1212 SourceType Origin) {
1213 SymbolicRangeInferrer Inferrer(F, State);
1214 return Inferrer.infer(Origin);
1218 if (std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1227 RangeSet VisitUnarySymExpr(
const UnarySymExpr *USE) {
1228 if (std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1233 RangeSet VisitSymIntExpr(
const SymIntExpr *Sym) {
1234 return VisitBinaryOperator(Sym);
1237 RangeSet VisitIntSymExpr(
const IntSymExpr *Sym) {
1238 return VisitBinaryOperator(Sym);
1241 RangeSet VisitSymSymExpr(
const SymSymExpr *SSE) {
1250 getRangeForNegatedSymSym(SSE),
1252 getRangeCommutativeSymSym(SSE),
1256 getRangeForComparisonSymbol(SSE),
1259 getRangeForEqualities(SSE),
1261 VisitBinaryOperator(SSE));
1266 : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
1272 RangeSet inferAs(
const llvm::APSInt &Val, QualType) {
1273 return {RangeFactory, Val};
1277 RangeSet inferAs(
SymbolRef Sym, QualType DestType) {
1278 QualType ActualType = Sym->
getType();
1286 return infer(DestType);
1290 return intersect(RangeFactory,
1293 getConstraint(State, Sym),
1299 RangeSet infer(EquivalenceClass
Class) {
1300 if (
const RangeSet *AssociatedConstraint = getConstraint(State,
Class))
1301 return *AssociatedConstraint;
1303 return infer(
Class.getType());
1307 RangeSet infer(QualType
T) {
1310 RangeSet
Result(RangeFactory, ValueFactory.getMinValue(
T),
1311 ValueFactory.getMaxValue(
T));
1315 return assumeNonZero(
Result,
T);
1320 template <
class BinarySymExprTy>
1321 RangeSet VisitBinaryOperator(
const BinarySymExprTy *Sym) {
1333 QualType ResultType = Sym->getType();
1334 return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1336 inferAs(Sym->getRHS(), ResultType), ResultType);
1340 RangeSet RHS, QualType
T);
1351 static Range fillGaps(RangeSet Origin) {
1359 std::optional<Range> convert(
const Range &Origin, APSIntType To) {
1362 return std::nullopt;
1364 return Range(ValueFactory.Convert(To, Origin.
From()),
1365 ValueFactory.Convert(To, Origin.
To()));
1368 template <BinaryOperator::Opcode Op>
1369 RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType
T) {
1372 Range CoarseLHS = fillGaps(LHS);
1373 Range CoarseRHS = fillGaps(RHS);
1375 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1379 auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1380 auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1384 if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1388 return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS,
T);
1391 template <BinaryOperator::Opcode Op>
1392 RangeSet VisitBinaryOperator(Range LHS, Range RHS, QualType
T) {
1402 auto Eval = [&](
const llvm::APSInt &L,
1403 const llvm::APSInt &
R) -> std::optional<llvm::APSInt> {
1404 bool Overflow =
false;
1408 Result = IsUnsigned ? L.uadd_ov(R, Overflow) : L.sadd_ov(R, Overflow);
1411 Result = IsUnsigned ? L.usub_ov(R, Overflow) : L.ssub_ov(R, Overflow);
1414 Result = IsUnsigned ? L.umul_ov(R, Overflow) : L.smul_ov(R, Overflow);
1417 llvm_unreachable(
"only +, - and * are handled here");
1420 return std::nullopt;
1421 return llvm::APSInt(
Result, IsUnsigned);
1426 std::optional<llvm::APSInt>
Min,
Max;
1427 for (
const llvm::APSInt &L : {LHS.
From(), LHS.
To()}) {
1428 for (
const llvm::APSInt &R : {RHS.
From(), RHS.
To()}) {
1429 std::optional<llvm::APSInt> Corner = Eval(L, R);
1432 if (!Corner.has_value())
1434 if (!
Min || Corner.value() < *
Min)
1436 if (!
Max || Corner.value() > *
Max)
1440 return RangeSet{RangeFactory, ValueFactory.getValue(
Min.value()),
1441 ValueFactory.getValue(
Max.value())};
1452 Range getSymmetricalRange(Range Origin, QualType
T) {
1453 APSIntType RangeType = ValueFactory.getAPSIntType(
T);
1456 return Range(ValueFactory.getMinValue(RangeType), Origin.
To());
1459 if (Origin.
From().isMinSignedValue()) {
1463 return {ValueFactory.getMinValue(RangeType),
1464 ValueFactory.getMaxValue(RangeType)};
1478 llvm::APSInt AbsMax = std::max(-Origin.
From(), Origin.
To());
1481 return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
1485 RangeSet assumeNonZero(RangeSet
Domain, QualType
T) {
1486 APSIntType IntType = ValueFactory.getAPSIntType(
T);
1490 template <
typename ProduceNegatedSymFunc>
1491 std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1496 return std::nullopt;
1499 if (
const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1500 return RangeFactory.negate(*NegatedRange);
1502 return std::nullopt;
1505 std::optional<RangeSet> getRangeForNegatedUnarySym(
const UnarySymExpr *USE) {
1508 return getRangeForNegatedExpr(
1517 std::optional<RangeSet> getRangeForNegatedSymSym(
const SymSymExpr *SSE) {
1518 return getRangeForNegatedExpr(
1519 [SSE, State = this->State]() ->
SymbolRef {
1521 return State->getSymbolManager().acquire<
SymSymExpr>(
1528 std::optional<RangeSet> getRangeForNegatedSym(
SymbolRef Sym) {
1529 return getRangeForNegatedExpr(
1530 [Sym, State = this->State]() {
1531 return State->getSymbolManager().acquire<UnarySymExpr>(
1532 Sym, UO_Minus, Sym->
getType());
1537 std::optional<RangeSet> getRangeCommutativeSymSym(
const SymSymExpr *SSE) {
1539 bool IsCommutative = llvm::is_contained(
1541 {BO_EQ, BO_NE, BO_Or, BO_And, BO_Add, BO_Mul, BO_Xor}, Op);
1543 return std::nullopt;
1547 if (
const RangeSet *Range = getConstraint(State, Commuted))
1549 return std::nullopt;
1562 std::optional<RangeSet> getRangeForComparisonSymbol(
const SymSymExpr *SSE) {
1567 return std::nullopt;
1569 static const OperatorRelationsTable CmpOpTable{};
1571 const SymExpr *LHS = SSE->
getLHS();
1572 const SymExpr *RHS = SSE->
getRHS();
1575 SymbolManager &SymMgr = State->getSymbolManager();
1592 const RangeSet *QueriedRangeSet = getConstraint(State, SymSym);
1596 if (!QueriedRangeSet) {
1600 QueriedRangeSet = getConstraint(State, SymSym);
1603 if (!QueriedRangeSet || QueriedRangeSet->isEmpty())
1606 const llvm::APSInt *ConcreteValue = QueriedRangeSet->getConcreteValue();
1607 const bool isInFalseBranch =
1608 ConcreteValue ? (*ConcreteValue == 0) :
false;
1613 if (isInFalseBranch)
1620 if (LastQueriedOpToUnknown != CurrentOP &&
1621 LastQueriedOpToUnknown != QueriedOP) {
1629 LastQueriedOpToUnknown = QueriedOP;
1638 return std::nullopt;
1641 std::optional<RangeSet> getRangeForEqualities(
const SymSymExpr *Sym) {
1642 std::optional<bool>
Equality = meansEquality(Sym);
1645 return std::nullopt;
1647 if (std::optional<bool> AreEqual =
1648 EquivalenceClass::areEqual(State, Sym->
getLHS(), Sym->
getRHS())) {
1652 if (*AreEqual == *Equality) {
1653 return getTrueRange(Sym->
getType());
1656 return getFalseRange(Sym->
getType());
1659 return std::nullopt;
1662 RangeSet getTrueRange(QualType
T) {
1663 RangeSet TypeRange = infer(
T);
1664 return assumeNonZero(TypeRange,
T);
1667 RangeSet getFalseRange(QualType
T) {
1668 const llvm::APSInt &
Zero = ValueFactory.getValue(0,
T);
1669 return RangeSet(RangeFactory,
Zero);
1672 BasicValueFactory &ValueFactory;
1682RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_NE>(RangeSet LHS,
1688 if (intersect(RangeFactory, LHS, RHS).isEmpty())
1689 return getTrueRange(
T);
1708 return getTrueRange(
T);
1713 return getTrueRange(
T);
1721 RangeSet CastedLHS = RangeFactory.castTo(LHS, CastingType);
1722 RangeSet CastedRHS = RangeFactory.castTo(RHS, CastingType);
1724 if (intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1725 return getTrueRange(
T);
1733RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS,
1735 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1738 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1739 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1741 bool IsLHSNegative = LHS.
To() <
Zero;
1742 bool IsRHSNegative = RHS.
To() <
Zero;
1745 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1746 (IsLHSNegative && IsRHSNegative)) {
1748 const llvm::APSInt &
Min = std::max(LHS.
From(), RHS.
From());
1761 const llvm::APSInt &
Max = IsLHSNegative
1762 ? ValueFactory.getValue(--
Zero)
1763 : ValueFactory.getMaxValue(ResultType);
1765 return {RangeFactory, ValueFactory.getValue(
Min),
Max};
1769 if (IsLHSNegative || IsRHSNegative) {
1771 return {RangeFactory, ValueFactory.getMinValue(ResultType),
1772 ValueFactory.getValue(--
Zero)};
1775 RangeSet DefaultRange = infer(
T);
1782 return assumeNonZero(DefaultRange,
T);
1786 return DefaultRange;
1790RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(Range LHS,
1793 APSIntType ResultType = ValueFactory.getAPSIntType(
T);
1796 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1797 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1799 bool IsLHSNegative = LHS.
To() <
Zero;
1800 bool IsRHSNegative = RHS.
To() <
Zero;
1803 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1804 (IsLHSNegative && IsRHSNegative)) {
1806 const llvm::APSInt &
Max = std::min(LHS.
To(), RHS.
To());
1810 const llvm::APSInt &
Min = IsLHSNegative
1811 ? ValueFactory.getMinValue(ResultType)
1812 : ValueFactory.getValue(
Zero);
1814 return {RangeFactory,
Min,
Max};
1818 if (IsLHSPositiveOrZero || IsRHSPositiveOrZero) {
1823 const llvm::APSInt &
Max = IsLHSPositiveOrZero ? LHS.
To() : RHS.
To();
1827 return {RangeFactory, ValueFactory.getValue(
Zero),
1828 ValueFactory.getValue(
Max)};
1836RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS,
1839 llvm::APSInt
Zero = ValueFactory.getAPSIntType(
T).getZeroValue();
1841 Range ConservativeRange = getSymmetricalRange(RHS,
T);
1843 llvm::APSInt
Max = ConservativeRange.
To();
1844 llvm::APSInt
Min = ConservativeRange.
From();
1850 return RangeFactory.getEmptySet();
1863 if (
Min.isSigned()) {
1868 bool IsLHSPositiveOrZero = LHS.
From() >=
Zero;
1869 bool IsRHSPositiveOrZero = RHS.
From() >=
Zero;
1873 if (IsLHSPositiveOrZero && IsRHSPositiveOrZero) {
1889 return {RangeFactory, ValueFactory.getValue(
Min), ValueFactory.getValue(
Max)};
1893RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Add>(Range LHS,
1896 return inferFromCorners(BO_Add, LHS, RHS,
T);
1900RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Sub>(Range LHS,
1903 return inferFromCorners(BO_Sub, LHS, RHS,
T);
1907RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Mul>(Range LHS,
1910 return inferFromCorners(BO_Mul, LHS, RHS,
T);
1913RangeSet SymbolicRangeInferrer::VisitBinaryOperator(RangeSet LHS,
1915 RangeSet RHS, QualType
T) {
1919 return RangeFactory.getEmptySet();
1924 return VisitBinaryOperator<BO_NE>(LHS, RHS,
T);
1926 return VisitBinaryOperator<BO_Or>(LHS, RHS,
T);
1928 return VisitBinaryOperator<BO_And>(LHS, RHS,
T);
1930 return VisitBinaryOperator<BO_Rem>(LHS, RHS,
T);
1932 return VisitBinaryOperator<BO_Add>(LHS, RHS,
T);
1934 return VisitBinaryOperator<BO_Sub>(LHS, RHS,
T);
1936 return VisitBinaryOperator<BO_Mul>(LHS, RHS,
T);
1946class RangeConstraintManager :
public RangedConstraintManager {
1948 RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB)
1949 : RangedConstraintManager(EE, SVB), F(getBasicVals()) {}
1960 return S1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1961 S1->get<ClassMap>() == S2->get<ClassMap>();
1964 bool canReasonAbout(SVal
X)
const override;
1978 SymbolReaper &SymReaper)
override;
1980 void printJson(raw_ostream &Out,
ProgramStateRef State,
const char *NL =
"\n",
1981 unsigned int Space = 0,
bool IsDot =
false)
const override;
1985 const char *NL =
"\n",
unsigned int Space = 0,
1986 bool IsDot =
false)
const;
1988 const char *NL =
"\n",
unsigned int Space = 0,
1989 bool IsDot =
false)
const;
1991 const char *NL =
"\n",
unsigned int Space = 0,
1992 bool IsDot =
false)
const;
1999 const llvm::APSInt &
V,
2000 const llvm::APSInt &Adjustment)
override;
2003 const llvm::APSInt &
V,
2004 const llvm::APSInt &Adjustment)
override;
2007 const llvm::APSInt &
V,
2008 const llvm::APSInt &Adjustment)
override;
2011 const llvm::APSInt &
V,
2012 const llvm::APSInt &Adjustment)
override;
2015 const llvm::APSInt &
V,
2016 const llvm::APSInt &Adjustment)
override;
2019 const llvm::APSInt &
V,
2020 const llvm::APSInt &Adjustment)
override;
2024 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
2028 const llvm::APSInt &To,
const llvm::APSInt &Adjustment)
override;
2038 const llvm::APSInt &Int,
2039 const llvm::APSInt &Adjustment)
const;
2041 const llvm::APSInt &Int,
2042 const llvm::APSInt &Adjustment)
const;
2044 const llvm::APSInt &Int,
2045 const llvm::APSInt &Adjustment)
const;
2046 RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS,
2047 const llvm::APSInt &Int,
2048 const llvm::APSInt &Adjustment)
const;
2050 const llvm::APSInt &Int,
2051 const llvm::APSInt &Adjustment)
const;
2072template <
class Derived>
class ConstraintAssignorBase {
2074 using Const =
const llvm::APSInt &;
2076#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
2078#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \
2079 if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \
2083 assignImpl(Sym, Constraint);
2086 bool assignImpl(
SymbolRef Sym, RangeSet Constraint) {
2088#define SYMBOL(Id, Parent) \
2089 case SymExpr::Id##Kind: \
2091#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2093 llvm_unreachable(
"Unknown SymExpr kind!");
2096#define DEFAULT_ASSIGN(Id) \
2097 bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \
2100 bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
2101 bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
2107#define CONSTRAINT_DISPATCH(Id) \
2108 if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \
2109 ASSIGN(Id, Const, Sym, *Const); \
2111 if (Constraint.size() == 1) { \
2112 ASSIGN(Id, Range, Sym, *Constraint.begin()); \
2114 ASSIGN(Id, RangeSet, Sym, Constraint)
2119#define SYMBOL(Id, Parent) \
2120 bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \
2121 CONSTRAINT_DISPATCH(Id); \
2125#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
2126#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2136#undef CONSTRAINT_DISPATCH
2137#undef DEFAULT_ASSIGN
2152class ConstraintAssignor :
public ConstraintAssignorBase<ConstraintAssignor> {
2154 template <
class ClassOrSymbol>
2157 ClassOrSymbol CoS, RangeSet NewConstraint) {
2158 if (!State || NewConstraint.
isEmpty())
2161 ConstraintAssignor Assignor{State, Builder, F};
2162 return Assignor.assign(CoS, NewConstraint);
2166 template <
typename SymT>
2167 bool handleRemainderOp(
const SymT *Sym, RangeSet Constraint) {
2168 if (Sym->getOpcode() != BO_Rem)
2172 SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2173 if (
auto NonLocSymSVal = SymSVal.
getAs<nonloc::SymbolVal>()) {
2174 State = State->assume(*NonLocSymSVal,
true);
2182 inline bool assignSymExprToConst(
const SymExpr *Sym, Const Constraint);
2183 inline bool assignSymIntExprToRangeSet(
const SymIntExpr *Sym,
2184 RangeSet Constraint) {
2185 return handleRemainderOp(Sym, Constraint);
2187 inline bool assignSymSymExprToRangeSet(
const SymSymExpr *Sym,
2188 RangeSet Constraint);
2193 : State(State), Builder(Builder), RangeFactory(F) {}
2194 using Base = ConstraintAssignorBase<ConstraintAssignor>;
2200 State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2206 Base::assign(Sym, NewConstraint);
2212 RangeSet NewConstraint) {
2220 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2221 ConstraintRangeTy::Factory &
CF = State->get_context<ConstraintRange>();
2224 Constraints =
CF.add(Constraints,
Class, NewConstraint);
2226 for (EquivalenceClass DisequalClass :
Class.getDisequalClasses(State)) {
2227 RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
2228 RangeFactory, State, DisequalClass);
2230 UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2234 if (UpdatedConstraint.
isEmpty())
2237 Constraints =
CF.add(Constraints, DisequalClass, UpdatedConstraint);
2239 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2240 "a state with infeasible constraints");
2242 return setConstraints(State, Constraints);
2245 return setConstraint(State,
Class, NewConstraint);
2250 return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2255 return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2258 [[nodiscard]] std::optional<bool> interpreteAsBool(RangeSet Constraint) {
2259 assert(!Constraint.
isEmpty() &&
"Empty ranges shouldn't get here");
2267 return std::nullopt;
2271 SValBuilder &Builder;
2275bool ConstraintAssignor::assignSymExprToConst(
const SymExpr *Sym,
2276 const llvm::APSInt &Constraint) {
2277 llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2279 ClassMembersTy Members = State->get<ClassMembers>();
2280 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2281 EquivalenceClass
Class = ClassToSymbolSet.first;
2282 State = EquivalenceClass::simplify(Builder, RangeFactory, State,
Class);
2285 SimplifiedClasses.insert(
Class);
2291 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2292 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2293 EquivalenceClass
Class = ClassConstraint.first;
2294 if (SimplifiedClasses.count(
Class))
2296 State = EquivalenceClass::simplify(Builder, RangeFactory, State,
Class);
2303 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2304 for (std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2306 EquivalenceClass
Class = DisequalityEntry.first;
2307 ClassSet DisequalClasses = DisequalityEntry.second;
2308 State = EquivalenceClass::simplify(Builder, RangeFactory, State,
Class);
2316bool ConstraintAssignor::assignSymSymExprToRangeSet(
const SymSymExpr *Sym,
2317 RangeSet Constraint) {
2318 if (!handleRemainderOp(Sym, Constraint))
2321 std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2323 if (!ConstraintAsBool)
2326 if (std::optional<bool> Equality = meansEquality(Sym)) {
2332 if (*Equality == *ConstraintAsBool) {
2333 State = trackEquality(State, Sym->
getLHS(), Sym->
getRHS());
2336 State = trackDisequality(State, Sym->
getLHS(), Sym->
getRHS());
2348std::unique_ptr<ConstraintManager>
2351 return std::make_unique<RangeConstraintManager>(Eng, StMgr.
getSValBuilder());
2355 ConstraintMap::Factory &F = State->get_context<
ConstraintMap>();
2358 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2359 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2360 EquivalenceClass
Class = ClassConstraint.first;
2362 assert(!ClassMembers.isEmpty() &&
2363 "Class must always have at least one member!");
2365 SymbolRef Representative = *ClassMembers.begin();
2366 Result = F.add(
Result, Representative, ClassConstraint.second);
2376LLVM_DUMP_METHOD
void EquivalenceClass::dumpToStream(
ProgramStateRef State,
2377 raw_ostream &os)
const {
2378 SymbolSet ClassMembers = getClassMembers(State);
2379 for (
const SymbolRef &MemberSym : ClassMembers) {
2387 assert(State &&
"State should not be null");
2388 assert(Sym &&
"Symbol should not be null");
2390 if (
const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2391 return *NontrivialClass;
2401 EquivalenceClass FirstClass = find(State,
First);
2402 EquivalenceClass SecondClass = find(State, Second);
2404 return FirstClass.merge(F, State, SecondClass);
2409 EquivalenceClass
Other) {
2425 if (
getType()->getCanonicalTypeUnqualified() !=
2426 Other.getType()->getCanonicalTypeUnqualified())
2429 SymbolSet Members = getClassMembers(State);
2435 if (Members.getHeight() >= OtherMembers.getHeight()) {
2436 return mergeImpl(F, State, Members,
Other, OtherMembers);
2438 return Other.mergeImpl(F, State, OtherMembers, *
this, Members);
2457 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2458 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2465 if (std::optional<RangeSet> NewClassConstraint =
2466 intersect(RangeFactory, getConstraint(State, *
this),
2467 getConstraint(State,
Other))) {
2473 if (NewClassConstraint->isEmpty())
2478 Constraints = CRF.remove(Constraints,
Other);
2480 Constraints = CRF.add(Constraints, *
this, *NewClassConstraint);
2482 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2483 "a state with infeasible constraints");
2485 State = State->set<ConstraintRange>(Constraints);
2489 ClassMapTy Classes = State->get<ClassMap>();
2490 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2492 ClassMembersTy Members = State->get<ClassMembers>();
2493 ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2495 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2496 DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2498 ClassSet::Factory &
CF = State->get_context<ClassSet>();
2499 SymbolSet::Factory &F = getMembersFactory(State);
2504 NewClassMembers = F.add(NewClassMembers, Sym);
2506 Classes = CMF.add(Classes, Sym, *
this);
2512 Members = MF.remove(Members,
Other);
2514 Members = MF.add(Members, *
this, NewClassMembers);
2517 ClassSet DisequalToOther =
Other.getDisequalClasses(DisequalityInfo,
CF);
2520 if (DisequalToOther.contains(*
this))
2523 if (!DisequalToOther.isEmpty()) {
2524 ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo,
CF);
2525 DisequalityInfo = DF.remove(DisequalityInfo,
Other);
2527 for (EquivalenceClass DisequalClass : DisequalToOther) {
2528 DisequalToThis =
CF.add(DisequalToThis, DisequalClass);
2533 ClassSet OriginalSetLinkedToOther =
2534 *DisequalityInfo.lookup(DisequalClass);
2538 ClassSet NewSet =
CF.remove(OriginalSetLinkedToOther,
Other);
2539 NewSet =
CF.add(NewSet, *
this);
2541 DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2544 DisequalityInfo = DF.add(DisequalityInfo, *
this, DisequalToThis);
2545 State = State->set<DisequalityMap>(DisequalityInfo);
2549 State = State->set<ClassMap>(Classes);
2550 State = State->set<ClassMembers>(Members);
2555inline SymbolSet::Factory &
2561 if (
const SymbolSet *Members = State->get<ClassMembers>(*
this))
2566 SymbolSet::Factory &F = getMembersFactory(State);
2567 return F.add(F.getEmptySet(), getRepresentativeSymbol());
2571 return State->get<ClassMembers>(*this) ==
nullptr;
2575 SymbolReaper &Reaper)
const {
2583 return markDisequal(RF, State, find(State,
First), find(State, Second));
2588 EquivalenceClass
First,
2589 EquivalenceClass Second) {
2590 return First.markDisequal(RF, State, Second);
2595 EquivalenceClass
Other)
const {
2598 if (*
this ==
Other) {
2602 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2603 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2607 if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *
this,
2609 !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State,
Other,
2613 assert(areFeasible(Constraints) &&
"Constraint manager shouldn't produce "
2614 "a state with infeasible constraints");
2616 State = State->set<DisequalityMap>(DisequalityInfo);
2617 State = State->set<ConstraintRange>(Constraints);
2622inline bool EquivalenceClass::addToDisequalityInfo(
2623 DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2625 EquivalenceClass Second) {
2628 DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2629 ClassSet::Factory &
CF = State->get_context<ClassSet>();
2630 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2633 const ClassSet *CurrentSet = Info.lookup(
First);
2634 ClassSet NewSet = CurrentSet ? *CurrentSet :
CF.getEmptySet();
2635 NewSet =
CF.add(NewSet, Second);
2637 Info = F.add(Info,
First, NewSet);
2644 if (
const RangeSet *SecondConstraint = Constraints.lookup(Second))
2645 if (
const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2647 RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
2648 RF, State,
First.getRepresentativeSymbol());
2650 FirstConstraint = RF.
deletePoint(FirstConstraint, *Point);
2654 if (FirstConstraint.
isEmpty())
2657 Constraints = CRF.add(Constraints,
First, FirstConstraint);
2663inline std::optional<bool> EquivalenceClass::areEqual(
ProgramStateRef State,
2666 return EquivalenceClass::areEqual(State, find(State, FirstSym),
2667 find(State, SecondSym));
2670inline std::optional<bool> EquivalenceClass::areEqual(
ProgramStateRef State,
2671 EquivalenceClass
First,
2672 EquivalenceClass Second) {
2674 if (
First == Second)
2679 ClassSet DisequalToFirst =
First.getDisequalClasses(State);
2680 if (DisequalToFirst.contains(Second))
2684 return std::nullopt;
2690 SymbolSet ClsMembers = getClassMembers(State);
2691 assert(ClsMembers.contains(Old));
2694 SymbolSet::Factory &F = getMembersFactory(State);
2695 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2696 ClsMembers = F.remove(ClsMembers, Old);
2699 assert(!ClsMembers.isEmpty() &&
2700 "Class should have had at least two members before member removal");
2702 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2703 ClassMembersMap = EMFactory.add(ClassMembersMap, *
this, ClsMembers);
2704 State = State->set<ClassMembers>(ClassMembersMap);
2707 ClassMapTy Classes = State->get<ClassMap>();
2708 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2709 Classes = CMF.remove(Classes, Old);
2710 State = State->set<ClassMap>(Classes);
2725 return State->assume(DefinedVal,
false);
2730 State = State->assume(DefinedVal,
true);
2737 return State->assumeInclusiveRange(DefinedVal, Constraint->
getMinValue(),
2750 for (
const SymbolRef &MemberSym : ClassMembers) {
2752 const SVal SimplifiedMemberVal =
simplifyToSVal(State, MemberSym);
2757 if (
const auto CI = SimplifiedMemberVal.
getAs<nonloc::ConcreteInt>()) {
2758 const llvm::APSInt &SV = CI->getValue();
2759 const RangeSet *ClassConstraint = getConstraint(State,
Class);
2761 if (ClassConstraint && !ClassConstraint->
contains(SV))
2765 if (SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
2770 State =
merge(F, State, MemberSym, SimplifiedMemberSym);
2774 if (OldState == State)
2790 State = find(State, MemberSym).removeMember(State, MemberSym);
2794 const RangeSet *ClassConstraint = getConstraint(State,
Class);
2815 State =
reAssume(State, ClassConstraint, SimplifiedMemberVal);
2823inline ClassSet EquivalenceClass::getDisequalClasses(
ProgramStateRef State,
2825 return find(State, Sym).getDisequalClasses(State);
2830 return getDisequalClasses(State->get<DisequalityMap>(),
2831 State->get_context<ClassSet>());
2835EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2836 ClassSet::Factory &
Factory)
const {
2837 if (
const ClassSet *DisequalClasses = Map.lookup(*
this))
2838 return *DisequalClasses;
2844 ClassMembersTy Members = State->get<ClassMembers>();
2846 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2849 if (find(State,
Member) == ClassMembersPair.first) {
2857 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2858 for (std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2859 EquivalenceClass
Class = DisequalityInfo.first;
2860 ClassSet DisequalClasses = DisequalityInfo.second;
2863 if (DisequalClasses.isEmpty())
2868 for (EquivalenceClass DisequalClass : DisequalClasses) {
2869 const ClassSet *DisequalToDisequalClasses =
2870 Disequalities.lookup(DisequalClass);
2873 if (!DisequalToDisequalClasses ||
2874 !DisequalToDisequalClasses->contains(
Class))
2886bool RangeConstraintManager::canReasonAbout(SVal
X)
const {
2887 std::optional<nonloc::SymbolVal> SymVal =
X.getAs<nonloc::SymbolVal>();
2888 if (SymVal && SymVal->isExpression()) {
2889 const SymExpr *SE = SymVal->getSymbol();
2891 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
2892 switch (SIE->getOpcode()) {
2912 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
2932ConditionTruthVal RangeConstraintManager::checkNull(
ProgramStateRef State,
2934 const RangeSet *Ranges = getConstraint(State, Sym);
2938 return ConditionTruthVal();
2944 BasicValueFactory &BV = getBasicVals();
2953 return ConditionTruthVal();
2956const llvm::APSInt *RangeConstraintManager::getSymVal(
ProgramStateRef St,
2958 return getRange(St, Sym).getConcreteValue();
2961const llvm::APSInt *RangeConstraintManager::getSymMinVal(
ProgramStateRef St,
2967const llvm::APSInt *RangeConstraintManager::getSymMaxVal(
ProgramStateRef St,
2981 SymbolReaper &SymReaper) {
2982 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2983 ClassMembersTy NewClassMembersMap = ClassMembersMap;
2984 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2985 SymbolSet::Factory &SetFactory = State->get_context<
SymbolSet>();
2987 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2988 ConstraintRangeTy NewConstraints = Constraints;
2989 ConstraintRangeTy::Factory &ConstraintFactory =
2990 State->get_context<ConstraintRange>();
2992 ClassMapTy Map = State->get<ClassMap>();
2993 ClassMapTy NewMap = Map;
2994 ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2996 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2997 DisequalityMapTy::Factory &DisequalityFactory =
2998 State->get_context<DisequalityMap>();
2999 ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
3001 bool ClassMapChanged =
false;
3002 bool MembersMapChanged =
false;
3003 bool ConstraintMapChanged =
false;
3004 bool DisequalitiesChanged =
false;
3006 auto removeDeadClass = [&](EquivalenceClass
Class) {
3008 Constraints = ConstraintFactory.remove(Constraints,
Class);
3009 ConstraintMapChanged =
true;
3013 ClassSet DisequalClasses =
3014 Class.getDisequalClasses(Disequalities, ClassSetFactory);
3015 if (!DisequalClasses.isEmpty()) {
3016 for (EquivalenceClass DisequalClass : DisequalClasses) {
3017 ClassSet DisequalToDisequalSet =
3018 DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
3021 assert(!DisequalToDisequalSet.isEmpty());
3022 ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet,
Class);
3025 if (NewSet.isEmpty()) {
3027 DisequalityFactory.remove(Disequalities, DisequalClass);
3030 DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
3034 Disequalities = DisequalityFactory.remove(Disequalities,
Class);
3035 DisequalitiesChanged =
true;
3040 for (std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
3042 EquivalenceClass
Class = ClassConstraintPair.first;
3043 if (
Class.isTriviallyDead(State, SymReaper)) {
3045 removeDeadClass(
Class);
3050 for (std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
3053 if (SymReaper.
isDead(Sym)) {
3054 ClassMapChanged =
true;
3055 NewMap = ClassFactory.remove(NewMap, Sym);
3061 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
3063 EquivalenceClass
Class = ClassMembersPair.first;
3064 SymbolSet LiveMembers = ClassMembersPair.second;
3065 bool MembersChanged =
false;
3069 MembersChanged =
true;
3070 LiveMembers = SetFactory.remove(LiveMembers,
Member);
3075 if (!MembersChanged)
3078 MembersMapChanged =
true;
3080 if (LiveMembers.isEmpty()) {
3082 NewClassMembersMap = EMFactory.remove(NewClassMembersMap,
Class);
3085 removeDeadClass(
Class);
3088 NewClassMembersMap =
3089 EMFactory.add(NewClassMembersMap,
Class, LiveMembers);
3096 if (ClassMapChanged)
3097 State = State->set<ClassMap>(NewMap);
3099 if (MembersMapChanged)
3100 State = State->set<ClassMembers>(NewClassMembersMap);
3102 if (ConstraintMapChanged)
3103 State = State->set<ConstraintRange>(Constraints);
3105 if (DisequalitiesChanged)
3106 State = State->set<DisequalityMap>(Disequalities);
3108 assert(EquivalenceClass::isClassDataConsistent(State));
3115 return SymbolicRangeInferrer::inferRange(F, State, Sym);
3121 return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range);
3138 const llvm::APSInt &Int,
3139 const llvm::APSInt &Adjustment) {
3141 APSIntType AdjustmentType(Adjustment);
3145 llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3149 return setRange(St, Sym,
New);
3154 const llvm::APSInt &Int,
3155 const llvm::APSInt &Adjustment) {
3157 APSIntType AdjustmentType(Adjustment);
3162 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3166 return setRange(St, Sym,
New);
3171 const llvm::APSInt &Int,
3172 const llvm::APSInt &Adjustment)
const {
3174 APSIntType AdjustmentType(Adjustment);
3175 switch (AdjustmentType.testInRange(Int,
true)) {
3185 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3186 llvm::APSInt
Min = AdjustmentType.getMinValue();
3187 if (ComparisonVal ==
Min)
3190 llvm::APSInt Lower =
Min - Adjustment;
3191 llvm::APSInt Upper = ComparisonVal - Adjustment;
3200 const llvm::APSInt &Int,
3201 const llvm::APSInt &Adjustment) {
3202 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
3203 return setRange(St, Sym,
New);
3208 const llvm::APSInt &Int,
3209 const llvm::APSInt &Adjustment)
const {
3211 APSIntType AdjustmentType(Adjustment);
3212 switch (AdjustmentType.testInRange(Int,
true)) {
3222 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3223 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3224 if (ComparisonVal ==
Max)
3227 llvm::APSInt Lower = ComparisonVal - Adjustment;
3228 llvm::APSInt Upper =
Max - Adjustment;
3232 return F.
intersect(SymRange, Lower, Upper);
3237 const llvm::APSInt &Int,
3238 const llvm::APSInt &Adjustment) {
3239 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
3240 return setRange(St, Sym,
New);
3245 const llvm::APSInt &Int,
3246 const llvm::APSInt &Adjustment)
const {
3248 APSIntType AdjustmentType(Adjustment);
3249 switch (AdjustmentType.testInRange(Int,
true)) {
3259 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3260 llvm::APSInt
Min = AdjustmentType.getMinValue();
3261 if (ComparisonVal ==
Min)
3264 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3265 llvm::APSInt Lower = ComparisonVal - Adjustment;
3266 llvm::APSInt Upper =
Max - Adjustment;
3269 return F.
intersect(SymRange, Lower, Upper);
3274 const llvm::APSInt &Int,
3275 const llvm::APSInt &Adjustment) {
3276 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
3277 return setRange(St, Sym,
New);
3281RangeConstraintManager::getSymLERange(llvm::function_ref<
RangeSet()> RS,
3282 const llvm::APSInt &Int,
3283 const llvm::APSInt &Adjustment)
const {
3285 APSIntType AdjustmentType(Adjustment);
3286 switch (AdjustmentType.testInRange(Int,
true)) {
3296 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3297 llvm::APSInt
Max = AdjustmentType.getMaxValue();
3298 if (ComparisonVal ==
Max)
3301 llvm::APSInt
Min = AdjustmentType.getMinValue();
3302 llvm::APSInt Lower =
Min - Adjustment;
3303 llvm::APSInt Upper = ComparisonVal - Adjustment;
3311 const llvm::APSInt &Int,
3312 const llvm::APSInt &Adjustment)
const {
3313 return getSymLERange([&] {
return getRange(St, Sym); },
Int, Adjustment);
3318 const llvm::APSInt &Int,
3319 const llvm::APSInt &Adjustment) {
3320 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
3321 return setRange(St, Sym,
New);
3326 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
3327 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
3330 RangeSet Out = getSymLERange([&] {
return New; }, To, Adjustment);
3331 return setRange(State, Sym, Out);
3334ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
3336 const llvm::APSInt &To,
const llvm::APSInt &Adjustment) {
3337 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
3338 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
3340 return setRange(State, Sym,
New);
3347void RangeConstraintManager::printJson(raw_ostream &Out,
ProgramStateRef State,
3348 const char *NL,
unsigned int Space,
3350 printConstraints(Out, State, NL, Space, IsDot);
3351 printEquivalenceClasses(Out, State, NL, Space, IsDot);
3352 printDisequalities(Out, State, NL, Space, IsDot);
3355void RangeConstraintManager::printValue(raw_ostream &Out,
ProgramStateRef State,
3359 Out <<
"<empty rangeset>";
3368 llvm::raw_string_ostream O(S);
3373void RangeConstraintManager::printConstraints(raw_ostream &Out,
3378 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
3380 Indent(Out, Space, IsDot) <<
"\"constraints\": ";
3381 if (Constraints.isEmpty()) {
3382 Out <<
"null," << NL;
3386 std::map<std::string, RangeSet> OrderedConstraints;
3387 for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
3388 SymbolSet ClassMembers = P.first.getClassMembers(State);
3389 for (
const SymbolRef &ClassMember : ClassMembers) {
3390 bool insertion_took_place;
3391 std::tie(std::ignore, insertion_took_place) =
3392 OrderedConstraints.insert({
toString(ClassMember), P.second});
3393 assert(insertion_took_place &&
3394 "two symbols should not have the same dump");
3401 for (std::pair<std::string, RangeSet> P : OrderedConstraints) {
3408 Indent(Out, Space, IsDot)
3409 <<
"{ \"symbol\": \"" << P.first <<
"\", \"range\": \"";
3416 Indent(Out, Space, IsDot) <<
"]," << NL;
3420 SymbolSet ClassMembers = Class.getClassMembers(State);
3422 ClassMembers.end());
3423 llvm::sort(ClassMembersSorted,
3428 bool FirstMember =
true;
3431 llvm::raw_string_ostream Out(Str);
3433 for (
SymbolRef ClassMember : ClassMembersSorted) {
3435 FirstMember =
false;
3438 Out <<
"\"" << ClassMember <<
"\"";
3444void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3449 ClassMembersTy Members = State->get<ClassMembers>();
3451 Indent(Out, Space, IsDot) <<
"\"equivalence_classes\": ";
3452 if (Members.isEmpty()) {
3453 Out <<
"null," << NL;
3457 std::set<std::string> MembersStr;
3458 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3459 MembersStr.insert(
toString(State, ClassToSymbolSet.first));
3463 bool FirstClass =
true;
3464 for (
const std::string &Str : MembersStr) {
3471 Indent(Out, Space, IsDot);
3477 Indent(Out, Space, IsDot) <<
"]," << NL;
3480void RangeConstraintManager::printDisequalities(raw_ostream &Out,
3485 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3487 Indent(Out, Space, IsDot) <<
"\"disequality_info\": ";
3488 if (Disequalities.isEmpty()) {
3489 Out <<
"null," << NL;
3495 using EqClassesStrTy = std::set<std::string>;
3496 using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3497 DisequalityInfoStrTy DisequalityInfoStr;
3498 for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3499 EquivalenceClass
Class = ClassToDisEqSet.first;
3500 ClassSet DisequalClasses = ClassToDisEqSet.second;
3501 EqClassesStrTy MembersStr;
3502 for (EquivalenceClass DisEqClass : DisequalClasses)
3503 MembersStr.insert(
toString(State, DisEqClass));
3504 DisequalityInfoStr.insert({
toString(State,
Class), MembersStr});
3509 bool FirstClass =
true;
3510 for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3511 DisequalityInfoStr) {
3512 const std::string &
Class = ClassToDisEqSet.first;
3519 Indent(Out, Space, IsDot) <<
"{" << NL;
3520 unsigned int DisEqSpace = Space + 1;
3521 Indent(Out, DisEqSpace, IsDot) <<
"\"class\": ";
3523 const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3524 if (!DisequalClasses.empty()) {
3526 Indent(Out, DisEqSpace, IsDot) <<
"\"disequal_to\": [" << NL;
3527 unsigned int DisEqClassSpace = DisEqSpace + 1;
3528 Indent(Out, DisEqClassSpace, IsDot);
3529 bool FirstDisEqClass =
true;
3530 for (
const std::string &DisEqClass : DisequalClasses) {
3531 if (FirstDisEqClass) {
3532 FirstDisEqClass =
false;
3535 Indent(Out, DisEqClassSpace, IsDot);
3541 Indent(Out, Space, IsDot) <<
"}";
3546 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)
Result
Implement __builtin_bit_cast and related operations.
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
BinaryOperatorKind Opcode
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.
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.
RangeSet(const RangeSet &)=default
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
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.
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.
QualType getType() const override
UnaryOperator::Opcode getOpcode() const
const SymExpr * getOperand() const
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
BinarySymExprImpl< APSIntPtr, const SymExpr *, SymExpr::Kind::IntSymExprKind > IntSymExpr
Represents a symbolic expression like 3 - 'x'.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
BinarySymExprImpl< const SymExpr *, const SymExpr *, SymExpr::Kind::SymSymExprKind > SymSymExpr
Represents a symbolic expression like 'x' + 'y'.
BinarySymExprImpl< const SymExpr *, APSIntPtr, SymExpr::Kind::SymIntExprKind > SymIntExpr
Represents a symbolic expression like 'x' + 3.
@ 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 Const(InterpState &S, 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)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
@ Default
Set to the current date and time.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Type
The name was classified as a type.
bool operator!=(CanQual< T > x, CanQual< U > y)
@ 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...