xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines RangeConstraintManager, a class that tracks simple
100b57cec5SDimitry Andric //  equality and inequality constraints on symbolic values of ProgramState.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h"
150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
170b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
180b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
195ffd83dbSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
200b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
210b57cec5SDimitry Andric #include "llvm/ADT/ImmutableSet.h"
22fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
23fe6060f1SDimitry Andric #include "llvm/ADT/SmallSet.h"
2481ad6265SDimitry Andric #include "llvm/ADT/StringExtras.h"
25fe6060f1SDimitry Andric #include "llvm/Support/Compiler.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
27fe6060f1SDimitry Andric #include <algorithm>
28fe6060f1SDimitry Andric #include <iterator>
29bdd1243dSDimitry Andric #include <optional>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace clang;
320b57cec5SDimitry Andric using namespace ento;
330b57cec5SDimitry Andric 
345ffd83dbSDimitry Andric // This class can be extended with other tables which will help to reason
355ffd83dbSDimitry Andric // about ranges more precisely.
365ffd83dbSDimitry Andric class OperatorRelationsTable {
375ffd83dbSDimitry Andric   static_assert(BO_LT < BO_GT && BO_GT < BO_LE && BO_LE < BO_GE &&
385ffd83dbSDimitry Andric                     BO_GE < BO_EQ && BO_EQ < BO_NE,
395ffd83dbSDimitry Andric                 "This class relies on operators order. Rework it otherwise.");
405ffd83dbSDimitry Andric 
415ffd83dbSDimitry Andric public:
425ffd83dbSDimitry Andric   enum TriStateKind {
435ffd83dbSDimitry Andric     False = 0,
445ffd83dbSDimitry Andric     True,
455ffd83dbSDimitry Andric     Unknown,
465ffd83dbSDimitry Andric   };
475ffd83dbSDimitry Andric 
485ffd83dbSDimitry Andric private:
495ffd83dbSDimitry Andric   // CmpOpTable holds states which represent the corresponding range for
505ffd83dbSDimitry Andric   // branching an exploded graph. We can reason about the branch if there is
515ffd83dbSDimitry Andric   // a previously known fact of the existence of a comparison expression with
525ffd83dbSDimitry Andric   // operands used in the current expression.
535ffd83dbSDimitry Andric   // E.g. assuming (x < y) is true that means (x != y) is surely true.
545ffd83dbSDimitry Andric   // if (x previous_operation y)  // <    | !=      | >
555ffd83dbSDimitry Andric   //   if (x operation y)         // !=   | >       | <
565ffd83dbSDimitry Andric   //     tristate                 // True | Unknown | False
575ffd83dbSDimitry Andric   //
585ffd83dbSDimitry Andric   // CmpOpTable represents next:
595ffd83dbSDimitry Andric   // __|< |> |<=|>=|==|!=|UnknownX2|
605ffd83dbSDimitry Andric   // < |1 |0 |* |0 |0 |* |1        |
615ffd83dbSDimitry Andric   // > |0 |1 |0 |* |0 |* |1        |
625ffd83dbSDimitry Andric   // <=|1 |0 |1 |* |1 |* |0        |
635ffd83dbSDimitry Andric   // >=|0 |1 |* |1 |1 |* |0        |
645ffd83dbSDimitry Andric   // ==|0 |0 |* |* |1 |0 |1        |
655ffd83dbSDimitry Andric   // !=|1 |1 |* |* |0 |1 |0        |
665ffd83dbSDimitry Andric   //
675ffd83dbSDimitry Andric   // Columns stands for a previous operator.
685ffd83dbSDimitry Andric   // Rows stands for a current operator.
695ffd83dbSDimitry Andric   // Each row has exactly two `Unknown` cases.
705ffd83dbSDimitry Andric   // UnknownX2 means that both `Unknown` previous operators are met in code,
715ffd83dbSDimitry Andric   // and there is a special column for that, for example:
725ffd83dbSDimitry Andric   // if (x >= y)
735ffd83dbSDimitry Andric   //   if (x != y)
745ffd83dbSDimitry Andric   //     if (x <= y)
755ffd83dbSDimitry Andric   //       False only
765ffd83dbSDimitry Andric   static constexpr size_t CmpOpCount = BO_NE - BO_LT + 1;
775ffd83dbSDimitry Andric   const TriStateKind CmpOpTable[CmpOpCount][CmpOpCount + 1] = {
785ffd83dbSDimitry Andric       // <      >      <=     >=     ==     !=    UnknownX2
795ffd83dbSDimitry Andric       {True, False, Unknown, False, False, Unknown, True}, // <
805ffd83dbSDimitry Andric       {False, True, False, Unknown, False, Unknown, True}, // >
815ffd83dbSDimitry Andric       {True, False, True, Unknown, True, Unknown, False},  // <=
825ffd83dbSDimitry Andric       {False, True, Unknown, True, True, Unknown, False},  // >=
835ffd83dbSDimitry Andric       {False, False, Unknown, Unknown, True, False, True}, // ==
845ffd83dbSDimitry Andric       {True, True, Unknown, Unknown, False, True, False},  // !=
855ffd83dbSDimitry Andric   };
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric   static size_t getIndexFromOp(BinaryOperatorKind OP) {
885ffd83dbSDimitry Andric     return static_cast<size_t>(OP - BO_LT);
895ffd83dbSDimitry Andric   }
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric public:
925ffd83dbSDimitry Andric   constexpr size_t getCmpOpCount() const { return CmpOpCount; }
935ffd83dbSDimitry Andric 
945ffd83dbSDimitry Andric   static BinaryOperatorKind getOpFromIndex(size_t Index) {
955ffd83dbSDimitry Andric     return static_cast<BinaryOperatorKind>(Index + BO_LT);
965ffd83dbSDimitry Andric   }
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric   TriStateKind getCmpOpState(BinaryOperatorKind CurrentOP,
995ffd83dbSDimitry Andric                              BinaryOperatorKind QueriedOP) const {
1005ffd83dbSDimitry Andric     return CmpOpTable[getIndexFromOp(CurrentOP)][getIndexFromOp(QueriedOP)];
1015ffd83dbSDimitry Andric   }
1025ffd83dbSDimitry Andric 
1035ffd83dbSDimitry Andric   TriStateKind getCmpOpStateForUnknownX2(BinaryOperatorKind CurrentOP) const {
1045ffd83dbSDimitry Andric     return CmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
1055ffd83dbSDimitry Andric   }
1065ffd83dbSDimitry Andric };
107fe6060f1SDimitry Andric 
1085ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
1095ffd83dbSDimitry Andric //                           RangeSet implementation
1105ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
1115ffd83dbSDimitry Andric 
112fe6060f1SDimitry Andric RangeSet::ContainerType RangeSet::Factory::EmptySet{};
113fe6060f1SDimitry Andric 
1140eae32dcSDimitry Andric RangeSet RangeSet::Factory::add(RangeSet LHS, RangeSet RHS) {
1150eae32dcSDimitry Andric   ContainerType Result;
1160eae32dcSDimitry Andric   Result.reserve(LHS.size() + RHS.size());
1170eae32dcSDimitry Andric   std::merge(LHS.begin(), LHS.end(), RHS.begin(), RHS.end(),
1180eae32dcSDimitry Andric              std::back_inserter(Result));
1190eae32dcSDimitry Andric   return makePersistent(std::move(Result));
1200eae32dcSDimitry Andric }
1210eae32dcSDimitry Andric 
122fe6060f1SDimitry Andric RangeSet RangeSet::Factory::add(RangeSet Original, Range Element) {
123fe6060f1SDimitry Andric   ContainerType Result;
124fe6060f1SDimitry Andric   Result.reserve(Original.size() + 1);
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric   const_iterator Lower = llvm::lower_bound(Original, Element);
127fe6060f1SDimitry Andric   Result.insert(Result.end(), Original.begin(), Lower);
128fe6060f1SDimitry Andric   Result.push_back(Element);
129fe6060f1SDimitry Andric   Result.insert(Result.end(), Lower, Original.end());
130fe6060f1SDimitry Andric 
131fe6060f1SDimitry Andric   return makePersistent(std::move(Result));
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
134fe6060f1SDimitry Andric RangeSet RangeSet::Factory::add(RangeSet Original, const llvm::APSInt &Point) {
135fe6060f1SDimitry Andric   return add(Original, Range(Point));
1360b57cec5SDimitry Andric }
137fe6060f1SDimitry Andric 
1380eae32dcSDimitry Andric RangeSet RangeSet::Factory::unite(RangeSet LHS, RangeSet RHS) {
1390eae32dcSDimitry Andric   ContainerType Result = unite(*LHS.Impl, *RHS.Impl);
1400eae32dcSDimitry Andric   return makePersistent(std::move(Result));
1410eae32dcSDimitry Andric }
1420eae32dcSDimitry Andric 
1430eae32dcSDimitry Andric RangeSet RangeSet::Factory::unite(RangeSet Original, Range R) {
1440eae32dcSDimitry Andric   ContainerType Result;
1450eae32dcSDimitry Andric   Result.push_back(R);
1460eae32dcSDimitry Andric   Result = unite(*Original.Impl, Result);
1470eae32dcSDimitry Andric   return makePersistent(std::move(Result));
1480eae32dcSDimitry Andric }
1490eae32dcSDimitry Andric 
1500eae32dcSDimitry Andric RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt Point) {
1510eae32dcSDimitry Andric   return unite(Original, Range(ValueFactory.getValue(Point)));
1520eae32dcSDimitry Andric }
1530eae32dcSDimitry Andric 
1540eae32dcSDimitry Andric RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt From,
1550eae32dcSDimitry Andric                                   llvm::APSInt To) {
1560eae32dcSDimitry Andric   return unite(Original,
1570eae32dcSDimitry Andric                Range(ValueFactory.getValue(From), ValueFactory.getValue(To)));
1580eae32dcSDimitry Andric }
1590eae32dcSDimitry Andric 
1600eae32dcSDimitry Andric template <typename T>
1610eae32dcSDimitry Andric void swapIterators(T &First, T &FirstEnd, T &Second, T &SecondEnd) {
1620eae32dcSDimitry Andric   std::swap(First, Second);
1630eae32dcSDimitry Andric   std::swap(FirstEnd, SecondEnd);
1640eae32dcSDimitry Andric }
1650eae32dcSDimitry Andric 
1660eae32dcSDimitry Andric RangeSet::ContainerType RangeSet::Factory::unite(const ContainerType &LHS,
1670eae32dcSDimitry Andric                                                  const ContainerType &RHS) {
1680eae32dcSDimitry Andric   if (LHS.empty())
1690eae32dcSDimitry Andric     return RHS;
1700eae32dcSDimitry Andric   if (RHS.empty())
1710eae32dcSDimitry Andric     return LHS;
1720eae32dcSDimitry Andric 
1730eae32dcSDimitry Andric   using llvm::APSInt;
1740eae32dcSDimitry Andric   using iterator = ContainerType::const_iterator;
1750eae32dcSDimitry Andric 
1760eae32dcSDimitry Andric   iterator First = LHS.begin();
1770eae32dcSDimitry Andric   iterator FirstEnd = LHS.end();
1780eae32dcSDimitry Andric   iterator Second = RHS.begin();
1790eae32dcSDimitry Andric   iterator SecondEnd = RHS.end();
1800eae32dcSDimitry Andric   APSIntType Ty = APSIntType(First->From());
1810eae32dcSDimitry Andric   const APSInt Min = Ty.getMinValue();
1820eae32dcSDimitry Andric 
1830eae32dcSDimitry Andric   // Handle a corner case first when both range sets start from MIN.
1840eae32dcSDimitry Andric   // This helps to avoid complicated conditions below. Specifically, this
1850eae32dcSDimitry Andric   // particular check for `MIN` is not needed in the loop below every time
1860eae32dcSDimitry Andric   // when we do `Second->From() - One` operation.
1870eae32dcSDimitry Andric   if (Min == First->From() && Min == Second->From()) {
1880eae32dcSDimitry Andric     if (First->To() > Second->To()) {
1890eae32dcSDimitry Andric       //    [ First    ]--->
1900eae32dcSDimitry Andric       //    [ Second ]----->
1910eae32dcSDimitry Andric       // MIN^
1920eae32dcSDimitry Andric       // The Second range is entirely inside the First one.
1930eae32dcSDimitry Andric 
1940eae32dcSDimitry Andric       // Check if Second is the last in its RangeSet.
1950eae32dcSDimitry Andric       if (++Second == SecondEnd)
1960eae32dcSDimitry Andric         //    [ First     ]--[ First + 1 ]--->
1970eae32dcSDimitry Andric         //    [ Second ]--------------------->
1980eae32dcSDimitry Andric         // MIN^
1990eae32dcSDimitry Andric         // The Union is equal to First's RangeSet.
2000eae32dcSDimitry Andric         return LHS;
2010eae32dcSDimitry Andric     } else {
2020eae32dcSDimitry Andric       // case 1: [ First ]----->
2030eae32dcSDimitry Andric       // case 2: [ First   ]--->
2040eae32dcSDimitry Andric       //         [ Second  ]--->
2050eae32dcSDimitry Andric       //      MIN^
2060eae32dcSDimitry Andric       // The First range is entirely inside or equal to the Second one.
2070eae32dcSDimitry Andric 
2080eae32dcSDimitry Andric       // Check if First is the last in its RangeSet.
2090eae32dcSDimitry Andric       if (++First == FirstEnd)
2100eae32dcSDimitry Andric         //    [ First ]----------------------->
2110eae32dcSDimitry Andric         //    [ Second  ]--[ Second + 1 ]---->
2120eae32dcSDimitry Andric         // MIN^
2130eae32dcSDimitry Andric         // The Union is equal to Second's RangeSet.
2140eae32dcSDimitry Andric         return RHS;
2150eae32dcSDimitry Andric     }
2160eae32dcSDimitry Andric   }
2170eae32dcSDimitry Andric 
2180eae32dcSDimitry Andric   const APSInt One = Ty.getValue(1);
2190eae32dcSDimitry Andric   ContainerType Result;
2200eae32dcSDimitry Andric 
2210eae32dcSDimitry Andric   // This is called when there are no ranges left in one of the ranges.
2220eae32dcSDimitry Andric   // Append the rest of the ranges from another range set to the Result
2230eae32dcSDimitry Andric   // and return with that.
2240eae32dcSDimitry Andric   const auto AppendTheRest = [&Result](iterator I, iterator E) {
2250eae32dcSDimitry Andric     Result.append(I, E);
2260eae32dcSDimitry Andric     return Result;
2270eae32dcSDimitry Andric   };
2280eae32dcSDimitry Andric 
2290eae32dcSDimitry Andric   while (true) {
2300eae32dcSDimitry Andric     // We want to keep the following invariant at all times:
2310eae32dcSDimitry Andric     // ---[ First ------>
2320eae32dcSDimitry Andric     // -----[ Second --->
2330eae32dcSDimitry Andric     if (First->From() > Second->From())
2340eae32dcSDimitry Andric       swapIterators(First, FirstEnd, Second, SecondEnd);
2350eae32dcSDimitry Andric 
2360eae32dcSDimitry Andric     // The Union definitely starts with First->From().
2370eae32dcSDimitry Andric     // ----------[ First ------>
2380eae32dcSDimitry Andric     // ------------[ Second --->
2390eae32dcSDimitry Andric     // ----------[ Union ------>
2400eae32dcSDimitry Andric     // UnionStart^
2410eae32dcSDimitry Andric     const llvm::APSInt &UnionStart = First->From();
2420eae32dcSDimitry Andric 
2430eae32dcSDimitry Andric     // Loop where the invariant holds.
2440eae32dcSDimitry Andric     while (true) {
2450eae32dcSDimitry Andric       // Skip all enclosed ranges.
2460eae32dcSDimitry Andric       // ---[                  First                     ]--->
2470eae32dcSDimitry Andric       // -----[ Second ]--[ Second + 1 ]--[ Second + N ]----->
2480eae32dcSDimitry Andric       while (First->To() >= Second->To()) {
2490eae32dcSDimitry Andric         // Check if Second is the last in its RangeSet.
2500eae32dcSDimitry Andric         if (++Second == SecondEnd) {
2510eae32dcSDimitry Andric           // Append the Union.
2520eae32dcSDimitry Andric           // ---[ Union      ]--->
2530eae32dcSDimitry Andric           // -----[ Second ]----->
2540eae32dcSDimitry Andric           // --------[ First ]--->
2550eae32dcSDimitry Andric           //         UnionEnd^
2560eae32dcSDimitry Andric           Result.emplace_back(UnionStart, First->To());
2570eae32dcSDimitry Andric           // ---[ Union ]----------------->
2580eae32dcSDimitry Andric           // --------------[ First + 1]--->
2590eae32dcSDimitry Andric           // Append all remaining ranges from the First's RangeSet.
2600eae32dcSDimitry Andric           return AppendTheRest(++First, FirstEnd);
2610eae32dcSDimitry Andric         }
2620eae32dcSDimitry Andric       }
2630eae32dcSDimitry Andric 
2640eae32dcSDimitry Andric       // Check if First and Second are disjoint. It means that we find
2650eae32dcSDimitry Andric       // the end of the Union. Exit the loop and append the Union.
2660eae32dcSDimitry Andric       // ---[ First ]=------------->
2670eae32dcSDimitry Andric       // ------------=[ Second ]--->
2680eae32dcSDimitry Andric       // ----MinusOne^
2690eae32dcSDimitry Andric       if (First->To() < Second->From() - One)
2700eae32dcSDimitry Andric         break;
2710eae32dcSDimitry Andric 
2720eae32dcSDimitry Andric       // First is entirely inside the Union. Go next.
2730eae32dcSDimitry Andric       // ---[ Union ----------->
2740eae32dcSDimitry Andric       // ---- [ First ]-------->
2750eae32dcSDimitry Andric       // -------[ Second ]----->
2760eae32dcSDimitry Andric       // Check if First is the last in its RangeSet.
2770eae32dcSDimitry Andric       if (++First == FirstEnd) {
2780eae32dcSDimitry Andric         // Append the Union.
2790eae32dcSDimitry Andric         // ---[ Union       ]--->
2800eae32dcSDimitry Andric         // -----[ First ]------->
2810eae32dcSDimitry Andric         // --------[ Second ]--->
2820eae32dcSDimitry Andric         //          UnionEnd^
2830eae32dcSDimitry Andric         Result.emplace_back(UnionStart, Second->To());
2840eae32dcSDimitry Andric         // ---[ Union ]------------------>
2850eae32dcSDimitry Andric         // --------------[ Second + 1]--->
2860eae32dcSDimitry Andric         // Append all remaining ranges from the Second's RangeSet.
2870eae32dcSDimitry Andric         return AppendTheRest(++Second, SecondEnd);
2880eae32dcSDimitry Andric       }
2890eae32dcSDimitry Andric 
2900eae32dcSDimitry Andric       // We know that we are at one of the two cases:
2910eae32dcSDimitry Andric       // case 1: --[ First ]--------->
2920eae32dcSDimitry Andric       // case 2: ----[ First ]------->
2930eae32dcSDimitry Andric       // --------[ Second ]---------->
2940eae32dcSDimitry Andric       // In both cases First starts after Second->From().
2950eae32dcSDimitry Andric       // Make sure that the loop invariant holds.
2960eae32dcSDimitry Andric       swapIterators(First, FirstEnd, Second, SecondEnd);
2970eae32dcSDimitry Andric     }
2980eae32dcSDimitry Andric 
2990eae32dcSDimitry Andric     // Here First and Second are disjoint.
3000eae32dcSDimitry Andric     // Append the Union.
3010eae32dcSDimitry Andric     // ---[ Union    ]--------------->
3020eae32dcSDimitry Andric     // -----------------[ Second ]--->
3030eae32dcSDimitry Andric     // ------[ First ]--------------->
3040eae32dcSDimitry Andric     //       UnionEnd^
3050eae32dcSDimitry Andric     Result.emplace_back(UnionStart, First->To());
3060eae32dcSDimitry Andric 
3070eae32dcSDimitry Andric     // Check if First is the last in its RangeSet.
3080eae32dcSDimitry Andric     if (++First == FirstEnd)
3090eae32dcSDimitry Andric       // ---[ Union ]--------------->
3100eae32dcSDimitry Andric       // --------------[ Second ]--->
3110eae32dcSDimitry Andric       // Append all remaining ranges from the Second's RangeSet.
3120eae32dcSDimitry Andric       return AppendTheRest(Second, SecondEnd);
3130eae32dcSDimitry Andric   }
3140eae32dcSDimitry Andric 
3150eae32dcSDimitry Andric   llvm_unreachable("Normally, we should not reach here");
3160eae32dcSDimitry Andric }
3170eae32dcSDimitry Andric 
318fe6060f1SDimitry Andric RangeSet RangeSet::Factory::getRangeSet(Range From) {
319fe6060f1SDimitry Andric   ContainerType Result;
320fe6060f1SDimitry Andric   Result.push_back(From);
321fe6060f1SDimitry Andric   return makePersistent(std::move(Result));
3220b57cec5SDimitry Andric }
323fe6060f1SDimitry Andric 
324fe6060f1SDimitry Andric RangeSet RangeSet::Factory::makePersistent(ContainerType &&From) {
325fe6060f1SDimitry Andric   llvm::FoldingSetNodeID ID;
326fe6060f1SDimitry Andric   void *InsertPos;
327fe6060f1SDimitry Andric 
328fe6060f1SDimitry Andric   From.Profile(ID);
329fe6060f1SDimitry Andric   ContainerType *Result = Cache.FindNodeOrInsertPos(ID, InsertPos);
330fe6060f1SDimitry Andric 
331fe6060f1SDimitry Andric   if (!Result) {
332fe6060f1SDimitry Andric     // It is cheaper to fully construct the resulting range on stack
333fe6060f1SDimitry Andric     // and move it to the freshly allocated buffer if we don't have
334fe6060f1SDimitry Andric     // a set like this already.
335fe6060f1SDimitry Andric     Result = construct(std::move(From));
336fe6060f1SDimitry Andric     Cache.InsertNode(Result, InsertPos);
337fe6060f1SDimitry Andric   }
338fe6060f1SDimitry Andric 
339fe6060f1SDimitry Andric   return Result;
340fe6060f1SDimitry Andric }
341fe6060f1SDimitry Andric 
342fe6060f1SDimitry Andric RangeSet::ContainerType *RangeSet::Factory::construct(ContainerType &&From) {
343fe6060f1SDimitry Andric   void *Buffer = Arena.Allocate();
344fe6060f1SDimitry Andric   return new (Buffer) ContainerType(std::move(From));
345fe6060f1SDimitry Andric }
346fe6060f1SDimitry Andric 
3470b57cec5SDimitry Andric const llvm::APSInt &RangeSet::getMinValue() const {
3480b57cec5SDimitry Andric   assert(!isEmpty());
3495ffd83dbSDimitry Andric   return begin()->From();
3505ffd83dbSDimitry Andric }
3515ffd83dbSDimitry Andric 
3525ffd83dbSDimitry Andric const llvm::APSInt &RangeSet::getMaxValue() const {
3535ffd83dbSDimitry Andric   assert(!isEmpty());
354fe6060f1SDimitry Andric   return std::prev(end())->To();
3555ffd83dbSDimitry Andric }
356fe6060f1SDimitry Andric 
35781ad6265SDimitry Andric bool clang::ento::RangeSet::isUnsigned() const {
35881ad6265SDimitry Andric   assert(!isEmpty());
35981ad6265SDimitry Andric   return begin()->From().isUnsigned();
36081ad6265SDimitry Andric }
36181ad6265SDimitry Andric 
36281ad6265SDimitry Andric uint32_t clang::ento::RangeSet::getBitWidth() const {
36381ad6265SDimitry Andric   assert(!isEmpty());
36481ad6265SDimitry Andric   return begin()->From().getBitWidth();
36581ad6265SDimitry Andric }
36681ad6265SDimitry Andric 
36781ad6265SDimitry Andric APSIntType clang::ento::RangeSet::getAPSIntType() const {
36881ad6265SDimitry Andric   assert(!isEmpty());
36981ad6265SDimitry Andric   return APSIntType(begin()->From());
37081ad6265SDimitry Andric }
37181ad6265SDimitry Andric 
372fe6060f1SDimitry Andric bool RangeSet::containsImpl(llvm::APSInt &Point) const {
373fe6060f1SDimitry Andric   if (isEmpty() || !pin(Point))
374fe6060f1SDimitry Andric     return false;
375fe6060f1SDimitry Andric 
376fe6060f1SDimitry Andric   Range Dummy(Point);
377fe6060f1SDimitry Andric   const_iterator It = llvm::upper_bound(*this, Dummy);
378fe6060f1SDimitry Andric   if (It == begin())
379fe6060f1SDimitry Andric     return false;
380fe6060f1SDimitry Andric 
381fe6060f1SDimitry Andric   return std::prev(It)->Includes(Point);
382fe6060f1SDimitry Andric }
383fe6060f1SDimitry Andric 
384fe6060f1SDimitry Andric bool RangeSet::pin(llvm::APSInt &Point) const {
385fe6060f1SDimitry Andric   APSIntType Type(getMinValue());
386fe6060f1SDimitry Andric   if (Type.testInRange(Point, true) != APSIntType::RTR_Within)
387fe6060f1SDimitry Andric     return false;
388fe6060f1SDimitry Andric 
389fe6060f1SDimitry Andric   Type.apply(Point);
390fe6060f1SDimitry Andric   return true;
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
3940b57cec5SDimitry Andric   // This function has nine cases, the cartesian product of range-testing
3950b57cec5SDimitry Andric   // both the upper and lower bounds against the symbol's type.
3960b57cec5SDimitry Andric   // Each case requires a different pinning operation.
3970b57cec5SDimitry Andric   // The function returns false if the described range is entirely outside
3980b57cec5SDimitry Andric   // the range of values for the associated symbol.
3990b57cec5SDimitry Andric   APSIntType Type(getMinValue());
4000b57cec5SDimitry Andric   APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
4010b57cec5SDimitry Andric   APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   switch (LowerTest) {
4040b57cec5SDimitry Andric   case APSIntType::RTR_Below:
4050b57cec5SDimitry Andric     switch (UpperTest) {
4060b57cec5SDimitry Andric     case APSIntType::RTR_Below:
4070b57cec5SDimitry Andric       // The entire range is outside the symbol's set of possible values.
4080b57cec5SDimitry Andric       // If this is a conventionally-ordered range, the state is infeasible.
4090b57cec5SDimitry Andric       if (Lower <= Upper)
4100b57cec5SDimitry Andric         return false;
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric       // However, if the range wraps around, it spans all possible values.
4130b57cec5SDimitry Andric       Lower = Type.getMinValue();
4140b57cec5SDimitry Andric       Upper = Type.getMaxValue();
4150b57cec5SDimitry Andric       break;
4160b57cec5SDimitry Andric     case APSIntType::RTR_Within:
4170b57cec5SDimitry Andric       // The range starts below what's possible but ends within it. Pin.
4180b57cec5SDimitry Andric       Lower = Type.getMinValue();
4190b57cec5SDimitry Andric       Type.apply(Upper);
4200b57cec5SDimitry Andric       break;
4210b57cec5SDimitry Andric     case APSIntType::RTR_Above:
4220b57cec5SDimitry Andric       // The range spans all possible values for the symbol. Pin.
4230b57cec5SDimitry Andric       Lower = Type.getMinValue();
4240b57cec5SDimitry Andric       Upper = Type.getMaxValue();
4250b57cec5SDimitry Andric       break;
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric     break;
4280b57cec5SDimitry Andric   case APSIntType::RTR_Within:
4290b57cec5SDimitry Andric     switch (UpperTest) {
4300b57cec5SDimitry Andric     case APSIntType::RTR_Below:
4310b57cec5SDimitry Andric       // The range wraps around, but all lower values are not possible.
4320b57cec5SDimitry Andric       Type.apply(Lower);
4330b57cec5SDimitry Andric       Upper = Type.getMaxValue();
4340b57cec5SDimitry Andric       break;
4350b57cec5SDimitry Andric     case APSIntType::RTR_Within:
4360b57cec5SDimitry Andric       // The range may or may not wrap around, but both limits are valid.
4370b57cec5SDimitry Andric       Type.apply(Lower);
4380b57cec5SDimitry Andric       Type.apply(Upper);
4390b57cec5SDimitry Andric       break;
4400b57cec5SDimitry Andric     case APSIntType::RTR_Above:
4410b57cec5SDimitry Andric       // The range starts within what's possible but ends above it. Pin.
4420b57cec5SDimitry Andric       Type.apply(Lower);
4430b57cec5SDimitry Andric       Upper = Type.getMaxValue();
4440b57cec5SDimitry Andric       break;
4450b57cec5SDimitry Andric     }
4460b57cec5SDimitry Andric     break;
4470b57cec5SDimitry Andric   case APSIntType::RTR_Above:
4480b57cec5SDimitry Andric     switch (UpperTest) {
4490b57cec5SDimitry Andric     case APSIntType::RTR_Below:
4500b57cec5SDimitry Andric       // The range wraps but is outside the symbol's set of possible values.
4510b57cec5SDimitry Andric       return false;
4520b57cec5SDimitry Andric     case APSIntType::RTR_Within:
4530b57cec5SDimitry Andric       // The range starts above what's possible but ends within it (wrap).
4540b57cec5SDimitry Andric       Lower = Type.getMinValue();
4550b57cec5SDimitry Andric       Type.apply(Upper);
4560b57cec5SDimitry Andric       break;
4570b57cec5SDimitry Andric     case APSIntType::RTR_Above:
4580b57cec5SDimitry Andric       // The entire range is outside the symbol's set of possible values.
4590b57cec5SDimitry Andric       // If this is a conventionally-ordered range, the state is infeasible.
4600b57cec5SDimitry Andric       if (Lower <= Upper)
4610b57cec5SDimitry Andric         return false;
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric       // However, if the range wraps around, it spans all possible values.
4640b57cec5SDimitry Andric       Lower = Type.getMinValue();
4650b57cec5SDimitry Andric       Upper = Type.getMaxValue();
4660b57cec5SDimitry Andric       break;
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric     break;
4690b57cec5SDimitry Andric   }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   return true;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
474fe6060f1SDimitry Andric RangeSet RangeSet::Factory::intersect(RangeSet What, llvm::APSInt Lower,
475fe6060f1SDimitry Andric                                       llvm::APSInt Upper) {
476fe6060f1SDimitry Andric   if (What.isEmpty() || !What.pin(Lower, Upper))
477fe6060f1SDimitry Andric     return getEmptySet();
4780b57cec5SDimitry Andric 
479fe6060f1SDimitry Andric   ContainerType DummyContainer;
4805ffd83dbSDimitry Andric 
481fe6060f1SDimitry Andric   if (Lower <= Upper) {
482fe6060f1SDimitry Andric     // [Lower, Upper] is a regular range.
4835ffd83dbSDimitry Andric     //
484fe6060f1SDimitry Andric     // Shortcut: check that there is even a possibility of the intersection
485fe6060f1SDimitry Andric     //           by checking the two following situations:
4865ffd83dbSDimitry Andric     //
487fe6060f1SDimitry Andric     //               <---[  What  ]---[------]------>
488fe6060f1SDimitry Andric     //                              Lower  Upper
489fe6060f1SDimitry Andric     //                            -or-
490fe6060f1SDimitry Andric     //               <----[------]----[  What  ]---->
491fe6060f1SDimitry Andric     //                  Lower  Upper
492fe6060f1SDimitry Andric     if (What.getMaxValue() < Lower || Upper < What.getMinValue())
493fe6060f1SDimitry Andric       return getEmptySet();
494fe6060f1SDimitry Andric 
495fe6060f1SDimitry Andric     DummyContainer.push_back(
496fe6060f1SDimitry Andric         Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
497fe6060f1SDimitry Andric   } else {
498fe6060f1SDimitry Andric     // [Lower, Upper] is an inverted range, i.e. [MIN, Upper] U [Lower, MAX]
4995ffd83dbSDimitry Andric     //
500fe6060f1SDimitry Andric     // Shortcut: check that there is even a possibility of the intersection
501fe6060f1SDimitry Andric     //           by checking the following situation:
502fe6060f1SDimitry Andric     //
503fe6060f1SDimitry Andric     //               <------]---[  What  ]---[------>
504fe6060f1SDimitry Andric     //                    Upper             Lower
505fe6060f1SDimitry Andric     if (What.getMaxValue() < Lower && Upper < What.getMinValue())
506fe6060f1SDimitry Andric       return getEmptySet();
5070b57cec5SDimitry Andric 
508fe6060f1SDimitry Andric     DummyContainer.push_back(
509fe6060f1SDimitry Andric         Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
510fe6060f1SDimitry Andric     DummyContainer.push_back(
511fe6060f1SDimitry Andric         Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
512fe6060f1SDimitry Andric   }
5135ffd83dbSDimitry Andric 
514fe6060f1SDimitry Andric   return intersect(*What.Impl, DummyContainer);
515fe6060f1SDimitry Andric }
516fe6060f1SDimitry Andric 
517fe6060f1SDimitry Andric RangeSet RangeSet::Factory::intersect(const RangeSet::ContainerType &LHS,
518fe6060f1SDimitry Andric                                       const RangeSet::ContainerType &RHS) {
519fe6060f1SDimitry Andric   ContainerType Result;
520fe6060f1SDimitry Andric   Result.reserve(std::max(LHS.size(), RHS.size()));
521fe6060f1SDimitry Andric 
522fe6060f1SDimitry Andric   const_iterator First = LHS.begin(), Second = RHS.begin(),
523fe6060f1SDimitry Andric                  FirstEnd = LHS.end(), SecondEnd = RHS.end();
524fe6060f1SDimitry Andric 
525fe6060f1SDimitry Andric   // If we ran out of ranges in one set, but not in the other,
526fe6060f1SDimitry Andric   // it means that those elements are definitely not in the
527fe6060f1SDimitry Andric   // intersection.
528fe6060f1SDimitry Andric   while (First != FirstEnd && Second != SecondEnd) {
529fe6060f1SDimitry Andric     // We want to keep the following invariant at all times:
530fe6060f1SDimitry Andric     //
531fe6060f1SDimitry Andric     //    ----[ First ---------------------->
532fe6060f1SDimitry Andric     //    --------[ Second ----------------->
533fe6060f1SDimitry Andric     if (Second->From() < First->From())
5340eae32dcSDimitry Andric       swapIterators(First, FirstEnd, Second, SecondEnd);
535fe6060f1SDimitry Andric 
536fe6060f1SDimitry Andric     // Loop where the invariant holds:
537fe6060f1SDimitry Andric     do {
538fe6060f1SDimitry Andric       // Check for the following situation:
539fe6060f1SDimitry Andric       //
540fe6060f1SDimitry Andric       //    ----[ First ]--------------------->
541fe6060f1SDimitry Andric       //    ---------------[ Second ]--------->
542fe6060f1SDimitry Andric       //
543fe6060f1SDimitry Andric       // which means that...
544fe6060f1SDimitry Andric       if (Second->From() > First->To()) {
545fe6060f1SDimitry Andric         // ...First is not in the intersection.
546fe6060f1SDimitry Andric         //
547fe6060f1SDimitry Andric         // We should move on to the next range after First and break out of the
548fe6060f1SDimitry Andric         // loop because the invariant might not be true.
549fe6060f1SDimitry Andric         ++First;
550fe6060f1SDimitry Andric         break;
551fe6060f1SDimitry Andric       }
552fe6060f1SDimitry Andric 
553fe6060f1SDimitry Andric       // We have a guaranteed intersection at this point!
554fe6060f1SDimitry Andric       // And this is the current situation:
555fe6060f1SDimitry Andric       //
556fe6060f1SDimitry Andric       //    ----[   First   ]----------------->
557fe6060f1SDimitry Andric       //    -------[ Second ------------------>
558fe6060f1SDimitry Andric       //
559fe6060f1SDimitry Andric       // Additionally, it definitely starts with Second->From().
560fe6060f1SDimitry Andric       const llvm::APSInt &IntersectionStart = Second->From();
561fe6060f1SDimitry Andric 
562fe6060f1SDimitry Andric       // It is important to know which of the two ranges' ends
563fe6060f1SDimitry Andric       // is greater.  That "longer" range might have some other
564fe6060f1SDimitry Andric       // intersections, while the "shorter" range might not.
565fe6060f1SDimitry Andric       if (Second->To() > First->To()) {
566fe6060f1SDimitry Andric         // Here we make a decision to keep First as the "longer"
567fe6060f1SDimitry Andric         // range.
5680eae32dcSDimitry Andric         swapIterators(First, FirstEnd, Second, SecondEnd);
569fe6060f1SDimitry Andric       }
570fe6060f1SDimitry Andric 
571fe6060f1SDimitry Andric       // At this point, we have the following situation:
572fe6060f1SDimitry Andric       //
573fe6060f1SDimitry Andric       //    ---- First      ]-------------------->
574fe6060f1SDimitry Andric       //    ---- Second ]--[  Second+1 ---------->
575fe6060f1SDimitry Andric       //
576fe6060f1SDimitry Andric       // We don't know the relationship between First->From and
577fe6060f1SDimitry Andric       // Second->From and we don't know whether Second+1 intersects
578fe6060f1SDimitry Andric       // with First.
579fe6060f1SDimitry Andric       //
580fe6060f1SDimitry Andric       // However, we know that [IntersectionStart, Second->To] is
581fe6060f1SDimitry Andric       // a part of the intersection...
582fe6060f1SDimitry Andric       Result.push_back(Range(IntersectionStart, Second->To()));
583fe6060f1SDimitry Andric       ++Second;
584fe6060f1SDimitry Andric       // ...and that the invariant will hold for a valid Second+1
585fe6060f1SDimitry Andric       // because First->From <= Second->To < (Second+1)->From.
586fe6060f1SDimitry Andric     } while (Second != SecondEnd);
587fe6060f1SDimitry Andric   }
588fe6060f1SDimitry Andric 
589fe6060f1SDimitry Andric   if (Result.empty())
590fe6060f1SDimitry Andric     return getEmptySet();
591fe6060f1SDimitry Andric 
592fe6060f1SDimitry Andric   return makePersistent(std::move(Result));
593fe6060f1SDimitry Andric }
594fe6060f1SDimitry Andric 
595fe6060f1SDimitry Andric RangeSet RangeSet::Factory::intersect(RangeSet LHS, RangeSet RHS) {
596fe6060f1SDimitry Andric   // Shortcut: let's see if the intersection is even possible.
597fe6060f1SDimitry Andric   if (LHS.isEmpty() || RHS.isEmpty() || LHS.getMaxValue() < RHS.getMinValue() ||
598fe6060f1SDimitry Andric       RHS.getMaxValue() < LHS.getMinValue())
599fe6060f1SDimitry Andric     return getEmptySet();
600fe6060f1SDimitry Andric 
601fe6060f1SDimitry Andric   return intersect(*LHS.Impl, *RHS.Impl);
602fe6060f1SDimitry Andric }
603fe6060f1SDimitry Andric 
604fe6060f1SDimitry Andric RangeSet RangeSet::Factory::intersect(RangeSet LHS, llvm::APSInt Point) {
605fe6060f1SDimitry Andric   if (LHS.containsImpl(Point))
606fe6060f1SDimitry Andric     return getRangeSet(ValueFactory.getValue(Point));
607fe6060f1SDimitry Andric 
608fe6060f1SDimitry Andric   return getEmptySet();
609fe6060f1SDimitry Andric }
610fe6060f1SDimitry Andric 
611fe6060f1SDimitry Andric RangeSet RangeSet::Factory::negate(RangeSet What) {
612fe6060f1SDimitry Andric   if (What.isEmpty())
613fe6060f1SDimitry Andric     return getEmptySet();
614fe6060f1SDimitry Andric 
615fe6060f1SDimitry Andric   const llvm::APSInt SampleValue = What.getMinValue();
616fe6060f1SDimitry Andric   const llvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
617fe6060f1SDimitry Andric   const llvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
618fe6060f1SDimitry Andric 
619fe6060f1SDimitry Andric   ContainerType Result;
620fe6060f1SDimitry Andric   Result.reserve(What.size() + (SampleValue == MIN));
6215ffd83dbSDimitry Andric 
6225ffd83dbSDimitry Andric   // Handle a special case for MIN value.
623fe6060f1SDimitry Andric   const_iterator It = What.begin();
624fe6060f1SDimitry Andric   const_iterator End = What.end();
625fe6060f1SDimitry Andric 
626fe6060f1SDimitry Andric   const llvm::APSInt &From = It->From();
627fe6060f1SDimitry Andric   const llvm::APSInt &To = It->To();
628fe6060f1SDimitry Andric 
629fe6060f1SDimitry Andric   if (From == MIN) {
630fe6060f1SDimitry Andric     // If the range [From, To] is [MIN, MAX], then result is also [MIN, MAX].
631fe6060f1SDimitry Andric     if (To == MAX) {
632fe6060f1SDimitry Andric       return What;
633fe6060f1SDimitry Andric     }
634fe6060f1SDimitry Andric 
635fe6060f1SDimitry Andric     const_iterator Last = std::prev(End);
636fe6060f1SDimitry Andric 
637fe6060f1SDimitry Andric     // Try to find and unite the following ranges:
638fe6060f1SDimitry Andric     // [MIN, MIN] & [MIN + 1, N] => [MIN, N].
639fe6060f1SDimitry Andric     if (Last->To() == MAX) {
640fe6060f1SDimitry Andric       // It means that in the original range we have ranges
641fe6060f1SDimitry Andric       //   [MIN, A], ... , [B, MAX]
642fe6060f1SDimitry Andric       // And the result should be [MIN, -B], ..., [-A, MAX]
643fe6060f1SDimitry Andric       Result.emplace_back(MIN, ValueFactory.getValue(-Last->From()));
644fe6060f1SDimitry Andric       // We already negated Last, so we can skip it.
645fe6060f1SDimitry Andric       End = Last;
6465ffd83dbSDimitry Andric     } else {
647fe6060f1SDimitry Andric       // Add a separate range for the lowest value.
648fe6060f1SDimitry Andric       Result.emplace_back(MIN, MIN);
6495ffd83dbSDimitry Andric     }
650fe6060f1SDimitry Andric 
651fe6060f1SDimitry Andric     // Skip adding the second range in case when [From, To] are [MIN, MIN].
652fe6060f1SDimitry Andric     if (To != MIN) {
653fe6060f1SDimitry Andric       Result.emplace_back(ValueFactory.getValue(-To), MAX);
6545ffd83dbSDimitry Andric     }
655fe6060f1SDimitry Andric 
6565ffd83dbSDimitry Andric     // Skip the first range in the loop.
657fe6060f1SDimitry Andric     ++It;
6585ffd83dbSDimitry Andric   }
6595ffd83dbSDimitry Andric 
6605ffd83dbSDimitry Andric   // Negate all other ranges.
661fe6060f1SDimitry Andric   for (; It != End; ++It) {
6625ffd83dbSDimitry Andric     // Negate int values.
663fe6060f1SDimitry Andric     const llvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
664fe6060f1SDimitry Andric     const llvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
665fe6060f1SDimitry Andric 
6665ffd83dbSDimitry Andric     // Add a negated range.
667fe6060f1SDimitry Andric     Result.emplace_back(NewFrom, NewTo);
6680b57cec5SDimitry Andric   }
6695ffd83dbSDimitry Andric 
670fe6060f1SDimitry Andric   llvm::sort(Result);
671fe6060f1SDimitry Andric   return makePersistent(std::move(Result));
6720b57cec5SDimitry Andric }
6730b57cec5SDimitry Andric 
67481ad6265SDimitry Andric // Convert range set to the given integral type using truncation and promotion.
67581ad6265SDimitry Andric // This works similar to APSIntType::apply function but for the range set.
67681ad6265SDimitry Andric RangeSet RangeSet::Factory::castTo(RangeSet What, APSIntType Ty) {
67781ad6265SDimitry Andric   // Set is empty or NOOP (aka cast to the same type).
67881ad6265SDimitry Andric   if (What.isEmpty() || What.getAPSIntType() == Ty)
67981ad6265SDimitry Andric     return What;
68081ad6265SDimitry Andric 
68181ad6265SDimitry Andric   const bool IsConversion = What.isUnsigned() != Ty.isUnsigned();
68281ad6265SDimitry Andric   const bool IsTruncation = What.getBitWidth() > Ty.getBitWidth();
68381ad6265SDimitry Andric   const bool IsPromotion = What.getBitWidth() < Ty.getBitWidth();
68481ad6265SDimitry Andric 
68581ad6265SDimitry Andric   if (IsTruncation)
68681ad6265SDimitry Andric     return makePersistent(truncateTo(What, Ty));
68781ad6265SDimitry Andric 
68881ad6265SDimitry Andric   // Here we handle 2 cases:
68981ad6265SDimitry Andric   // - IsConversion && !IsPromotion.
69081ad6265SDimitry Andric   //   In this case we handle changing a sign with same bitwidth: char -> uchar,
69181ad6265SDimitry Andric   //   uint -> int. Here we convert negatives to positives and positives which
69281ad6265SDimitry Andric   //   is out of range to negatives. We use convertTo function for that.
69381ad6265SDimitry Andric   // - IsConversion && IsPromotion && !What.isUnsigned().
69481ad6265SDimitry Andric   //   In this case we handle changing a sign from signeds to unsigneds with
69581ad6265SDimitry Andric   //   higher bitwidth: char -> uint, int-> uint64. The point is that we also
69681ad6265SDimitry Andric   //   need convert negatives to positives and use convertTo function as well.
69781ad6265SDimitry Andric   //   For example, we don't need such a convertion when converting unsigned to
69881ad6265SDimitry Andric   //   signed with higher bitwidth, because all the values of unsigned is valid
69981ad6265SDimitry Andric   //   for the such signed.
70081ad6265SDimitry Andric   if (IsConversion && (!IsPromotion || !What.isUnsigned()))
70181ad6265SDimitry Andric     return makePersistent(convertTo(What, Ty));
70281ad6265SDimitry Andric 
70381ad6265SDimitry Andric   assert(IsPromotion && "Only promotion operation from unsigneds left.");
70481ad6265SDimitry Andric   return makePersistent(promoteTo(What, Ty));
70581ad6265SDimitry Andric }
70681ad6265SDimitry Andric 
70781ad6265SDimitry Andric RangeSet RangeSet::Factory::castTo(RangeSet What, QualType T) {
70881ad6265SDimitry Andric   assert(T->isIntegralOrEnumerationType() && "T shall be an integral type.");
70981ad6265SDimitry Andric   return castTo(What, ValueFactory.getAPSIntType(T));
71081ad6265SDimitry Andric }
71181ad6265SDimitry Andric 
71281ad6265SDimitry Andric RangeSet::ContainerType RangeSet::Factory::truncateTo(RangeSet What,
71381ad6265SDimitry Andric                                                       APSIntType Ty) {
71481ad6265SDimitry Andric   using llvm::APInt;
71581ad6265SDimitry Andric   using llvm::APSInt;
71681ad6265SDimitry Andric   ContainerType Result;
71781ad6265SDimitry Andric   ContainerType Dummy;
71881ad6265SDimitry Andric   // CastRangeSize is an amount of all possible values of cast type.
71981ad6265SDimitry Andric   // Example: `char` has 256 values; `short` has 65536 values.
72081ad6265SDimitry Andric   // But in fact we use `amount of values` - 1, because
72181ad6265SDimitry Andric   // we can't keep `amount of values of UINT64` inside uint64_t.
72281ad6265SDimitry Andric   // E.g. 256 is an amount of all possible values of `char` and we can't keep
72381ad6265SDimitry Andric   // it inside `char`.
72481ad6265SDimitry Andric   // And it's OK, it's enough to do correct calculations.
72581ad6265SDimitry Andric   uint64_t CastRangeSize = APInt::getMaxValue(Ty.getBitWidth()).getZExtValue();
72681ad6265SDimitry Andric   for (const Range &R : What) {
72781ad6265SDimitry Andric     // Get bounds of the given range.
72881ad6265SDimitry Andric     APSInt FromInt = R.From();
72981ad6265SDimitry Andric     APSInt ToInt = R.To();
73081ad6265SDimitry Andric     // CurrentRangeSize is an amount of all possible values of the current
73181ad6265SDimitry Andric     // range minus one.
73281ad6265SDimitry Andric     uint64_t CurrentRangeSize = (ToInt - FromInt).getZExtValue();
73381ad6265SDimitry Andric     // This is an optimization for a specific case when this Range covers
73481ad6265SDimitry Andric     // the whole range of the target type.
73581ad6265SDimitry Andric     Dummy.clear();
73681ad6265SDimitry Andric     if (CurrentRangeSize >= CastRangeSize) {
73781ad6265SDimitry Andric       Dummy.emplace_back(ValueFactory.getMinValue(Ty),
73881ad6265SDimitry Andric                          ValueFactory.getMaxValue(Ty));
73981ad6265SDimitry Andric       Result = std::move(Dummy);
74081ad6265SDimitry Andric       break;
74181ad6265SDimitry Andric     }
74281ad6265SDimitry Andric     // Cast the bounds.
74381ad6265SDimitry Andric     Ty.apply(FromInt);
74481ad6265SDimitry Andric     Ty.apply(ToInt);
74581ad6265SDimitry Andric     const APSInt &PersistentFrom = ValueFactory.getValue(FromInt);
74681ad6265SDimitry Andric     const APSInt &PersistentTo = ValueFactory.getValue(ToInt);
74781ad6265SDimitry Andric     if (FromInt > ToInt) {
74881ad6265SDimitry Andric       Dummy.emplace_back(ValueFactory.getMinValue(Ty), PersistentTo);
74981ad6265SDimitry Andric       Dummy.emplace_back(PersistentFrom, ValueFactory.getMaxValue(Ty));
75081ad6265SDimitry Andric     } else
75181ad6265SDimitry Andric       Dummy.emplace_back(PersistentFrom, PersistentTo);
75281ad6265SDimitry Andric     // Every range retrieved after truncation potentialy has garbage values.
75381ad6265SDimitry Andric     // So, we have to unite every next range with the previouses.
75481ad6265SDimitry Andric     Result = unite(Result, Dummy);
75581ad6265SDimitry Andric   }
75681ad6265SDimitry Andric 
75781ad6265SDimitry Andric   return Result;
75881ad6265SDimitry Andric }
75981ad6265SDimitry Andric 
76081ad6265SDimitry Andric // Divide the convertion into two phases (presented as loops here).
76181ad6265SDimitry Andric // First phase(loop) works when casted values go in ascending order.
76281ad6265SDimitry Andric // E.g. char{1,3,5,127} -> uint{1,3,5,127}
76381ad6265SDimitry Andric // Interrupt the first phase and go to second one when casted values start
76481ad6265SDimitry Andric // go in descending order. That means that we crossed over the middle of
76581ad6265SDimitry Andric // the type value set (aka 0 for signeds and MAX/2+1 for unsigneds).
76681ad6265SDimitry Andric // For instance:
76781ad6265SDimitry Andric // 1: uchar{1,3,5,128,255} -> char{1,3,5,-128,-1}
76881ad6265SDimitry Andric //    Here we put {1,3,5} to one array and {-128, -1} to another
76981ad6265SDimitry Andric // 2: char{-128,-127,-1,0,1,2} -> uchar{128,129,255,0,1,3}
77081ad6265SDimitry Andric //    Here we put {128,129,255} to one array and {0,1,3} to another.
77181ad6265SDimitry Andric // After that we unite both arrays.
77281ad6265SDimitry Andric // NOTE: We don't just concatenate the arrays, because they may have
77381ad6265SDimitry Andric // adjacent ranges, e.g.:
77481ad6265SDimitry Andric // 1: char(-128, 127) -> uchar -> arr1(128, 255), arr2(0, 127) ->
77581ad6265SDimitry Andric //    unite -> uchar(0, 255)
77681ad6265SDimitry Andric // 2: uchar(0, 1)U(254, 255) -> char -> arr1(0, 1), arr2(-2, -1) ->
77781ad6265SDimitry Andric //    unite -> uchar(-2, 1)
77881ad6265SDimitry Andric RangeSet::ContainerType RangeSet::Factory::convertTo(RangeSet What,
77981ad6265SDimitry Andric                                                      APSIntType Ty) {
78081ad6265SDimitry Andric   using llvm::APInt;
78181ad6265SDimitry Andric   using llvm::APSInt;
78281ad6265SDimitry Andric   using Bounds = std::pair<const APSInt &, const APSInt &>;
78381ad6265SDimitry Andric   ContainerType AscendArray;
78481ad6265SDimitry Andric   ContainerType DescendArray;
78581ad6265SDimitry Andric   auto CastRange = [Ty, &VF = ValueFactory](const Range &R) -> Bounds {
78681ad6265SDimitry Andric     // Get bounds of the given range.
78781ad6265SDimitry Andric     APSInt FromInt = R.From();
78881ad6265SDimitry Andric     APSInt ToInt = R.To();
78981ad6265SDimitry Andric     // Cast the bounds.
79081ad6265SDimitry Andric     Ty.apply(FromInt);
79181ad6265SDimitry Andric     Ty.apply(ToInt);
79281ad6265SDimitry Andric     return {VF.getValue(FromInt), VF.getValue(ToInt)};
79381ad6265SDimitry Andric   };
79481ad6265SDimitry Andric   // Phase 1. Fill the first array.
79581ad6265SDimitry Andric   APSInt LastConvertedInt = Ty.getMinValue();
79681ad6265SDimitry Andric   const auto *It = What.begin();
79781ad6265SDimitry Andric   const auto *E = What.end();
79881ad6265SDimitry Andric   while (It != E) {
79981ad6265SDimitry Andric     Bounds NewBounds = CastRange(*(It++));
80081ad6265SDimitry Andric     // If values stop going acsending order, go to the second phase(loop).
80181ad6265SDimitry Andric     if (NewBounds.first < LastConvertedInt) {
80281ad6265SDimitry Andric       DescendArray.emplace_back(NewBounds.first, NewBounds.second);
80381ad6265SDimitry Andric       break;
80481ad6265SDimitry Andric     }
80581ad6265SDimitry Andric     // If the range contains a midpoint, then split the range.
80681ad6265SDimitry Andric     // E.g. char(-5, 5) -> uchar(251, 5)
80781ad6265SDimitry Andric     // Here we shall add a range (251, 255) to the first array and (0, 5) to the
80881ad6265SDimitry Andric     // second one.
80981ad6265SDimitry Andric     if (NewBounds.first > NewBounds.second) {
81081ad6265SDimitry Andric       DescendArray.emplace_back(ValueFactory.getMinValue(Ty), NewBounds.second);
81181ad6265SDimitry Andric       AscendArray.emplace_back(NewBounds.first, ValueFactory.getMaxValue(Ty));
81281ad6265SDimitry Andric     } else
81381ad6265SDimitry Andric       // Values are going acsending order.
81481ad6265SDimitry Andric       AscendArray.emplace_back(NewBounds.first, NewBounds.second);
81581ad6265SDimitry Andric     LastConvertedInt = NewBounds.first;
81681ad6265SDimitry Andric   }
81781ad6265SDimitry Andric   // Phase 2. Fill the second array.
81881ad6265SDimitry Andric   while (It != E) {
81981ad6265SDimitry Andric     Bounds NewBounds = CastRange(*(It++));
82081ad6265SDimitry Andric     DescendArray.emplace_back(NewBounds.first, NewBounds.second);
82181ad6265SDimitry Andric   }
82281ad6265SDimitry Andric   // Unite both arrays.
82381ad6265SDimitry Andric   return unite(AscendArray, DescendArray);
82481ad6265SDimitry Andric }
82581ad6265SDimitry Andric 
82681ad6265SDimitry Andric /// Promotion from unsigneds to signeds/unsigneds left.
82781ad6265SDimitry Andric RangeSet::ContainerType RangeSet::Factory::promoteTo(RangeSet What,
82881ad6265SDimitry Andric                                                      APSIntType Ty) {
82981ad6265SDimitry Andric   ContainerType Result;
83081ad6265SDimitry Andric   // We definitely know the size of the result set.
83181ad6265SDimitry Andric   Result.reserve(What.size());
83281ad6265SDimitry Andric 
83381ad6265SDimitry Andric   // Each unsigned value fits every larger type without any changes,
83481ad6265SDimitry Andric   // whether the larger type is signed or unsigned. So just promote and push
83581ad6265SDimitry Andric   // back each range one by one.
83681ad6265SDimitry Andric   for (const Range &R : What) {
83781ad6265SDimitry Andric     // Get bounds of the given range.
83881ad6265SDimitry Andric     llvm::APSInt FromInt = R.From();
83981ad6265SDimitry Andric     llvm::APSInt ToInt = R.To();
84081ad6265SDimitry Andric     // Cast the bounds.
84181ad6265SDimitry Andric     Ty.apply(FromInt);
84281ad6265SDimitry Andric     Ty.apply(ToInt);
84381ad6265SDimitry Andric     Result.emplace_back(ValueFactory.getValue(FromInt),
84481ad6265SDimitry Andric                         ValueFactory.getValue(ToInt));
84581ad6265SDimitry Andric   }
84681ad6265SDimitry Andric   return Result;
84781ad6265SDimitry Andric }
84881ad6265SDimitry Andric 
849fe6060f1SDimitry Andric RangeSet RangeSet::Factory::deletePoint(RangeSet From,
850fe6060f1SDimitry Andric                                         const llvm::APSInt &Point) {
851fe6060f1SDimitry Andric   if (!From.contains(Point))
852fe6060f1SDimitry Andric     return From;
8530b57cec5SDimitry Andric 
854e8d8bef9SDimitry Andric   llvm::APSInt Upper = Point;
855e8d8bef9SDimitry Andric   llvm::APSInt Lower = Point;
856e8d8bef9SDimitry Andric 
857e8d8bef9SDimitry Andric   ++Upper;
858e8d8bef9SDimitry Andric   --Lower;
859e8d8bef9SDimitry Andric 
860e8d8bef9SDimitry Andric   // Notice that the lower bound is greater than the upper bound.
861fe6060f1SDimitry Andric   return intersect(From, Upper, Lower);
862e8d8bef9SDimitry Andric }
863e8d8bef9SDimitry Andric 
864349cc55cSDimitry Andric LLVM_DUMP_METHOD void Range::dump(raw_ostream &OS) const {
865fe6060f1SDimitry Andric   OS << '[' << toString(From(), 10) << ", " << toString(To(), 10) << ']';
8660b57cec5SDimitry Andric }
867349cc55cSDimitry Andric LLVM_DUMP_METHOD void Range::dump() const { dump(llvm::errs()); }
868fe6060f1SDimitry Andric 
869349cc55cSDimitry Andric LLVM_DUMP_METHOD void RangeSet::dump(raw_ostream &OS) const {
870fe6060f1SDimitry Andric   OS << "{ ";
871fe6060f1SDimitry Andric   llvm::interleaveComma(*this, OS, [&OS](const Range &R) { R.dump(OS); });
872fe6060f1SDimitry Andric   OS << " }";
8730b57cec5SDimitry Andric }
874349cc55cSDimitry Andric LLVM_DUMP_METHOD void RangeSet::dump() const { dump(llvm::errs()); }
8750b57cec5SDimitry Andric 
876e8d8bef9SDimitry Andric REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef)
877e8d8bef9SDimitry Andric 
8780b57cec5SDimitry Andric namespace {
879e8d8bef9SDimitry Andric class EquivalenceClass;
880e8d8bef9SDimitry Andric } // end anonymous namespace
881e8d8bef9SDimitry Andric 
882e8d8bef9SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(ClassMap, SymbolRef, EquivalenceClass)
883e8d8bef9SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(ClassMembers, EquivalenceClass, SymbolSet)
884e8d8bef9SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(ConstraintRange, EquivalenceClass, RangeSet)
885e8d8bef9SDimitry Andric 
886e8d8bef9SDimitry Andric REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(ClassSet, EquivalenceClass)
887e8d8bef9SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(DisequalityMap, EquivalenceClass, ClassSet)
888e8d8bef9SDimitry Andric 
889e8d8bef9SDimitry Andric namespace {
890e8d8bef9SDimitry Andric /// This class encapsulates a set of symbols equal to each other.
891e8d8bef9SDimitry Andric ///
892e8d8bef9SDimitry Andric /// The main idea of the approach requiring such classes is in narrowing
893e8d8bef9SDimitry Andric /// and sharing constraints between symbols within the class.  Also we can
894e8d8bef9SDimitry Andric /// conclude that there is no practical need in storing constraints for
895e8d8bef9SDimitry Andric /// every member of the class separately.
896e8d8bef9SDimitry Andric ///
897e8d8bef9SDimitry Andric /// Main terminology:
898e8d8bef9SDimitry Andric ///
899e8d8bef9SDimitry Andric ///   * "Equivalence class" is an object of this class, which can be efficiently
900e8d8bef9SDimitry Andric ///     compared to other classes.  It represents the whole class without
901e8d8bef9SDimitry Andric ///     storing the actual in it.  The members of the class however can be
902e8d8bef9SDimitry Andric ///     retrieved from the state.
903e8d8bef9SDimitry Andric ///
904e8d8bef9SDimitry Andric ///   * "Class members" are the symbols corresponding to the class.  This means
905e8d8bef9SDimitry Andric ///     that A == B for every member symbols A and B from the class.  Members of
906e8d8bef9SDimitry Andric ///     each class are stored in the state.
907e8d8bef9SDimitry Andric ///
908e8d8bef9SDimitry Andric ///   * "Trivial class" is a class that has and ever had only one same symbol.
909e8d8bef9SDimitry Andric ///
910e8d8bef9SDimitry Andric ///   * "Merge operation" merges two classes into one.  It is the main operation
911e8d8bef9SDimitry Andric ///     to produce non-trivial classes.
912e8d8bef9SDimitry Andric ///     If, at some point, we can assume that two symbols from two distinct
913e8d8bef9SDimitry Andric ///     classes are equal, we can merge these classes.
914e8d8bef9SDimitry Andric class EquivalenceClass : public llvm::FoldingSetNode {
915e8d8bef9SDimitry Andric public:
916e8d8bef9SDimitry Andric   /// Find equivalence class for the given symbol in the given state.
917bdd1243dSDimitry Andric   [[nodiscard]] static inline EquivalenceClass find(ProgramStateRef State,
918e8d8bef9SDimitry Andric                                                     SymbolRef Sym);
919e8d8bef9SDimitry Andric 
920e8d8bef9SDimitry Andric   /// Merge classes for the given symbols and return a new state.
921bdd1243dSDimitry Andric   [[nodiscard]] static inline ProgramStateRef merge(RangeSet::Factory &F,
922e8d8bef9SDimitry Andric                                                     ProgramStateRef State,
923fe6060f1SDimitry Andric                                                     SymbolRef First,
924fe6060f1SDimitry Andric                                                     SymbolRef Second);
925fe6060f1SDimitry Andric   // Merge this class with the given class and return a new state.
926bdd1243dSDimitry Andric   [[nodiscard]] inline ProgramStateRef
927fe6060f1SDimitry Andric   merge(RangeSet::Factory &F, ProgramStateRef State, EquivalenceClass Other);
928e8d8bef9SDimitry Andric 
929e8d8bef9SDimitry Andric   /// Return a set of class members for the given state.
930bdd1243dSDimitry Andric   [[nodiscard]] inline SymbolSet getClassMembers(ProgramStateRef State) const;
931fe6060f1SDimitry Andric 
932e8d8bef9SDimitry Andric   /// Return true if the current class is trivial in the given state.
933fe6060f1SDimitry Andric   /// A class is trivial if and only if there is not any member relations stored
934fe6060f1SDimitry Andric   /// to it in State/ClassMembers.
935fe6060f1SDimitry Andric   /// An equivalence class with one member might seem as it does not hold any
936fe6060f1SDimitry Andric   /// meaningful information, i.e. that is a tautology. However, during the
937fe6060f1SDimitry Andric   /// removal of dead symbols we do not remove classes with one member for
938fe6060f1SDimitry Andric   /// resource and performance reasons. Consequently, a class with one member is
939fe6060f1SDimitry Andric   /// not necessarily trivial. It could happen that we have a class with two
940fe6060f1SDimitry Andric   /// members and then during the removal of dead symbols we remove one of its
941fe6060f1SDimitry Andric   /// members. In this case, the class is still non-trivial (it still has the
942fe6060f1SDimitry Andric   /// mappings in ClassMembers), even though it has only one member.
943bdd1243dSDimitry Andric   [[nodiscard]] inline bool isTrivial(ProgramStateRef State) const;
944fe6060f1SDimitry Andric 
945e8d8bef9SDimitry Andric   /// Return true if the current class is trivial and its only member is dead.
946bdd1243dSDimitry Andric   [[nodiscard]] inline bool isTriviallyDead(ProgramStateRef State,
947fe6060f1SDimitry Andric                                             SymbolReaper &Reaper) const;
948e8d8bef9SDimitry Andric 
949bdd1243dSDimitry Andric   [[nodiscard]] static inline ProgramStateRef
950fe6060f1SDimitry Andric   markDisequal(RangeSet::Factory &F, ProgramStateRef State, SymbolRef First,
951fe6060f1SDimitry Andric                SymbolRef Second);
952bdd1243dSDimitry Andric   [[nodiscard]] static inline ProgramStateRef
953fe6060f1SDimitry Andric   markDisequal(RangeSet::Factory &F, ProgramStateRef State,
954fe6060f1SDimitry Andric                EquivalenceClass First, EquivalenceClass Second);
955bdd1243dSDimitry Andric   [[nodiscard]] inline ProgramStateRef
956fe6060f1SDimitry Andric   markDisequal(RangeSet::Factory &F, ProgramStateRef State,
957fe6060f1SDimitry Andric                EquivalenceClass Other) const;
958bdd1243dSDimitry Andric   [[nodiscard]] static inline ClassSet getDisequalClasses(ProgramStateRef State,
959bdd1243dSDimitry Andric                                                           SymbolRef Sym);
960bdd1243dSDimitry Andric   [[nodiscard]] inline ClassSet getDisequalClasses(ProgramStateRef State) const;
961bdd1243dSDimitry Andric   [[nodiscard]] inline ClassSet
962e8d8bef9SDimitry Andric   getDisequalClasses(DisequalityMapTy Map, ClassSet::Factory &Factory) const;
963e8d8bef9SDimitry Andric 
964bdd1243dSDimitry Andric   [[nodiscard]] static inline std::optional<bool>
965bdd1243dSDimitry Andric   areEqual(ProgramStateRef State, EquivalenceClass First,
966fe6060f1SDimitry Andric            EquivalenceClass Second);
967bdd1243dSDimitry Andric   [[nodiscard]] static inline std::optional<bool>
968e8d8bef9SDimitry Andric   areEqual(ProgramStateRef State, SymbolRef First, SymbolRef Second);
969e8d8bef9SDimitry Andric 
970349cc55cSDimitry Andric   /// Remove one member from the class.
971bdd1243dSDimitry Andric   [[nodiscard]] ProgramStateRef removeMember(ProgramStateRef State,
972349cc55cSDimitry Andric                                              const SymbolRef Old);
973349cc55cSDimitry Andric 
974fe6060f1SDimitry Andric   /// Iterate over all symbols and try to simplify them.
975bdd1243dSDimitry Andric   [[nodiscard]] static inline ProgramStateRef simplify(SValBuilder &SVB,
976fe6060f1SDimitry Andric                                                        RangeSet::Factory &F,
977fe6060f1SDimitry Andric                                                        ProgramStateRef State,
978fe6060f1SDimitry Andric                                                        EquivalenceClass Class);
979fe6060f1SDimitry Andric 
980fe6060f1SDimitry Andric   void dumpToStream(ProgramStateRef State, raw_ostream &os) const;
981fe6060f1SDimitry Andric   LLVM_DUMP_METHOD void dump(ProgramStateRef State) const {
982fe6060f1SDimitry Andric     dumpToStream(State, llvm::errs());
983fe6060f1SDimitry Andric   }
984fe6060f1SDimitry Andric 
985e8d8bef9SDimitry Andric   /// Check equivalence data for consistency.
986bdd1243dSDimitry Andric   [[nodiscard]] LLVM_ATTRIBUTE_UNUSED static bool
987e8d8bef9SDimitry Andric   isClassDataConsistent(ProgramStateRef State);
988e8d8bef9SDimitry Andric 
989bdd1243dSDimitry Andric   [[nodiscard]] QualType getType() const {
990e8d8bef9SDimitry Andric     return getRepresentativeSymbol()->getType();
991e8d8bef9SDimitry Andric   }
992e8d8bef9SDimitry Andric 
993e8d8bef9SDimitry Andric   EquivalenceClass() = delete;
994e8d8bef9SDimitry Andric   EquivalenceClass(const EquivalenceClass &) = default;
995e8d8bef9SDimitry Andric   EquivalenceClass &operator=(const EquivalenceClass &) = delete;
996e8d8bef9SDimitry Andric   EquivalenceClass(EquivalenceClass &&) = default;
997e8d8bef9SDimitry Andric   EquivalenceClass &operator=(EquivalenceClass &&) = delete;
998e8d8bef9SDimitry Andric 
999e8d8bef9SDimitry Andric   bool operator==(const EquivalenceClass &Other) const {
1000e8d8bef9SDimitry Andric     return ID == Other.ID;
1001e8d8bef9SDimitry Andric   }
1002e8d8bef9SDimitry Andric   bool operator<(const EquivalenceClass &Other) const { return ID < Other.ID; }
1003e8d8bef9SDimitry Andric   bool operator!=(const EquivalenceClass &Other) const {
1004e8d8bef9SDimitry Andric     return !operator==(Other);
1005e8d8bef9SDimitry Andric   }
1006e8d8bef9SDimitry Andric 
1007e8d8bef9SDimitry Andric   static void Profile(llvm::FoldingSetNodeID &ID, uintptr_t CID) {
1008e8d8bef9SDimitry Andric     ID.AddInteger(CID);
1009e8d8bef9SDimitry Andric   }
1010e8d8bef9SDimitry Andric 
1011e8d8bef9SDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, this->ID); }
1012e8d8bef9SDimitry Andric 
1013e8d8bef9SDimitry Andric private:
1014e8d8bef9SDimitry Andric   /* implicit */ EquivalenceClass(SymbolRef Sym)
1015e8d8bef9SDimitry Andric       : ID(reinterpret_cast<uintptr_t>(Sym)) {}
1016e8d8bef9SDimitry Andric 
1017e8d8bef9SDimitry Andric   /// This function is intended to be used ONLY within the class.
1018e8d8bef9SDimitry Andric   /// The fact that ID is a pointer to a symbol is an implementation detail
1019e8d8bef9SDimitry Andric   /// and should stay that way.
1020e8d8bef9SDimitry Andric   /// In the current implementation, we use it to retrieve the only member
1021e8d8bef9SDimitry Andric   /// of the trivial class.
1022e8d8bef9SDimitry Andric   SymbolRef getRepresentativeSymbol() const {
1023e8d8bef9SDimitry Andric     return reinterpret_cast<SymbolRef>(ID);
1024e8d8bef9SDimitry Andric   }
1025e8d8bef9SDimitry Andric   static inline SymbolSet::Factory &getMembersFactory(ProgramStateRef State);
1026e8d8bef9SDimitry Andric 
1027fe6060f1SDimitry Andric   inline ProgramStateRef mergeImpl(RangeSet::Factory &F, ProgramStateRef State,
1028fe6060f1SDimitry Andric                                    SymbolSet Members, EquivalenceClass Other,
1029e8d8bef9SDimitry Andric                                    SymbolSet OtherMembers);
1030349cc55cSDimitry Andric 
1031fe6060f1SDimitry Andric   static inline bool
1032e8d8bef9SDimitry Andric   addToDisequalityInfo(DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
1033fe6060f1SDimitry Andric                        RangeSet::Factory &F, ProgramStateRef State,
1034fe6060f1SDimitry Andric                        EquivalenceClass First, EquivalenceClass Second);
1035e8d8bef9SDimitry Andric 
1036e8d8bef9SDimitry Andric   /// This is a unique identifier of the class.
1037e8d8bef9SDimitry Andric   uintptr_t ID;
1038e8d8bef9SDimitry Andric };
1039e8d8bef9SDimitry Andric 
1040e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1041e8d8bef9SDimitry Andric //                             Constraint functions
1042e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1043e8d8bef9SDimitry Andric 
1044bdd1243dSDimitry Andric [[nodiscard]] LLVM_ATTRIBUTE_UNUSED bool
1045fe6060f1SDimitry Andric areFeasible(ConstraintRangeTy Constraints) {
1046fe6060f1SDimitry Andric   return llvm::none_of(
1047fe6060f1SDimitry Andric       Constraints,
1048fe6060f1SDimitry Andric       [](const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1049fe6060f1SDimitry Andric         return ClassConstraint.second.isEmpty();
1050fe6060f1SDimitry Andric       });
1051fe6060f1SDimitry Andric }
1052fe6060f1SDimitry Andric 
1053bdd1243dSDimitry Andric [[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1054e8d8bef9SDimitry Andric                                                    EquivalenceClass Class) {
1055e8d8bef9SDimitry Andric   return State->get<ConstraintRange>(Class);
1056e8d8bef9SDimitry Andric }
1057e8d8bef9SDimitry Andric 
1058bdd1243dSDimitry Andric [[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1059e8d8bef9SDimitry Andric                                                    SymbolRef Sym) {
1060e8d8bef9SDimitry Andric   return getConstraint(State, EquivalenceClass::find(State, Sym));
1061e8d8bef9SDimitry Andric }
1062e8d8bef9SDimitry Andric 
1063bdd1243dSDimitry Andric [[nodiscard]] ProgramStateRef setConstraint(ProgramStateRef State,
1064fe6060f1SDimitry Andric                                             EquivalenceClass Class,
1065fe6060f1SDimitry Andric                                             RangeSet Constraint) {
1066fe6060f1SDimitry Andric   return State->set<ConstraintRange>(Class, Constraint);
1067fe6060f1SDimitry Andric }
1068fe6060f1SDimitry Andric 
1069bdd1243dSDimitry Andric [[nodiscard]] ProgramStateRef setConstraints(ProgramStateRef State,
1070fe6060f1SDimitry Andric                                              ConstraintRangeTy Constraints) {
1071fe6060f1SDimitry Andric   return State->set<ConstraintRange>(Constraints);
1072fe6060f1SDimitry Andric }
1073fe6060f1SDimitry Andric 
1074e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1075e8d8bef9SDimitry Andric //                       Equality/diseqiality abstraction
1076e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1077e8d8bef9SDimitry Andric 
1078fe6060f1SDimitry Andric /// A small helper function for detecting symbolic (dis)equality.
1079e8d8bef9SDimitry Andric ///
1080e8d8bef9SDimitry Andric /// Equality check can have different forms (like a == b or a - b) and this
1081e8d8bef9SDimitry Andric /// class encapsulates those away if the only thing the user wants to check -
1082fe6060f1SDimitry Andric /// whether it's equality/diseqiality or not.
1083e8d8bef9SDimitry Andric ///
1084fe6060f1SDimitry Andric /// \returns true if assuming this Sym to be true means equality of operands
1085fe6060f1SDimitry Andric ///          false if it means disequality of operands
108606c3fb27SDimitry Andric ///          std::nullopt otherwise
1087bdd1243dSDimitry Andric std::optional<bool> meansEquality(const SymSymExpr *Sym) {
1088e8d8bef9SDimitry Andric   switch (Sym->getOpcode()) {
1089e8d8bef9SDimitry Andric   case BO_Sub:
1090e8d8bef9SDimitry Andric     // This case is: A - B != 0 -> disequality check.
1091fe6060f1SDimitry Andric     return false;
1092e8d8bef9SDimitry Andric   case BO_EQ:
1093e8d8bef9SDimitry Andric     // This case is: A == B != 0 -> equality check.
1094fe6060f1SDimitry Andric     return true;
1095e8d8bef9SDimitry Andric   case BO_NE:
1096e8d8bef9SDimitry Andric     // This case is: A != B != 0 -> diseqiality check.
1097fe6060f1SDimitry Andric     return false;
1098e8d8bef9SDimitry Andric   default:
1099bdd1243dSDimitry Andric     return std::nullopt;
1100e8d8bef9SDimitry Andric   }
1101e8d8bef9SDimitry Andric }
1102e8d8bef9SDimitry Andric 
1103e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1104e8d8bef9SDimitry Andric //                            Intersection functions
1105e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1106e8d8bef9SDimitry Andric 
1107e8d8bef9SDimitry Andric template <class SecondTy, class... RestTy>
1108bdd1243dSDimitry Andric [[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1109e8d8bef9SDimitry Andric                                         SecondTy Second, RestTy... Tail);
1110e8d8bef9SDimitry Andric 
1111e8d8bef9SDimitry Andric template <class... RangeTy> struct IntersectionTraits;
1112e8d8bef9SDimitry Andric 
1113e8d8bef9SDimitry Andric template <class... TailTy> struct IntersectionTraits<RangeSet, TailTy...> {
1114e8d8bef9SDimitry Andric   // Found RangeSet, no need to check any further
1115e8d8bef9SDimitry Andric   using Type = RangeSet;
1116e8d8bef9SDimitry Andric };
1117e8d8bef9SDimitry Andric 
1118e8d8bef9SDimitry Andric template <> struct IntersectionTraits<> {
1119e8d8bef9SDimitry Andric   // We ran out of types, and we didn't find any RangeSet, so the result should
1120e8d8bef9SDimitry Andric   // be optional.
1121bdd1243dSDimitry Andric   using Type = std::optional<RangeSet>;
1122e8d8bef9SDimitry Andric };
1123e8d8bef9SDimitry Andric 
1124e8d8bef9SDimitry Andric template <class OptionalOrPointer, class... TailTy>
1125e8d8bef9SDimitry Andric struct IntersectionTraits<OptionalOrPointer, TailTy...> {
1126e8d8bef9SDimitry Andric   // If current type is Optional or a raw pointer, we should keep looking.
1127e8d8bef9SDimitry Andric   using Type = typename IntersectionTraits<TailTy...>::Type;
1128e8d8bef9SDimitry Andric };
1129e8d8bef9SDimitry Andric 
1130e8d8bef9SDimitry Andric template <class EndTy>
1131bdd1243dSDimitry Andric [[nodiscard]] inline EndTy intersect(RangeSet::Factory &F, EndTy End) {
1132bdd1243dSDimitry Andric   // If the list contains only RangeSet or std::optional<RangeSet>, simply
1133bdd1243dSDimitry Andric   // return that range set.
1134e8d8bef9SDimitry Andric   return End;
1135e8d8bef9SDimitry Andric }
1136e8d8bef9SDimitry Andric 
1137bdd1243dSDimitry Andric [[nodiscard]] LLVM_ATTRIBUTE_UNUSED inline std::optional<RangeSet>
1138fe6060f1SDimitry Andric intersect(RangeSet::Factory &F, const RangeSet *End) {
1139bdd1243dSDimitry Andric   // This is an extraneous conversion from a raw pointer into
1140bdd1243dSDimitry Andric   // std::optional<RangeSet>
1141e8d8bef9SDimitry Andric   if (End) {
1142e8d8bef9SDimitry Andric     return *End;
1143e8d8bef9SDimitry Andric   }
1144bdd1243dSDimitry Andric   return std::nullopt;
1145e8d8bef9SDimitry Andric }
1146e8d8bef9SDimitry Andric 
1147e8d8bef9SDimitry Andric template <class... RestTy>
1148bdd1243dSDimitry Andric [[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1149e8d8bef9SDimitry Andric                                         RangeSet Second, RestTy... Tail) {
1150e8d8bef9SDimitry Andric   // Here we call either the <RangeSet,RangeSet,...> or <RangeSet,...> version
1151e8d8bef9SDimitry Andric   // of the function and can be sure that the result is RangeSet.
1152fe6060f1SDimitry Andric   return intersect(F, F.intersect(Head, Second), Tail...);
1153e8d8bef9SDimitry Andric }
1154e8d8bef9SDimitry Andric 
1155e8d8bef9SDimitry Andric template <class SecondTy, class... RestTy>
1156bdd1243dSDimitry Andric [[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1157e8d8bef9SDimitry Andric                                         SecondTy Second, RestTy... Tail) {
1158e8d8bef9SDimitry Andric   if (Second) {
1159e8d8bef9SDimitry Andric     // Here we call the <RangeSet,RangeSet,...> version of the function...
1160fe6060f1SDimitry Andric     return intersect(F, Head, *Second, Tail...);
1161e8d8bef9SDimitry Andric   }
1162e8d8bef9SDimitry Andric   // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163e8d8bef9SDimitry Andric   // means that the result is definitely RangeSet.
1164fe6060f1SDimitry Andric   return intersect(F, Head, Tail...);
1165e8d8bef9SDimitry Andric }
1166e8d8bef9SDimitry Andric 
1167e8d8bef9SDimitry Andric /// Main generic intersect function.
1168e8d8bef9SDimitry Andric /// It intersects all of the given range sets.  If some of the given arguments
1169bdd1243dSDimitry Andric /// don't hold a range set (nullptr or std::nullopt), the function will skip
1170bdd1243dSDimitry Andric /// them.
1171e8d8bef9SDimitry Andric ///
1172e8d8bef9SDimitry Andric /// Available representations for the arguments are:
1173e8d8bef9SDimitry Andric ///   * RangeSet
1174bdd1243dSDimitry Andric ///   * std::optional<RangeSet>
1175e8d8bef9SDimitry Andric ///   * RangeSet *
1176e8d8bef9SDimitry Andric /// Pointer to a RangeSet is automatically assumed to be nullable and will get
1177e8d8bef9SDimitry Andric /// checked as well as the optional version.  If this behaviour is undesired,
1178e8d8bef9SDimitry Andric /// please dereference the pointer in the call.
1179e8d8bef9SDimitry Andric ///
1180e8d8bef9SDimitry Andric /// Return type depends on the arguments' types.  If we can be sure in compile
1181e8d8bef9SDimitry Andric /// time that there will be a range set as a result, the returning type is
1182bdd1243dSDimitry Andric /// simply RangeSet, in other cases we have to back off to
1183bdd1243dSDimitry Andric /// std::optional<RangeSet>.
1184e8d8bef9SDimitry Andric ///
1185e8d8bef9SDimitry Andric /// Please, prefer optional range sets to raw pointers.  If the last argument is
1186bdd1243dSDimitry Andric /// a raw pointer and all previous arguments are std::nullopt, it will cost one
1187bdd1243dSDimitry Andric /// additional check to convert RangeSet * into std::optional<RangeSet>.
1188e8d8bef9SDimitry Andric template <class HeadTy, class SecondTy, class... RestTy>
1189bdd1243dSDimitry Andric [[nodiscard]] inline
1190e8d8bef9SDimitry Andric     typename IntersectionTraits<HeadTy, SecondTy, RestTy...>::Type
1191fe6060f1SDimitry Andric     intersect(RangeSet::Factory &F, HeadTy Head, SecondTy Second,
1192fe6060f1SDimitry Andric               RestTy... Tail) {
1193e8d8bef9SDimitry Andric   if (Head) {
1194fe6060f1SDimitry Andric     return intersect(F, *Head, Second, Tail...);
1195e8d8bef9SDimitry Andric   }
1196fe6060f1SDimitry Andric   return intersect(F, Second, Tail...);
1197e8d8bef9SDimitry Andric }
1198e8d8bef9SDimitry Andric 
1199e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1200e8d8bef9SDimitry Andric //                           Symbolic reasoning logic
1201e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
12025ffd83dbSDimitry Andric 
12035ffd83dbSDimitry Andric /// A little component aggregating all of the reasoning we have about
12045ffd83dbSDimitry Andric /// the ranges of symbolic expressions.
12055ffd83dbSDimitry Andric ///
12065ffd83dbSDimitry Andric /// Even when we don't know the exact values of the operands, we still
12075ffd83dbSDimitry Andric /// can get a pretty good estimate of the result's range.
12085ffd83dbSDimitry Andric class SymbolicRangeInferrer
12095ffd83dbSDimitry Andric     : public SymExprVisitor<SymbolicRangeInferrer, RangeSet> {
12105ffd83dbSDimitry Andric public:
1211e8d8bef9SDimitry Andric   template <class SourceType>
1212fe6060f1SDimitry Andric   static RangeSet inferRange(RangeSet::Factory &F, ProgramStateRef State,
1213fe6060f1SDimitry Andric                              SourceType Origin) {
1214fe6060f1SDimitry Andric     SymbolicRangeInferrer Inferrer(F, State);
1215e8d8bef9SDimitry Andric     return Inferrer.infer(Origin);
12165ffd83dbSDimitry Andric   }
12175ffd83dbSDimitry Andric 
12185ffd83dbSDimitry Andric   RangeSet VisitSymExpr(SymbolRef Sym) {
1219bdd1243dSDimitry Andric     if (std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1220fcaf7f86SDimitry Andric       return *RS;
1221fcaf7f86SDimitry Andric     // If we've reached this line, the actual type of the symbolic
12225ffd83dbSDimitry Andric     // expression is not supported for advanced inference.
12235ffd83dbSDimitry Andric     // In this case, we simply backoff to the default "let's simply
12245ffd83dbSDimitry Andric     // infer the range from the expression's type".
12255ffd83dbSDimitry Andric     return infer(Sym->getType());
12265ffd83dbSDimitry Andric   }
12275ffd83dbSDimitry Andric 
1228fcaf7f86SDimitry Andric   RangeSet VisitUnarySymExpr(const UnarySymExpr *USE) {
1229bdd1243dSDimitry Andric     if (std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1230fcaf7f86SDimitry Andric       return *RS;
1231fcaf7f86SDimitry Andric     return infer(USE->getType());
1232fcaf7f86SDimitry Andric   }
1233fcaf7f86SDimitry Andric 
12345ffd83dbSDimitry Andric   RangeSet VisitSymIntExpr(const SymIntExpr *Sym) {
12355ffd83dbSDimitry Andric     return VisitBinaryOperator(Sym);
12365ffd83dbSDimitry Andric   }
12375ffd83dbSDimitry Andric 
12385ffd83dbSDimitry Andric   RangeSet VisitIntSymExpr(const IntSymExpr *Sym) {
12395ffd83dbSDimitry Andric     return VisitBinaryOperator(Sym);
12405ffd83dbSDimitry Andric   }
12415ffd83dbSDimitry Andric 
1242fcaf7f86SDimitry Andric   RangeSet VisitSymSymExpr(const SymSymExpr *SSE) {
1243fe6060f1SDimitry Andric     return intersect(
1244fe6060f1SDimitry Andric         RangeFactory,
1245fcaf7f86SDimitry Andric         // If Sym is a difference of symbols A - B, then maybe we have range
1246fcaf7f86SDimitry Andric         // set stored for B - A.
1247fcaf7f86SDimitry Andric         //
1248fcaf7f86SDimitry Andric         // If we have range set stored for both A - B and B - A then
1249fcaf7f86SDimitry Andric         // calculate the effective range set by intersecting the range set
1250fcaf7f86SDimitry Andric         // for A - B and the negated range set of B - A.
1251fcaf7f86SDimitry Andric         getRangeForNegatedSymSym(SSE),
1252fcaf7f86SDimitry Andric         // If Sym is a comparison expression (except <=>),
1253fcaf7f86SDimitry Andric         // find any other comparisons with the same operands.
1254fcaf7f86SDimitry Andric         // See function description.
1255fcaf7f86SDimitry Andric         getRangeForComparisonSymbol(SSE),
1256fe6060f1SDimitry Andric         // If Sym is (dis)equality, we might have some information
1257fe6060f1SDimitry Andric         // on that in our equality classes data structure.
1258fcaf7f86SDimitry Andric         getRangeForEqualities(SSE),
1259fe6060f1SDimitry Andric         // And we should always check what we can get from the operands.
1260fcaf7f86SDimitry Andric         VisitBinaryOperator(SSE));
12615ffd83dbSDimitry Andric   }
12625ffd83dbSDimitry Andric 
12635ffd83dbSDimitry Andric private:
1264fe6060f1SDimitry Andric   SymbolicRangeInferrer(RangeSet::Factory &F, ProgramStateRef S)
1265fe6060f1SDimitry Andric       : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
12665ffd83dbSDimitry Andric 
12675ffd83dbSDimitry Andric   /// Infer range information from the given integer constant.
12685ffd83dbSDimitry Andric   ///
12695ffd83dbSDimitry Andric   /// It's not a real "inference", but is here for operating with
12705ffd83dbSDimitry Andric   /// sub-expressions in a more polymorphic manner.
12715ffd83dbSDimitry Andric   RangeSet inferAs(const llvm::APSInt &Val, QualType) {
12725ffd83dbSDimitry Andric     return {RangeFactory, Val};
12735ffd83dbSDimitry Andric   }
12745ffd83dbSDimitry Andric 
12755ffd83dbSDimitry Andric   /// Infer range information from symbol in the context of the given type.
12765ffd83dbSDimitry Andric   RangeSet inferAs(SymbolRef Sym, QualType DestType) {
12775ffd83dbSDimitry Andric     QualType ActualType = Sym->getType();
12785ffd83dbSDimitry Andric     // Check that we can reason about the symbol at all.
12795ffd83dbSDimitry Andric     if (ActualType->isIntegralOrEnumerationType() ||
12805ffd83dbSDimitry Andric         Loc::isLocType(ActualType)) {
12815ffd83dbSDimitry Andric       return infer(Sym);
12825ffd83dbSDimitry Andric     }
12835ffd83dbSDimitry Andric     // Otherwise, let's simply infer from the destination type.
12845ffd83dbSDimitry Andric     // We couldn't figure out nothing else about that expression.
12855ffd83dbSDimitry Andric     return infer(DestType);
12865ffd83dbSDimitry Andric   }
12875ffd83dbSDimitry Andric 
12885ffd83dbSDimitry Andric   RangeSet infer(SymbolRef Sym) {
1289fcaf7f86SDimitry Andric     return intersect(RangeFactory,
1290fcaf7f86SDimitry Andric                      // Of course, we should take the constraint directly
1291fcaf7f86SDimitry Andric                      // associated with this symbol into consideration.
1292fe6060f1SDimitry Andric                      getConstraint(State, Sym),
1293fcaf7f86SDimitry Andric                      // Apart from the Sym itself, we can infer quite a lot if
1294fcaf7f86SDimitry Andric                      // we look into subexpressions of Sym.
1295fe6060f1SDimitry Andric                      Visit(Sym));
12965ffd83dbSDimitry Andric   }
12975ffd83dbSDimitry Andric 
1298e8d8bef9SDimitry Andric   RangeSet infer(EquivalenceClass Class) {
1299e8d8bef9SDimitry Andric     if (const RangeSet *AssociatedConstraint = getConstraint(State, Class))
1300e8d8bef9SDimitry Andric       return *AssociatedConstraint;
1301e8d8bef9SDimitry Andric 
1302e8d8bef9SDimitry Andric     return infer(Class.getType());
1303e8d8bef9SDimitry Andric   }
1304e8d8bef9SDimitry Andric 
13055ffd83dbSDimitry Andric   /// Infer range information solely from the type.
13065ffd83dbSDimitry Andric   RangeSet infer(QualType T) {
13075ffd83dbSDimitry Andric     // Lazily generate a new RangeSet representing all possible values for the
13085ffd83dbSDimitry Andric     // given symbol type.
13095ffd83dbSDimitry Andric     RangeSet Result(RangeFactory, ValueFactory.getMinValue(T),
13105ffd83dbSDimitry Andric                     ValueFactory.getMaxValue(T));
13115ffd83dbSDimitry Andric 
13125ffd83dbSDimitry Andric     // References are known to be non-zero.
13135ffd83dbSDimitry Andric     if (T->isReferenceType())
13145ffd83dbSDimitry Andric       return assumeNonZero(Result, T);
13155ffd83dbSDimitry Andric 
13165ffd83dbSDimitry Andric     return Result;
13175ffd83dbSDimitry Andric   }
13185ffd83dbSDimitry Andric 
13195ffd83dbSDimitry Andric   template <class BinarySymExprTy>
13205ffd83dbSDimitry Andric   RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
13215ffd83dbSDimitry Andric     // TODO #1: VisitBinaryOperator implementation might not make a good
13225ffd83dbSDimitry Andric     // use of the inferred ranges.  In this case, we might be calculating
13235ffd83dbSDimitry Andric     // everything for nothing.  This being said, we should introduce some
13245ffd83dbSDimitry Andric     // sort of laziness mechanism here.
13255ffd83dbSDimitry Andric     //
13265ffd83dbSDimitry Andric     // TODO #2: We didn't go into the nested expressions before, so it
13275ffd83dbSDimitry Andric     // might cause us spending much more time doing the inference.
13285ffd83dbSDimitry Andric     // This can be a problem for deeply nested expressions that are
13295ffd83dbSDimitry Andric     // involved in conditions and get tested continuously.  We definitely
13305ffd83dbSDimitry Andric     // need to address this issue and introduce some sort of caching
13315ffd83dbSDimitry Andric     // in here.
13325ffd83dbSDimitry Andric     QualType ResultType = Sym->getType();
13335ffd83dbSDimitry Andric     return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
13345ffd83dbSDimitry Andric                                Sym->getOpcode(),
13355ffd83dbSDimitry Andric                                inferAs(Sym->getRHS(), ResultType), ResultType);
13365ffd83dbSDimitry Andric   }
13375ffd83dbSDimitry Andric 
13385ffd83dbSDimitry Andric   RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op,
1339bdd1243dSDimitry Andric                                RangeSet RHS, QualType T);
13405ffd83dbSDimitry Andric 
13415ffd83dbSDimitry Andric   //===----------------------------------------------------------------------===//
13425ffd83dbSDimitry Andric   //                         Ranges and operators
13435ffd83dbSDimitry Andric   //===----------------------------------------------------------------------===//
13445ffd83dbSDimitry Andric 
13455ffd83dbSDimitry Andric   /// Return a rough approximation of the given range set.
13465ffd83dbSDimitry Andric   ///
13475ffd83dbSDimitry Andric   /// For the range set:
13485ffd83dbSDimitry Andric   ///   { [x_0, y_0], [x_1, y_1], ... , [x_N, y_N] }
13495ffd83dbSDimitry Andric   /// it will return the range [x_0, y_N].
13505ffd83dbSDimitry Andric   static Range fillGaps(RangeSet Origin) {
13515ffd83dbSDimitry Andric     assert(!Origin.isEmpty());
13525ffd83dbSDimitry Andric     return {Origin.getMinValue(), Origin.getMaxValue()};
13535ffd83dbSDimitry Andric   }
13545ffd83dbSDimitry Andric 
13555ffd83dbSDimitry Andric   /// Try to convert given range into the given type.
13565ffd83dbSDimitry Andric   ///
1357bdd1243dSDimitry Andric   /// It will return std::nullopt only when the trivial conversion is possible.
1358bdd1243dSDimitry Andric   std::optional<Range> convert(const Range &Origin, APSIntType To) {
13595ffd83dbSDimitry Andric     if (To.testInRange(Origin.From(), false) != APSIntType::RTR_Within ||
13605ffd83dbSDimitry Andric         To.testInRange(Origin.To(), false) != APSIntType::RTR_Within) {
1361bdd1243dSDimitry Andric       return std::nullopt;
13625ffd83dbSDimitry Andric     }
13635ffd83dbSDimitry Andric     return Range(ValueFactory.Convert(To, Origin.From()),
13645ffd83dbSDimitry Andric                  ValueFactory.Convert(To, Origin.To()));
13655ffd83dbSDimitry Andric   }
13665ffd83dbSDimitry Andric 
13675ffd83dbSDimitry Andric   template <BinaryOperator::Opcode Op>
13685ffd83dbSDimitry Andric   RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1369bdd1243dSDimitry Andric     assert(!LHS.isEmpty() && !RHS.isEmpty());
13705ffd83dbSDimitry Andric 
13715ffd83dbSDimitry Andric     Range CoarseLHS = fillGaps(LHS);
13725ffd83dbSDimitry Andric     Range CoarseRHS = fillGaps(RHS);
13735ffd83dbSDimitry Andric 
13745ffd83dbSDimitry Andric     APSIntType ResultType = ValueFactory.getAPSIntType(T);
13755ffd83dbSDimitry Andric 
13765ffd83dbSDimitry Andric     // We need to convert ranges to the resulting type, so we can compare values
13775ffd83dbSDimitry Andric     // and combine them in a meaningful (in terms of the given operation) way.
13785ffd83dbSDimitry Andric     auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
13795ffd83dbSDimitry Andric     auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
13805ffd83dbSDimitry Andric 
13815ffd83dbSDimitry Andric     // It is hard to reason about ranges when conversion changes
13825ffd83dbSDimitry Andric     // borders of the ranges.
13835ffd83dbSDimitry Andric     if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
13845ffd83dbSDimitry Andric       return infer(T);
13855ffd83dbSDimitry Andric     }
13865ffd83dbSDimitry Andric 
13875ffd83dbSDimitry Andric     return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
13885ffd83dbSDimitry Andric   }
13895ffd83dbSDimitry Andric 
13905ffd83dbSDimitry Andric   template <BinaryOperator::Opcode Op>
13915ffd83dbSDimitry Andric   RangeSet VisitBinaryOperator(Range LHS, Range RHS, QualType T) {
13925ffd83dbSDimitry Andric     return infer(T);
13935ffd83dbSDimitry Andric   }
13945ffd83dbSDimitry Andric 
13955ffd83dbSDimitry Andric   /// Return a symmetrical range for the given range and type.
13965ffd83dbSDimitry Andric   ///
13975ffd83dbSDimitry Andric   /// If T is signed, return the smallest range [-x..x] that covers the original
13985ffd83dbSDimitry Andric   /// range, or [-min(T), max(T)] if the aforementioned symmetric range doesn't
13995ffd83dbSDimitry Andric   /// exist due to original range covering min(T)).
14005ffd83dbSDimitry Andric   ///
14015ffd83dbSDimitry Andric   /// If T is unsigned, return the smallest range [0..x] that covers the
14025ffd83dbSDimitry Andric   /// original range.
14035ffd83dbSDimitry Andric   Range getSymmetricalRange(Range Origin, QualType T) {
14045ffd83dbSDimitry Andric     APSIntType RangeType = ValueFactory.getAPSIntType(T);
14055ffd83dbSDimitry Andric 
14065ffd83dbSDimitry Andric     if (RangeType.isUnsigned()) {
14075ffd83dbSDimitry Andric       return Range(ValueFactory.getMinValue(RangeType), Origin.To());
14085ffd83dbSDimitry Andric     }
14095ffd83dbSDimitry Andric 
14105ffd83dbSDimitry Andric     if (Origin.From().isMinSignedValue()) {
14115ffd83dbSDimitry Andric       // If mini is a minimal signed value, absolute value of it is greater
14125ffd83dbSDimitry Andric       // than the maximal signed value.  In order to avoid these
14135ffd83dbSDimitry Andric       // complications, we simply return the whole range.
14145ffd83dbSDimitry Andric       return {ValueFactory.getMinValue(RangeType),
14155ffd83dbSDimitry Andric               ValueFactory.getMaxValue(RangeType)};
14165ffd83dbSDimitry Andric     }
14175ffd83dbSDimitry Andric 
14185ffd83dbSDimitry Andric     // At this point, we are sure that the type is signed and we can safely
14195ffd83dbSDimitry Andric     // use unary - operator.
14205ffd83dbSDimitry Andric     //
14215ffd83dbSDimitry Andric     // While calculating absolute maximum, we can use the following formula
14225ffd83dbSDimitry Andric     // because of these reasons:
14235ffd83dbSDimitry Andric     //   * If From >= 0 then To >= From and To >= -From.
14245ffd83dbSDimitry Andric     //     AbsMax == To == max(To, -From)
14255ffd83dbSDimitry Andric     //   * If To <= 0 then -From >= -To and -From >= From.
14265ffd83dbSDimitry Andric     //     AbsMax == -From == max(-From, To)
14275ffd83dbSDimitry Andric     //   * Otherwise, From <= 0, To >= 0, and
14285ffd83dbSDimitry Andric     //     AbsMax == max(abs(From), abs(To))
14295ffd83dbSDimitry Andric     llvm::APSInt AbsMax = std::max(-Origin.From(), Origin.To());
14305ffd83dbSDimitry Andric 
14315ffd83dbSDimitry Andric     // Intersection is guaranteed to be non-empty.
14325ffd83dbSDimitry Andric     return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
14335ffd83dbSDimitry Andric   }
14345ffd83dbSDimitry Andric 
14355ffd83dbSDimitry Andric   /// Return a range set subtracting zero from \p Domain.
14365ffd83dbSDimitry Andric   RangeSet assumeNonZero(RangeSet Domain, QualType T) {
14375ffd83dbSDimitry Andric     APSIntType IntType = ValueFactory.getAPSIntType(T);
1438fe6060f1SDimitry Andric     return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
14395ffd83dbSDimitry Andric   }
14405ffd83dbSDimitry Andric 
1441fcaf7f86SDimitry Andric   template <typename ProduceNegatedSymFunc>
1442bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1443fcaf7f86SDimitry Andric                                                  QualType T) {
144481ad6265SDimitry Andric     // Do not negate if the type cannot be meaningfully negated.
1445fcaf7f86SDimitry Andric     if (!T->isUnsignedIntegerOrEnumerationType() &&
1446fcaf7f86SDimitry Andric         !T->isSignedIntegerOrEnumerationType())
1447bdd1243dSDimitry Andric       return std::nullopt;
1448e8d8bef9SDimitry Andric 
1449fcaf7f86SDimitry Andric     if (SymbolRef NegatedSym = F())
1450fcaf7f86SDimitry Andric       if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1451fcaf7f86SDimitry Andric         return RangeFactory.negate(*NegatedRange);
1452fcaf7f86SDimitry Andric 
1453bdd1243dSDimitry Andric     return std::nullopt;
1454fcaf7f86SDimitry Andric   }
1455fcaf7f86SDimitry Andric 
1456bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForNegatedUnarySym(const UnarySymExpr *USE) {
145781ad6265SDimitry Andric     // Just get the operand when we negate a symbol that is already negated.
145881ad6265SDimitry Andric     // -(-a) == a
1459fcaf7f86SDimitry Andric     return getRangeForNegatedExpr(
1460fcaf7f86SDimitry Andric         [USE]() -> SymbolRef {
1461fcaf7f86SDimitry Andric           if (USE->getOpcode() == UO_Minus)
1462fcaf7f86SDimitry Andric             return USE->getOperand();
1463fcaf7f86SDimitry Andric           return nullptr;
1464fcaf7f86SDimitry Andric         },
1465fcaf7f86SDimitry Andric         USE->getType());
146681ad6265SDimitry Andric   }
14675ffd83dbSDimitry Andric 
1468bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForNegatedSymSym(const SymSymExpr *SSE) {
1469fcaf7f86SDimitry Andric     return getRangeForNegatedExpr(
1470fcaf7f86SDimitry Andric         [SSE, State = this->State]() -> SymbolRef {
1471fcaf7f86SDimitry Andric           if (SSE->getOpcode() == BO_Sub)
1472fcaf7f86SDimitry Andric             return State->getSymbolManager().getSymSymExpr(
1473fcaf7f86SDimitry Andric                 SSE->getRHS(), BO_Sub, SSE->getLHS(), SSE->getType());
1474fcaf7f86SDimitry Andric           return nullptr;
1475fcaf7f86SDimitry Andric         },
1476fcaf7f86SDimitry Andric         SSE->getType());
1477fcaf7f86SDimitry Andric   }
1478fcaf7f86SDimitry Andric 
1479bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForNegatedSym(SymbolRef Sym) {
1480fcaf7f86SDimitry Andric     return getRangeForNegatedExpr(
1481fcaf7f86SDimitry Andric         [Sym, State = this->State]() {
1482fcaf7f86SDimitry Andric           return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus,
1483fcaf7f86SDimitry Andric                                                            Sym->getType());
1484fcaf7f86SDimitry Andric         },
1485fcaf7f86SDimitry Andric         Sym->getType());
14865ffd83dbSDimitry Andric   }
14875ffd83dbSDimitry Andric 
14885ffd83dbSDimitry Andric   // Returns ranges only for binary comparison operators (except <=>)
14895ffd83dbSDimitry Andric   // when left and right operands are symbolic values.
14905ffd83dbSDimitry Andric   // Finds any other comparisons with the same operands.
14915ffd83dbSDimitry Andric   // Then do logical calculations and refuse impossible branches.
14925ffd83dbSDimitry Andric   // E.g. (x < y) and (x > y) at the same time are impossible.
14935ffd83dbSDimitry Andric   // E.g. (x >= y) and (x != y) at the same time makes (x > y) true only.
14945ffd83dbSDimitry Andric   // E.g. (x == y) and (y == x) are just reversed but the same.
14955ffd83dbSDimitry Andric   // It covers all possible combinations (see CmpOpTable description).
14965ffd83dbSDimitry Andric   // Note that `x` and `y` can also stand for subexpressions,
14975ffd83dbSDimitry Andric   // not only for actual symbols.
1498bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForComparisonSymbol(const SymSymExpr *SSE) {
1499349cc55cSDimitry Andric     const BinaryOperatorKind CurrentOP = SSE->getOpcode();
15005ffd83dbSDimitry Andric 
15015ffd83dbSDimitry Andric     // We currently do not support <=> (C++20).
15025ffd83dbSDimitry Andric     if (!BinaryOperator::isComparisonOp(CurrentOP) || (CurrentOP == BO_Cmp))
1503bdd1243dSDimitry Andric       return std::nullopt;
15045ffd83dbSDimitry Andric 
15055ffd83dbSDimitry Andric     static const OperatorRelationsTable CmpOpTable{};
15065ffd83dbSDimitry Andric 
15075ffd83dbSDimitry Andric     const SymExpr *LHS = SSE->getLHS();
15085ffd83dbSDimitry Andric     const SymExpr *RHS = SSE->getRHS();
15095ffd83dbSDimitry Andric     QualType T = SSE->getType();
15105ffd83dbSDimitry Andric 
15115ffd83dbSDimitry Andric     SymbolManager &SymMgr = State->getSymbolManager();
15125ffd83dbSDimitry Andric 
1513349cc55cSDimitry Andric     // We use this variable to store the last queried operator (`QueriedOP`)
1514349cc55cSDimitry Andric     // for which the `getCmpOpState` returned with `Unknown`. If there are two
1515349cc55cSDimitry Andric     // different OPs that returned `Unknown` then we have to query the special
1516349cc55cSDimitry Andric     // `UnknownX2` column. We assume that `getCmpOpState(CurrentOP, CurrentOP)`
1517349cc55cSDimitry Andric     // never returns `Unknown`, so `CurrentOP` is a good initial value.
1518349cc55cSDimitry Andric     BinaryOperatorKind LastQueriedOpToUnknown = CurrentOP;
15195ffd83dbSDimitry Andric 
15205ffd83dbSDimitry Andric     // Loop goes through all of the columns exept the last one ('UnknownX2').
15215ffd83dbSDimitry Andric     // We treat `UnknownX2` column separately at the end of the loop body.
15225ffd83dbSDimitry Andric     for (size_t i = 0; i < CmpOpTable.getCmpOpCount(); ++i) {
15235ffd83dbSDimitry Andric 
15245ffd83dbSDimitry Andric       // Let's find an expression e.g. (x < y).
15255ffd83dbSDimitry Andric       BinaryOperatorKind QueriedOP = OperatorRelationsTable::getOpFromIndex(i);
15265ffd83dbSDimitry Andric       const SymSymExpr *SymSym = SymMgr.getSymSymExpr(LHS, QueriedOP, RHS, T);
1527e8d8bef9SDimitry Andric       const RangeSet *QueriedRangeSet = getConstraint(State, SymSym);
15285ffd83dbSDimitry Andric 
15295ffd83dbSDimitry Andric       // If ranges were not previously found,
15305ffd83dbSDimitry Andric       // try to find a reversed expression (y > x).
15315ffd83dbSDimitry Andric       if (!QueriedRangeSet) {
15325ffd83dbSDimitry Andric         const BinaryOperatorKind ROP =
15335ffd83dbSDimitry Andric             BinaryOperator::reverseComparisonOp(QueriedOP);
15345ffd83dbSDimitry Andric         SymSym = SymMgr.getSymSymExpr(RHS, ROP, LHS, T);
1535e8d8bef9SDimitry Andric         QueriedRangeSet = getConstraint(State, SymSym);
15365ffd83dbSDimitry Andric       }
15375ffd83dbSDimitry Andric 
15385ffd83dbSDimitry Andric       if (!QueriedRangeSet || QueriedRangeSet->isEmpty())
15395ffd83dbSDimitry Andric         continue;
15405ffd83dbSDimitry Andric 
15415ffd83dbSDimitry Andric       const llvm::APSInt *ConcreteValue = QueriedRangeSet->getConcreteValue();
15425ffd83dbSDimitry Andric       const bool isInFalseBranch =
15435ffd83dbSDimitry Andric           ConcreteValue ? (*ConcreteValue == 0) : false;
15445ffd83dbSDimitry Andric 
15455ffd83dbSDimitry Andric       // If it is a false branch, we shall be guided by opposite operator,
15465ffd83dbSDimitry Andric       // because the table is made assuming we are in the true branch.
15475ffd83dbSDimitry Andric       // E.g. when (x <= y) is false, then (x > y) is true.
15485ffd83dbSDimitry Andric       if (isInFalseBranch)
15495ffd83dbSDimitry Andric         QueriedOP = BinaryOperator::negateComparisonOp(QueriedOP);
15505ffd83dbSDimitry Andric 
15515ffd83dbSDimitry Andric       OperatorRelationsTable::TriStateKind BranchState =
15525ffd83dbSDimitry Andric           CmpOpTable.getCmpOpState(CurrentOP, QueriedOP);
15535ffd83dbSDimitry Andric 
15545ffd83dbSDimitry Andric       if (BranchState == OperatorRelationsTable::Unknown) {
1555349cc55cSDimitry Andric         if (LastQueriedOpToUnknown != CurrentOP &&
1556349cc55cSDimitry Andric             LastQueriedOpToUnknown != QueriedOP) {
1557349cc55cSDimitry Andric           // If we got the Unknown state for both different operators.
15585ffd83dbSDimitry Andric           // if (x <= y)    // assume true
15595ffd83dbSDimitry Andric           //   if (x != y)  // assume true
15605ffd83dbSDimitry Andric           //     if (x < y) // would be also true
15615ffd83dbSDimitry Andric           // Get a state from `UnknownX2` column.
15625ffd83dbSDimitry Andric           BranchState = CmpOpTable.getCmpOpStateForUnknownX2(CurrentOP);
1563349cc55cSDimitry Andric         } else {
1564349cc55cSDimitry Andric           LastQueriedOpToUnknown = QueriedOP;
15655ffd83dbSDimitry Andric           continue;
15665ffd83dbSDimitry Andric         }
1567349cc55cSDimitry Andric       }
15685ffd83dbSDimitry Andric 
1569e8d8bef9SDimitry Andric       return (BranchState == OperatorRelationsTable::True) ? getTrueRange(T)
1570e8d8bef9SDimitry Andric                                                            : getFalseRange(T);
15715ffd83dbSDimitry Andric     }
15725ffd83dbSDimitry Andric 
1573bdd1243dSDimitry Andric     return std::nullopt;
1574e8d8bef9SDimitry Andric   }
1575e8d8bef9SDimitry Andric 
1576bdd1243dSDimitry Andric   std::optional<RangeSet> getRangeForEqualities(const SymSymExpr *Sym) {
1577bdd1243dSDimitry Andric     std::optional<bool> Equality = meansEquality(Sym);
1578e8d8bef9SDimitry Andric 
1579e8d8bef9SDimitry Andric     if (!Equality)
1580bdd1243dSDimitry Andric       return std::nullopt;
1581e8d8bef9SDimitry Andric 
1582bdd1243dSDimitry Andric     if (std::optional<bool> AreEqual =
1583fe6060f1SDimitry Andric             EquivalenceClass::areEqual(State, Sym->getLHS(), Sym->getRHS())) {
1584fe6060f1SDimitry Andric       // Here we cover two cases at once:
1585fe6060f1SDimitry Andric       //   * if Sym is equality and its operands are known to be equal -> true
1586fe6060f1SDimitry Andric       //   * if Sym is disequality and its operands are disequal -> true
1587fe6060f1SDimitry Andric       if (*AreEqual == *Equality) {
1588e8d8bef9SDimitry Andric         return getTrueRange(Sym->getType());
1589e8d8bef9SDimitry Andric       }
1590fe6060f1SDimitry Andric       // Opposite combinations result in false.
1591e8d8bef9SDimitry Andric       return getFalseRange(Sym->getType());
1592e8d8bef9SDimitry Andric     }
1593e8d8bef9SDimitry Andric 
1594bdd1243dSDimitry Andric     return std::nullopt;
1595e8d8bef9SDimitry Andric   }
1596e8d8bef9SDimitry Andric 
1597e8d8bef9SDimitry Andric   RangeSet getTrueRange(QualType T) {
1598e8d8bef9SDimitry Andric     RangeSet TypeRange = infer(T);
1599e8d8bef9SDimitry Andric     return assumeNonZero(TypeRange, T);
1600e8d8bef9SDimitry Andric   }
1601e8d8bef9SDimitry Andric 
1602e8d8bef9SDimitry Andric   RangeSet getFalseRange(QualType T) {
1603e8d8bef9SDimitry Andric     const llvm::APSInt &Zero = ValueFactory.getValue(0, T);
1604e8d8bef9SDimitry Andric     return RangeSet(RangeFactory, Zero);
16055ffd83dbSDimitry Andric   }
16065ffd83dbSDimitry Andric 
16075ffd83dbSDimitry Andric   BasicValueFactory &ValueFactory;
16085ffd83dbSDimitry Andric   RangeSet::Factory &RangeFactory;
16095ffd83dbSDimitry Andric   ProgramStateRef State;
16105ffd83dbSDimitry Andric };
16115ffd83dbSDimitry Andric 
1612e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1613e8d8bef9SDimitry Andric //               Range-based reasoning about symbolic operations
1614e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1615e8d8bef9SDimitry Andric 
16165ffd83dbSDimitry Andric template <>
1617bdd1243dSDimitry Andric RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_NE>(RangeSet LHS,
1618bdd1243dSDimitry Andric                                                            RangeSet RHS,
1619bdd1243dSDimitry Andric                                                            QualType T) {
1620bdd1243dSDimitry Andric   assert(!LHS.isEmpty() && !RHS.isEmpty());
1621bdd1243dSDimitry Andric 
1622bdd1243dSDimitry Andric   if (LHS.getAPSIntType() == RHS.getAPSIntType()) {
1623bdd1243dSDimitry Andric     if (intersect(RangeFactory, LHS, RHS).isEmpty())
1624bdd1243dSDimitry Andric       return getTrueRange(T);
1625bdd1243dSDimitry Andric 
1626bdd1243dSDimitry Andric   } else {
1627bdd1243dSDimitry Andric     // We can only lose information if we are casting smaller signed type to
1628bdd1243dSDimitry Andric     // bigger unsigned type. For e.g.,
1629bdd1243dSDimitry Andric     //    LHS (unsigned short): [2, USHRT_MAX]
1630bdd1243dSDimitry Andric     //    RHS   (signed short): [SHRT_MIN, 0]
1631bdd1243dSDimitry Andric     //
1632bdd1243dSDimitry Andric     // Casting RHS to LHS type will leave us with overlapping values
1633bdd1243dSDimitry Andric     //    CastedRHS : [0, 0] U [SHRT_MAX + 1, USHRT_MAX]
1634bdd1243dSDimitry Andric     //
1635bdd1243dSDimitry Andric     // We can avoid this by checking if signed type's maximum value is lesser
1636bdd1243dSDimitry Andric     // than unsigned type's minimum value.
1637bdd1243dSDimitry Andric 
1638bdd1243dSDimitry Andric     // If both have different signs then only we can get more information.
1639bdd1243dSDimitry Andric     if (LHS.isUnsigned() != RHS.isUnsigned()) {
1640bdd1243dSDimitry Andric       if (LHS.isUnsigned() && (LHS.getBitWidth() >= RHS.getBitWidth())) {
1641bdd1243dSDimitry Andric         if (RHS.getMaxValue().isNegative() ||
1642bdd1243dSDimitry Andric             LHS.getAPSIntType().convert(RHS.getMaxValue()) < LHS.getMinValue())
1643bdd1243dSDimitry Andric           return getTrueRange(T);
1644bdd1243dSDimitry Andric 
1645bdd1243dSDimitry Andric       } else if (RHS.isUnsigned() && (LHS.getBitWidth() <= RHS.getBitWidth())) {
1646bdd1243dSDimitry Andric         if (LHS.getMaxValue().isNegative() ||
1647bdd1243dSDimitry Andric             RHS.getAPSIntType().convert(LHS.getMaxValue()) < RHS.getMinValue())
1648bdd1243dSDimitry Andric           return getTrueRange(T);
1649bdd1243dSDimitry Andric       }
1650bdd1243dSDimitry Andric     }
1651bdd1243dSDimitry Andric 
1652bdd1243dSDimitry Andric     // Both RangeSets should be casted to bigger unsigned type.
1653bdd1243dSDimitry Andric     APSIntType CastingType(std::max(LHS.getBitWidth(), RHS.getBitWidth()),
1654bdd1243dSDimitry Andric                            LHS.isUnsigned() || RHS.isUnsigned());
1655bdd1243dSDimitry Andric 
1656bdd1243dSDimitry Andric     RangeSet CastedLHS = RangeFactory.castTo(LHS, CastingType);
1657bdd1243dSDimitry Andric     RangeSet CastedRHS = RangeFactory.castTo(RHS, CastingType);
1658bdd1243dSDimitry Andric 
1659bdd1243dSDimitry Andric     if (intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1660bdd1243dSDimitry Andric       return getTrueRange(T);
1661bdd1243dSDimitry Andric   }
1662bdd1243dSDimitry Andric 
1663bdd1243dSDimitry Andric   // In all other cases, the resulting range cannot be deduced.
1664bdd1243dSDimitry Andric   return infer(T);
1665bdd1243dSDimitry Andric }
1666bdd1243dSDimitry Andric 
1667bdd1243dSDimitry Andric template <>
16685ffd83dbSDimitry Andric RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS,
16695ffd83dbSDimitry Andric                                                            QualType T) {
16705ffd83dbSDimitry Andric   APSIntType ResultType = ValueFactory.getAPSIntType(T);
16715ffd83dbSDimitry Andric   llvm::APSInt Zero = ResultType.getZeroValue();
16725ffd83dbSDimitry Andric 
16735ffd83dbSDimitry Andric   bool IsLHSPositiveOrZero = LHS.From() >= Zero;
16745ffd83dbSDimitry Andric   bool IsRHSPositiveOrZero = RHS.From() >= Zero;
16755ffd83dbSDimitry Andric 
16765ffd83dbSDimitry Andric   bool IsLHSNegative = LHS.To() < Zero;
16775ffd83dbSDimitry Andric   bool IsRHSNegative = RHS.To() < Zero;
16785ffd83dbSDimitry Andric 
16795ffd83dbSDimitry Andric   // Check if both ranges have the same sign.
16805ffd83dbSDimitry Andric   if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
16815ffd83dbSDimitry Andric       (IsLHSNegative && IsRHSNegative)) {
16825ffd83dbSDimitry Andric     // The result is definitely greater or equal than any of the operands.
16835ffd83dbSDimitry Andric     const llvm::APSInt &Min = std::max(LHS.From(), RHS.From());
16845ffd83dbSDimitry Andric 
16855ffd83dbSDimitry Andric     // We estimate maximal value for positives as the maximal value for the
16865ffd83dbSDimitry Andric     // given type.  For negatives, we estimate it with -1 (e.g. 0x11111111).
16875ffd83dbSDimitry Andric     //
16885ffd83dbSDimitry Andric     // TODO: We basically, limit the resulting range from below, but don't do
16895ffd83dbSDimitry Andric     //       anything with the upper bound.
16905ffd83dbSDimitry Andric     //
16915ffd83dbSDimitry Andric     //       For positive operands, it can be done as follows: for the upper
16925ffd83dbSDimitry Andric     //       bound of LHS and RHS we calculate the most significant bit set.
16935ffd83dbSDimitry Andric     //       Let's call it the N-th bit.  Then we can estimate the maximal
16945ffd83dbSDimitry Andric     //       number to be 2^(N+1)-1, i.e. the number with all the bits up to
16955ffd83dbSDimitry Andric     //       the N-th bit set.
16965ffd83dbSDimitry Andric     const llvm::APSInt &Max = IsLHSNegative
16975ffd83dbSDimitry Andric                                   ? ValueFactory.getValue(--Zero)
16985ffd83dbSDimitry Andric                                   : ValueFactory.getMaxValue(ResultType);
16995ffd83dbSDimitry Andric 
17005ffd83dbSDimitry Andric     return {RangeFactory, ValueFactory.getValue(Min), Max};
17015ffd83dbSDimitry Andric   }
17025ffd83dbSDimitry Andric 
17035ffd83dbSDimitry Andric   // Otherwise, let's check if at least one of the operands is negative.
17045ffd83dbSDimitry Andric   if (IsLHSNegative || IsRHSNegative) {
17055ffd83dbSDimitry Andric     // This means that the result is definitely negative as well.
17065ffd83dbSDimitry Andric     return {RangeFactory, ValueFactory.getMinValue(ResultType),
17075ffd83dbSDimitry Andric             ValueFactory.getValue(--Zero)};
17085ffd83dbSDimitry Andric   }
17095ffd83dbSDimitry Andric 
17105ffd83dbSDimitry Andric   RangeSet DefaultRange = infer(T);
17115ffd83dbSDimitry Andric 
17125ffd83dbSDimitry Andric   // It is pretty hard to reason about operands with different signs
17135ffd83dbSDimitry Andric   // (and especially with possibly different signs).  We simply check if it
17145ffd83dbSDimitry Andric   // can be zero.  In order to conclude that the result could not be zero,
17155ffd83dbSDimitry Andric   // at least one of the operands should be definitely not zero itself.
17165ffd83dbSDimitry Andric   if (!LHS.Includes(Zero) || !RHS.Includes(Zero)) {
17175ffd83dbSDimitry Andric     return assumeNonZero(DefaultRange, T);
17185ffd83dbSDimitry Andric   }
17195ffd83dbSDimitry Andric 
17205ffd83dbSDimitry Andric   // Nothing much else to do here.
17215ffd83dbSDimitry Andric   return DefaultRange;
17225ffd83dbSDimitry Andric }
17235ffd83dbSDimitry Andric 
17245ffd83dbSDimitry Andric template <>
17255ffd83dbSDimitry Andric RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(Range LHS,
17265ffd83dbSDimitry Andric                                                             Range RHS,
17275ffd83dbSDimitry Andric                                                             QualType T) {
17285ffd83dbSDimitry Andric   APSIntType ResultType = ValueFactory.getAPSIntType(T);
17295ffd83dbSDimitry Andric   llvm::APSInt Zero = ResultType.getZeroValue();
17305ffd83dbSDimitry Andric 
17315ffd83dbSDimitry Andric   bool IsLHSPositiveOrZero = LHS.From() >= Zero;
17325ffd83dbSDimitry Andric   bool IsRHSPositiveOrZero = RHS.From() >= Zero;
17335ffd83dbSDimitry Andric 
17345ffd83dbSDimitry Andric   bool IsLHSNegative = LHS.To() < Zero;
17355ffd83dbSDimitry Andric   bool IsRHSNegative = RHS.To() < Zero;
17365ffd83dbSDimitry Andric 
17375ffd83dbSDimitry Andric   // Check if both ranges have the same sign.
17385ffd83dbSDimitry Andric   if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
17395ffd83dbSDimitry Andric       (IsLHSNegative && IsRHSNegative)) {
17405ffd83dbSDimitry Andric     // The result is definitely less or equal than any of the operands.
17415ffd83dbSDimitry Andric     const llvm::APSInt &Max = std::min(LHS.To(), RHS.To());
17425ffd83dbSDimitry Andric 
17435ffd83dbSDimitry Andric     // We conservatively estimate lower bound to be the smallest positive
17445ffd83dbSDimitry Andric     // or negative value corresponding to the sign of the operands.
17455ffd83dbSDimitry Andric     const llvm::APSInt &Min = IsLHSNegative
17465ffd83dbSDimitry Andric                                   ? ValueFactory.getMinValue(ResultType)
17475ffd83dbSDimitry Andric                                   : ValueFactory.getValue(Zero);
17485ffd83dbSDimitry Andric 
17495ffd83dbSDimitry Andric     return {RangeFactory, Min, Max};
17505ffd83dbSDimitry Andric   }
17515ffd83dbSDimitry Andric 
17525ffd83dbSDimitry Andric   // Otherwise, let's check if at least one of the operands is positive.
17535ffd83dbSDimitry Andric   if (IsLHSPositiveOrZero || IsRHSPositiveOrZero) {
17545ffd83dbSDimitry Andric     // This makes result definitely positive.
17555ffd83dbSDimitry Andric     //
17565ffd83dbSDimitry Andric     // We can also reason about a maximal value by finding the maximal
17575ffd83dbSDimitry Andric     // value of the positive operand.
17585ffd83dbSDimitry Andric     const llvm::APSInt &Max = IsLHSPositiveOrZero ? LHS.To() : RHS.To();
17595ffd83dbSDimitry Andric 
17605ffd83dbSDimitry Andric     // The minimal value on the other hand is much harder to reason about.
17615ffd83dbSDimitry Andric     // The only thing we know for sure is that the result is positive.
17625ffd83dbSDimitry Andric     return {RangeFactory, ValueFactory.getValue(Zero),
17635ffd83dbSDimitry Andric             ValueFactory.getValue(Max)};
17645ffd83dbSDimitry Andric   }
17655ffd83dbSDimitry Andric 
17665ffd83dbSDimitry Andric   // Nothing much else to do here.
17675ffd83dbSDimitry Andric   return infer(T);
17685ffd83dbSDimitry Andric }
17695ffd83dbSDimitry Andric 
17705ffd83dbSDimitry Andric template <>
17715ffd83dbSDimitry Andric RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS,
17725ffd83dbSDimitry Andric                                                             Range RHS,
17735ffd83dbSDimitry Andric                                                             QualType T) {
17745ffd83dbSDimitry Andric   llvm::APSInt Zero = ValueFactory.getAPSIntType(T).getZeroValue();
17755ffd83dbSDimitry Andric 
17765ffd83dbSDimitry Andric   Range ConservativeRange = getSymmetricalRange(RHS, T);
17775ffd83dbSDimitry Andric 
17785ffd83dbSDimitry Andric   llvm::APSInt Max = ConservativeRange.To();
17795ffd83dbSDimitry Andric   llvm::APSInt Min = ConservativeRange.From();
17805ffd83dbSDimitry Andric 
17815ffd83dbSDimitry Andric   if (Max == Zero) {
17825ffd83dbSDimitry Andric     // It's an undefined behaviour to divide by 0 and it seems like we know
17835ffd83dbSDimitry Andric     // for sure that RHS is 0.  Let's say that the resulting range is
17845ffd83dbSDimitry Andric     // simply infeasible for that matter.
17855ffd83dbSDimitry Andric     return RangeFactory.getEmptySet();
17865ffd83dbSDimitry Andric   }
17875ffd83dbSDimitry Andric 
17885ffd83dbSDimitry Andric   // At this point, our conservative range is closed.  The result, however,
17895ffd83dbSDimitry Andric   // couldn't be greater than the RHS' maximal absolute value.  Because of
17905ffd83dbSDimitry Andric   // this reason, we turn the range into open (or half-open in case of
17915ffd83dbSDimitry Andric   // unsigned integers).
17925ffd83dbSDimitry Andric   //
17935ffd83dbSDimitry Andric   // While we operate on integer values, an open interval (a, b) can be easily
17945ffd83dbSDimitry Andric   // represented by the closed interval [a + 1, b - 1].  And this is exactly
17955ffd83dbSDimitry Andric   // what we do next.
17965ffd83dbSDimitry Andric   //
17975ffd83dbSDimitry Andric   // If we are dealing with unsigned case, we shouldn't move the lower bound.
17985ffd83dbSDimitry Andric   if (Min.isSigned()) {
17995ffd83dbSDimitry Andric     ++Min;
18005ffd83dbSDimitry Andric   }
18015ffd83dbSDimitry Andric   --Max;
18025ffd83dbSDimitry Andric 
18035ffd83dbSDimitry Andric   bool IsLHSPositiveOrZero = LHS.From() >= Zero;
18045ffd83dbSDimitry Andric   bool IsRHSPositiveOrZero = RHS.From() >= Zero;
18055ffd83dbSDimitry Andric 
18065ffd83dbSDimitry Andric   // Remainder operator results with negative operands is implementation
18075ffd83dbSDimitry Andric   // defined.  Positive cases are much easier to reason about though.
18085ffd83dbSDimitry Andric   if (IsLHSPositiveOrZero && IsRHSPositiveOrZero) {
18095ffd83dbSDimitry Andric     // If maximal value of LHS is less than maximal value of RHS,
18105ffd83dbSDimitry Andric     // the result won't get greater than LHS.To().
18115ffd83dbSDimitry Andric     Max = std::min(LHS.To(), Max);
18125ffd83dbSDimitry Andric     // We want to check if it is a situation similar to the following:
18135ffd83dbSDimitry Andric     //
18145ffd83dbSDimitry Andric     // <------------|---[  LHS  ]--------[  RHS  ]----->
18155ffd83dbSDimitry Andric     //  -INF        0                              +INF
18165ffd83dbSDimitry Andric     //
18175ffd83dbSDimitry Andric     // In this situation, we can conclude that (LHS / RHS) == 0 and
18185ffd83dbSDimitry Andric     // (LHS % RHS) == LHS.
18195ffd83dbSDimitry Andric     Min = LHS.To() < RHS.From() ? LHS.From() : Zero;
18205ffd83dbSDimitry Andric   }
18215ffd83dbSDimitry Andric 
18225ffd83dbSDimitry Andric   // Nevertheless, the symmetrical range for RHS is a conservative estimate
18235ffd83dbSDimitry Andric   // for any sign of either LHS, or RHS.
18245ffd83dbSDimitry Andric   return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
18255ffd83dbSDimitry Andric }
18265ffd83dbSDimitry Andric 
1827bdd1243dSDimitry Andric RangeSet SymbolicRangeInferrer::VisitBinaryOperator(RangeSet LHS,
1828bdd1243dSDimitry Andric                                                     BinaryOperator::Opcode Op,
1829bdd1243dSDimitry Andric                                                     RangeSet RHS, QualType T) {
1830bdd1243dSDimitry Andric   // We should propagate information about unfeasbility of one of the
1831bdd1243dSDimitry Andric   // operands to the resulting range.
1832bdd1243dSDimitry Andric   if (LHS.isEmpty() || RHS.isEmpty()) {
1833bdd1243dSDimitry Andric     return RangeFactory.getEmptySet();
1834bdd1243dSDimitry Andric   }
1835bdd1243dSDimitry Andric 
1836bdd1243dSDimitry Andric   switch (Op) {
1837bdd1243dSDimitry Andric   case BO_NE:
1838bdd1243dSDimitry Andric     return VisitBinaryOperator<BO_NE>(LHS, RHS, T);
1839bdd1243dSDimitry Andric   case BO_Or:
1840bdd1243dSDimitry Andric     return VisitBinaryOperator<BO_Or>(LHS, RHS, T);
1841bdd1243dSDimitry Andric   case BO_And:
1842bdd1243dSDimitry Andric     return VisitBinaryOperator<BO_And>(LHS, RHS, T);
1843bdd1243dSDimitry Andric   case BO_Rem:
1844bdd1243dSDimitry Andric     return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
1845bdd1243dSDimitry Andric   default:
1846bdd1243dSDimitry Andric     return infer(T);
1847bdd1243dSDimitry Andric   }
1848bdd1243dSDimitry Andric }
1849bdd1243dSDimitry Andric 
1850e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1851349cc55cSDimitry Andric //                  Constraint manager implementation details
1852349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
1853349cc55cSDimitry Andric 
1854349cc55cSDimitry Andric class RangeConstraintManager : public RangedConstraintManager {
1855349cc55cSDimitry Andric public:
1856349cc55cSDimitry Andric   RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB)
1857349cc55cSDimitry Andric       : RangedConstraintManager(EE, SVB), F(getBasicVals()) {}
1858349cc55cSDimitry Andric 
1859349cc55cSDimitry Andric   //===------------------------------------------------------------------===//
1860349cc55cSDimitry Andric   // Implementation for interface from ConstraintManager.
1861349cc55cSDimitry Andric   //===------------------------------------------------------------------===//
1862349cc55cSDimitry Andric 
1863349cc55cSDimitry Andric   bool haveEqualConstraints(ProgramStateRef S1,
1864349cc55cSDimitry Andric                             ProgramStateRef S2) const override {
1865349cc55cSDimitry Andric     // NOTE: ClassMembers are as simple as back pointers for ClassMap,
1866349cc55cSDimitry Andric     //       so comparing constraint ranges and class maps should be
1867349cc55cSDimitry Andric     //       sufficient.
1868349cc55cSDimitry Andric     return S1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1869349cc55cSDimitry Andric            S1->get<ClassMap>() == S2->get<ClassMap>();
1870349cc55cSDimitry Andric   }
1871349cc55cSDimitry Andric 
1872349cc55cSDimitry Andric   bool canReasonAbout(SVal X) const override;
1873349cc55cSDimitry Andric 
1874349cc55cSDimitry Andric   ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
1875349cc55cSDimitry Andric 
1876349cc55cSDimitry Andric   const llvm::APSInt *getSymVal(ProgramStateRef State,
1877349cc55cSDimitry Andric                                 SymbolRef Sym) const override;
1878349cc55cSDimitry Andric 
18795f757f3fSDimitry Andric   const llvm::APSInt *getSymMinVal(ProgramStateRef State,
18805f757f3fSDimitry Andric                                    SymbolRef Sym) const override;
18815f757f3fSDimitry Andric 
18825f757f3fSDimitry Andric   const llvm::APSInt *getSymMaxVal(ProgramStateRef State,
18835f757f3fSDimitry Andric                                    SymbolRef Sym) const override;
18845f757f3fSDimitry Andric 
1885349cc55cSDimitry Andric   ProgramStateRef removeDeadBindings(ProgramStateRef State,
1886349cc55cSDimitry Andric                                      SymbolReaper &SymReaper) override;
1887349cc55cSDimitry Andric 
1888349cc55cSDimitry Andric   void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
1889349cc55cSDimitry Andric                  unsigned int Space = 0, bool IsDot = false) const override;
1890fcaf7f86SDimitry Andric   void printValue(raw_ostream &Out, ProgramStateRef State,
1891fcaf7f86SDimitry Andric                   SymbolRef Sym) override;
1892349cc55cSDimitry Andric   void printConstraints(raw_ostream &Out, ProgramStateRef State,
1893349cc55cSDimitry Andric                         const char *NL = "\n", unsigned int Space = 0,
1894349cc55cSDimitry Andric                         bool IsDot = false) const;
1895349cc55cSDimitry Andric   void printEquivalenceClasses(raw_ostream &Out, ProgramStateRef State,
1896349cc55cSDimitry Andric                                const char *NL = "\n", unsigned int Space = 0,
1897349cc55cSDimitry Andric                                bool IsDot = false) const;
1898349cc55cSDimitry Andric   void printDisequalities(raw_ostream &Out, ProgramStateRef State,
1899349cc55cSDimitry Andric                           const char *NL = "\n", unsigned int Space = 0,
1900349cc55cSDimitry Andric                           bool IsDot = false) const;
1901349cc55cSDimitry Andric 
1902349cc55cSDimitry Andric   //===------------------------------------------------------------------===//
1903349cc55cSDimitry Andric   // Implementation for interface from RangedConstraintManager.
1904349cc55cSDimitry Andric   //===------------------------------------------------------------------===//
1905349cc55cSDimitry Andric 
1906349cc55cSDimitry Andric   ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
1907349cc55cSDimitry Andric                               const llvm::APSInt &V,
1908349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1909349cc55cSDimitry Andric 
1910349cc55cSDimitry Andric   ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
1911349cc55cSDimitry Andric                               const llvm::APSInt &V,
1912349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1913349cc55cSDimitry Andric 
1914349cc55cSDimitry Andric   ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
1915349cc55cSDimitry Andric                               const llvm::APSInt &V,
1916349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1917349cc55cSDimitry Andric 
1918349cc55cSDimitry Andric   ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym,
1919349cc55cSDimitry Andric                               const llvm::APSInt &V,
1920349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1921349cc55cSDimitry Andric 
1922349cc55cSDimitry Andric   ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym,
1923349cc55cSDimitry Andric                               const llvm::APSInt &V,
1924349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1925349cc55cSDimitry Andric 
1926349cc55cSDimitry Andric   ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym,
1927349cc55cSDimitry Andric                               const llvm::APSInt &V,
1928349cc55cSDimitry Andric                               const llvm::APSInt &Adjustment) override;
1929349cc55cSDimitry Andric 
1930349cc55cSDimitry Andric   ProgramStateRef assumeSymWithinInclusiveRange(
1931349cc55cSDimitry Andric       ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1932349cc55cSDimitry Andric       const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1933349cc55cSDimitry Andric 
1934349cc55cSDimitry Andric   ProgramStateRef assumeSymOutsideInclusiveRange(
1935349cc55cSDimitry Andric       ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1936349cc55cSDimitry Andric       const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1937349cc55cSDimitry Andric 
1938349cc55cSDimitry Andric private:
1939349cc55cSDimitry Andric   RangeSet::Factory F;
1940349cc55cSDimitry Andric 
1941349cc55cSDimitry Andric   RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
1942349cc55cSDimitry Andric   RangeSet getRange(ProgramStateRef State, EquivalenceClass Class);
1943349cc55cSDimitry Andric   ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym,
1944349cc55cSDimitry Andric                            RangeSet Range);
1945349cc55cSDimitry Andric   ProgramStateRef setRange(ProgramStateRef State, EquivalenceClass Class,
1946349cc55cSDimitry Andric                            RangeSet Range);
1947349cc55cSDimitry Andric 
1948349cc55cSDimitry Andric   RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
1949349cc55cSDimitry Andric                          const llvm::APSInt &Int,
1950349cc55cSDimitry Andric                          const llvm::APSInt &Adjustment);
1951349cc55cSDimitry Andric   RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym,
1952349cc55cSDimitry Andric                          const llvm::APSInt &Int,
1953349cc55cSDimitry Andric                          const llvm::APSInt &Adjustment);
1954349cc55cSDimitry Andric   RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
1955349cc55cSDimitry Andric                          const llvm::APSInt &Int,
1956349cc55cSDimitry Andric                          const llvm::APSInt &Adjustment);
1957349cc55cSDimitry Andric   RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS,
1958349cc55cSDimitry Andric                          const llvm::APSInt &Int,
1959349cc55cSDimitry Andric                          const llvm::APSInt &Adjustment);
1960349cc55cSDimitry Andric   RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
1961349cc55cSDimitry Andric                          const llvm::APSInt &Int,
1962349cc55cSDimitry Andric                          const llvm::APSInt &Adjustment);
1963349cc55cSDimitry Andric };
1964349cc55cSDimitry Andric 
1965349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
1966fe6060f1SDimitry Andric //                         Constraint assignment logic
1967fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
1968fe6060f1SDimitry Andric 
1969fe6060f1SDimitry Andric /// ConstraintAssignorBase is a small utility class that unifies visitor
1970fe6060f1SDimitry Andric /// for ranges with a visitor for constraints (rangeset/range/constant).
1971fe6060f1SDimitry Andric ///
1972fe6060f1SDimitry Andric /// It is designed to have one derived class, but generally it can have more.
1973fe6060f1SDimitry Andric /// Derived class can control which types we handle by defining methods of the
1974fe6060f1SDimitry Andric /// following form:
1975fe6060f1SDimitry Andric ///
1976fe6060f1SDimitry Andric ///   bool handle${SYMBOL}To${CONSTRAINT}(const SYMBOL *Sym,
1977fe6060f1SDimitry Andric ///                                       CONSTRAINT Constraint);
1978fe6060f1SDimitry Andric ///
1979fe6060f1SDimitry Andric /// where SYMBOL is the type of the symbol (e.g. SymSymExpr, SymbolCast, etc.)
1980fe6060f1SDimitry Andric ///       CONSTRAINT is the type of constraint (RangeSet/Range/Const)
1981fe6060f1SDimitry Andric ///       return value signifies whether we should try other handle methods
1982fe6060f1SDimitry Andric ///          (i.e. false would mean to stop right after calling this method)
1983fe6060f1SDimitry Andric template <class Derived> class ConstraintAssignorBase {
1984fe6060f1SDimitry Andric public:
1985fe6060f1SDimitry Andric   using Const = const llvm::APSInt &;
1986fe6060f1SDimitry Andric 
1987fe6060f1SDimitry Andric #define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
1988fe6060f1SDimitry Andric 
1989fe6060f1SDimitry Andric #define ASSIGN(CLASS, TO, SYM, CONSTRAINT)                                     \
1990fe6060f1SDimitry Andric   if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT))   \
1991fe6060f1SDimitry Andric   return false
1992fe6060f1SDimitry Andric 
1993fe6060f1SDimitry Andric   void assign(SymbolRef Sym, RangeSet Constraint) {
1994fe6060f1SDimitry Andric     assignImpl(Sym, Constraint);
1995fe6060f1SDimitry Andric   }
1996fe6060f1SDimitry Andric 
1997fe6060f1SDimitry Andric   bool assignImpl(SymbolRef Sym, RangeSet Constraint) {
1998fe6060f1SDimitry Andric     switch (Sym->getKind()) {
1999fe6060f1SDimitry Andric #define SYMBOL(Id, Parent)                                                     \
2000fe6060f1SDimitry Andric   case SymExpr::Id##Kind:                                                      \
2001fe6060f1SDimitry Andric     DISPATCH(Id);
2002fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2003fe6060f1SDimitry Andric     }
2004fe6060f1SDimitry Andric     llvm_unreachable("Unknown SymExpr kind!");
2005fe6060f1SDimitry Andric   }
2006fe6060f1SDimitry Andric 
2007fe6060f1SDimitry Andric #define DEFAULT_ASSIGN(Id)                                                     \
2008fe6060f1SDimitry Andric   bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2009fe6060f1SDimitry Andric     return true;                                                               \
2010fe6060f1SDimitry Andric   }                                                                            \
2011fe6060f1SDimitry Andric   bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
2012fe6060f1SDimitry Andric   bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
2013fe6060f1SDimitry Andric 
2014fe6060f1SDimitry Andric   // When we dispatch for constraint types, we first try to check
2015fe6060f1SDimitry Andric   // if the new constraint is the constant and try the corresponding
2016fe6060f1SDimitry Andric   // assignor methods.  If it didn't interrupt, we can proceed to the
2017fe6060f1SDimitry Andric   // range, and finally to the range set.
2018fe6060f1SDimitry Andric #define CONSTRAINT_DISPATCH(Id)                                                \
2019fe6060f1SDimitry Andric   if (const llvm::APSInt *Const = Constraint.getConcreteValue()) {             \
2020fe6060f1SDimitry Andric     ASSIGN(Id, Const, Sym, *Const);                                            \
2021fe6060f1SDimitry Andric   }                                                                            \
2022fe6060f1SDimitry Andric   if (Constraint.size() == 1) {                                                \
2023fe6060f1SDimitry Andric     ASSIGN(Id, Range, Sym, *Constraint.begin());                               \
2024fe6060f1SDimitry Andric   }                                                                            \
2025fe6060f1SDimitry Andric   ASSIGN(Id, RangeSet, Sym, Constraint)
2026fe6060f1SDimitry Andric 
2027fe6060f1SDimitry Andric   // Our internal assign method first tries to call assignor methods for all
2028fe6060f1SDimitry Andric   // constraint types that apply.  And if not interrupted, continues with its
2029fe6060f1SDimitry Andric   // parent class.
2030fe6060f1SDimitry Andric #define SYMBOL(Id, Parent)                                                     \
2031fe6060f1SDimitry Andric   bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2032fe6060f1SDimitry Andric     CONSTRAINT_DISPATCH(Id);                                                   \
2033fe6060f1SDimitry Andric     DISPATCH(Parent);                                                          \
2034fe6060f1SDimitry Andric   }                                                                            \
2035fe6060f1SDimitry Andric   DEFAULT_ASSIGN(Id)
2036fe6060f1SDimitry Andric #define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
2037fe6060f1SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2038fe6060f1SDimitry Andric 
2039fe6060f1SDimitry Andric   // Default implementations for the top class that doesn't have parents.
2040fe6060f1SDimitry Andric   bool assignSymExprImpl(const SymExpr *Sym, RangeSet Constraint) {
2041fe6060f1SDimitry Andric     CONSTRAINT_DISPATCH(SymExpr);
2042fe6060f1SDimitry Andric     return true;
2043fe6060f1SDimitry Andric   }
2044fe6060f1SDimitry Andric   DEFAULT_ASSIGN(SymExpr);
2045fe6060f1SDimitry Andric 
2046fe6060f1SDimitry Andric #undef DISPATCH
2047fe6060f1SDimitry Andric #undef CONSTRAINT_DISPATCH
2048fe6060f1SDimitry Andric #undef DEFAULT_ASSIGN
2049fe6060f1SDimitry Andric #undef ASSIGN
2050fe6060f1SDimitry Andric };
2051fe6060f1SDimitry Andric 
2052fe6060f1SDimitry Andric /// A little component aggregating all of the reasoning we have about
2053fe6060f1SDimitry Andric /// assigning new constraints to symbols.
2054fe6060f1SDimitry Andric ///
2055fe6060f1SDimitry Andric /// The main purpose of this class is to associate constraints to symbols,
2056fe6060f1SDimitry Andric /// and impose additional constraints on other symbols, when we can imply
2057fe6060f1SDimitry Andric /// them.
2058fe6060f1SDimitry Andric ///
2059fe6060f1SDimitry Andric /// It has a nice symmetry with SymbolicRangeInferrer.  When the latter
2060fe6060f1SDimitry Andric /// can provide more precise ranges by looking into the operands of the
2061fe6060f1SDimitry Andric /// expression in question, ConstraintAssignor looks into the operands
2062fe6060f1SDimitry Andric /// to see if we can imply more from the new constraint.
2063fe6060f1SDimitry Andric class ConstraintAssignor : public ConstraintAssignorBase<ConstraintAssignor> {
2064fe6060f1SDimitry Andric public:
2065fe6060f1SDimitry Andric   template <class ClassOrSymbol>
2066bdd1243dSDimitry Andric   [[nodiscard]] static ProgramStateRef
2067fe6060f1SDimitry Andric   assign(ProgramStateRef State, SValBuilder &Builder, RangeSet::Factory &F,
2068fe6060f1SDimitry Andric          ClassOrSymbol CoS, RangeSet NewConstraint) {
2069fe6060f1SDimitry Andric     if (!State || NewConstraint.isEmpty())
2070fe6060f1SDimitry Andric       return nullptr;
2071fe6060f1SDimitry Andric 
2072fe6060f1SDimitry Andric     ConstraintAssignor Assignor{State, Builder, F};
2073fe6060f1SDimitry Andric     return Assignor.assign(CoS, NewConstraint);
2074fe6060f1SDimitry Andric   }
2075fe6060f1SDimitry Andric 
2076349cc55cSDimitry Andric   /// Handle expressions like: a % b != 0.
2077349cc55cSDimitry Andric   template <typename SymT>
2078349cc55cSDimitry Andric   bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
2079349cc55cSDimitry Andric     if (Sym->getOpcode() != BO_Rem)
2080349cc55cSDimitry Andric       return true;
2081349cc55cSDimitry Andric     // a % b != 0 implies that a != 0.
2082349cc55cSDimitry Andric     if (!Constraint.containsZero()) {
2083349cc55cSDimitry Andric       SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2084349cc55cSDimitry Andric       if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
2085349cc55cSDimitry Andric         State = State->assume(*NonLocSymSVal, true);
2086349cc55cSDimitry Andric         if (!State)
2087349cc55cSDimitry Andric           return false;
2088349cc55cSDimitry Andric       }
2089349cc55cSDimitry Andric     }
2090349cc55cSDimitry Andric     return true;
2091349cc55cSDimitry Andric   }
2092349cc55cSDimitry Andric 
2093fe6060f1SDimitry Andric   inline bool assignSymExprToConst(const SymExpr *Sym, Const Constraint);
2094349cc55cSDimitry Andric   inline bool assignSymIntExprToRangeSet(const SymIntExpr *Sym,
2095349cc55cSDimitry Andric                                          RangeSet Constraint) {
2096349cc55cSDimitry Andric     return handleRemainderOp(Sym, Constraint);
2097349cc55cSDimitry Andric   }
2098fe6060f1SDimitry Andric   inline bool assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2099fe6060f1SDimitry Andric                                          RangeSet Constraint);
2100fe6060f1SDimitry Andric 
2101fe6060f1SDimitry Andric private:
2102fe6060f1SDimitry Andric   ConstraintAssignor(ProgramStateRef State, SValBuilder &Builder,
2103fe6060f1SDimitry Andric                      RangeSet::Factory &F)
2104fe6060f1SDimitry Andric       : State(State), Builder(Builder), RangeFactory(F) {}
2105fe6060f1SDimitry Andric   using Base = ConstraintAssignorBase<ConstraintAssignor>;
2106fe6060f1SDimitry Andric 
2107fe6060f1SDimitry Andric   /// Base method for handling new constraints for symbols.
2108bdd1243dSDimitry Andric   [[nodiscard]] ProgramStateRef assign(SymbolRef Sym, RangeSet NewConstraint) {
2109fe6060f1SDimitry Andric     // All constraints are actually associated with equivalence classes, and
2110fe6060f1SDimitry Andric     // that's what we are going to do first.
2111fe6060f1SDimitry Andric     State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2112fe6060f1SDimitry Andric     if (!State)
2113fe6060f1SDimitry Andric       return nullptr;
2114fe6060f1SDimitry Andric 
2115fe6060f1SDimitry Andric     // And after that we can check what other things we can get from this
2116fe6060f1SDimitry Andric     // constraint.
2117fe6060f1SDimitry Andric     Base::assign(Sym, NewConstraint);
2118fe6060f1SDimitry Andric     return State;
2119fe6060f1SDimitry Andric   }
2120fe6060f1SDimitry Andric 
2121fe6060f1SDimitry Andric   /// Base method for handling new constraints for classes.
2122bdd1243dSDimitry Andric   [[nodiscard]] ProgramStateRef assign(EquivalenceClass Class,
2123fe6060f1SDimitry Andric                                        RangeSet NewConstraint) {
2124fe6060f1SDimitry Andric     // There is a chance that we might need to update constraints for the
2125fe6060f1SDimitry Andric     // classes that are known to be disequal to Class.
2126fe6060f1SDimitry Andric     //
2127fe6060f1SDimitry Andric     // In order for this to be even possible, the new constraint should
2128fe6060f1SDimitry Andric     // be simply a constant because we can't reason about range disequalities.
2129fe6060f1SDimitry Andric     if (const llvm::APSInt *Point = NewConstraint.getConcreteValue()) {
2130fe6060f1SDimitry Andric 
2131fe6060f1SDimitry Andric       ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2132fe6060f1SDimitry Andric       ConstraintRangeTy::Factory &CF = State->get_context<ConstraintRange>();
2133fe6060f1SDimitry Andric 
2134fe6060f1SDimitry Andric       // Add new constraint.
2135fe6060f1SDimitry Andric       Constraints = CF.add(Constraints, Class, NewConstraint);
2136fe6060f1SDimitry Andric 
2137fe6060f1SDimitry Andric       for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) {
2138fe6060f1SDimitry Andric         RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
2139fe6060f1SDimitry Andric             RangeFactory, State, DisequalClass);
2140fe6060f1SDimitry Andric 
2141fe6060f1SDimitry Andric         UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2142fe6060f1SDimitry Andric 
2143fe6060f1SDimitry Andric         // If we end up with at least one of the disequal classes to be
2144fe6060f1SDimitry Andric         // constrained with an empty range-set, the state is infeasible.
2145fe6060f1SDimitry Andric         if (UpdatedConstraint.isEmpty())
2146fe6060f1SDimitry Andric           return nullptr;
2147fe6060f1SDimitry Andric 
2148fe6060f1SDimitry Andric         Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint);
2149fe6060f1SDimitry Andric       }
2150fe6060f1SDimitry Andric       assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2151fe6060f1SDimitry Andric                                          "a state with infeasible constraints");
2152fe6060f1SDimitry Andric 
2153fe6060f1SDimitry Andric       return setConstraints(State, Constraints);
2154fe6060f1SDimitry Andric     }
2155fe6060f1SDimitry Andric 
2156fe6060f1SDimitry Andric     return setConstraint(State, Class, NewConstraint);
2157fe6060f1SDimitry Andric   }
2158fe6060f1SDimitry Andric 
2159fe6060f1SDimitry Andric   ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS,
2160fe6060f1SDimitry Andric                                    SymbolRef RHS) {
2161fe6060f1SDimitry Andric     return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2162fe6060f1SDimitry Andric   }
2163fe6060f1SDimitry Andric 
2164fe6060f1SDimitry Andric   ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS,
2165fe6060f1SDimitry Andric                                 SymbolRef RHS) {
2166fe6060f1SDimitry Andric     return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2167fe6060f1SDimitry Andric   }
2168fe6060f1SDimitry Andric 
2169bdd1243dSDimitry Andric   [[nodiscard]] std::optional<bool> interpreteAsBool(RangeSet Constraint) {
2170fe6060f1SDimitry Andric     assert(!Constraint.isEmpty() && "Empty ranges shouldn't get here");
2171fe6060f1SDimitry Andric 
2172fe6060f1SDimitry Andric     if (Constraint.getConcreteValue())
2173349cc55cSDimitry Andric       return !Constraint.getConcreteValue()->isZero();
2174fe6060f1SDimitry Andric 
2175349cc55cSDimitry Andric     if (!Constraint.containsZero())
2176fe6060f1SDimitry Andric       return true;
2177fe6060f1SDimitry Andric 
2178bdd1243dSDimitry Andric     return std::nullopt;
2179fe6060f1SDimitry Andric   }
2180fe6060f1SDimitry Andric 
2181fe6060f1SDimitry Andric   ProgramStateRef State;
2182fe6060f1SDimitry Andric   SValBuilder &Builder;
2183fe6060f1SDimitry Andric   RangeSet::Factory &RangeFactory;
2184fe6060f1SDimitry Andric };
2185fe6060f1SDimitry Andric 
2186fe6060f1SDimitry Andric bool ConstraintAssignor::assignSymExprToConst(const SymExpr *Sym,
2187fe6060f1SDimitry Andric                                               const llvm::APSInt &Constraint) {
2188fe6060f1SDimitry Andric   llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2189fe6060f1SDimitry Andric   // Iterate over all equivalence classes and try to simplify them.
2190fe6060f1SDimitry Andric   ClassMembersTy Members = State->get<ClassMembers>();
2191fe6060f1SDimitry Andric   for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2192fe6060f1SDimitry Andric     EquivalenceClass Class = ClassToSymbolSet.first;
2193fe6060f1SDimitry Andric     State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2194fe6060f1SDimitry Andric     if (!State)
2195fe6060f1SDimitry Andric       return false;
2196fe6060f1SDimitry Andric     SimplifiedClasses.insert(Class);
2197fe6060f1SDimitry Andric   }
2198fe6060f1SDimitry Andric 
2199fe6060f1SDimitry Andric   // Trivial equivalence classes (those that have only one symbol member) are
2200fe6060f1SDimitry Andric   // not stored in the State. Thus, we must skim through the constraints as
2201fe6060f1SDimitry Andric   // well. And we try to simplify symbols in the constraints.
2202fe6060f1SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2203fe6060f1SDimitry Andric   for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2204fe6060f1SDimitry Andric     EquivalenceClass Class = ClassConstraint.first;
2205fe6060f1SDimitry Andric     if (SimplifiedClasses.count(Class)) // Already simplified.
2206fe6060f1SDimitry Andric       continue;
2207fe6060f1SDimitry Andric     State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2208fe6060f1SDimitry Andric     if (!State)
2209fe6060f1SDimitry Andric       return false;
2210fe6060f1SDimitry Andric   }
2211fe6060f1SDimitry Andric 
2212349cc55cSDimitry Andric   // We may have trivial equivalence classes in the disequality info as
2213349cc55cSDimitry Andric   // well, and we need to simplify them.
2214349cc55cSDimitry Andric   DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2215349cc55cSDimitry Andric   for (std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2216349cc55cSDimitry Andric        DisequalityInfo) {
2217349cc55cSDimitry Andric     EquivalenceClass Class = DisequalityEntry.first;
2218349cc55cSDimitry Andric     ClassSet DisequalClasses = DisequalityEntry.second;
2219349cc55cSDimitry Andric     State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2220349cc55cSDimitry Andric     if (!State)
2221349cc55cSDimitry Andric       return false;
2222349cc55cSDimitry Andric   }
2223349cc55cSDimitry Andric 
2224fe6060f1SDimitry Andric   return true;
2225fe6060f1SDimitry Andric }
2226fe6060f1SDimitry Andric 
2227fe6060f1SDimitry Andric bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2228fe6060f1SDimitry Andric                                                     RangeSet Constraint) {
2229349cc55cSDimitry Andric   if (!handleRemainderOp(Sym, Constraint))
2230349cc55cSDimitry Andric     return false;
2231349cc55cSDimitry Andric 
2232bdd1243dSDimitry Andric   std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2233fe6060f1SDimitry Andric 
2234fe6060f1SDimitry Andric   if (!ConstraintAsBool)
2235fe6060f1SDimitry Andric     return true;
2236fe6060f1SDimitry Andric 
2237bdd1243dSDimitry Andric   if (std::optional<bool> Equality = meansEquality(Sym)) {
2238fe6060f1SDimitry Andric     // Here we cover two cases:
2239fe6060f1SDimitry Andric     //   * if Sym is equality and the new constraint is true -> Sym's operands
2240fe6060f1SDimitry Andric     //     should be marked as equal
2241fe6060f1SDimitry Andric     //   * if Sym is disequality and the new constraint is false -> Sym's
2242fe6060f1SDimitry Andric     //     operands should be also marked as equal
2243fe6060f1SDimitry Andric     if (*Equality == *ConstraintAsBool) {
2244fe6060f1SDimitry Andric       State = trackEquality(State, Sym->getLHS(), Sym->getRHS());
2245fe6060f1SDimitry Andric     } else {
2246fe6060f1SDimitry Andric       // Other combinations leave as with disequal operands.
2247fe6060f1SDimitry Andric       State = trackDisequality(State, Sym->getLHS(), Sym->getRHS());
2248fe6060f1SDimitry Andric     }
2249fe6060f1SDimitry Andric 
2250fe6060f1SDimitry Andric     if (!State)
2251fe6060f1SDimitry Andric       return false;
2252fe6060f1SDimitry Andric   }
2253fe6060f1SDimitry Andric 
2254fe6060f1SDimitry Andric   return true;
2255fe6060f1SDimitry Andric }
2256fe6060f1SDimitry Andric 
22570b57cec5SDimitry Andric } // end anonymous namespace
22580b57cec5SDimitry Andric 
22590b57cec5SDimitry Andric std::unique_ptr<ConstraintManager>
22605ffd83dbSDimitry Andric ento::CreateRangeConstraintManager(ProgramStateManager &StMgr,
22615ffd83dbSDimitry Andric                                    ExprEngine *Eng) {
2262a7dea167SDimitry Andric   return std::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder());
22630b57cec5SDimitry Andric }
22640b57cec5SDimitry Andric 
2265e8d8bef9SDimitry Andric ConstraintMap ento::getConstraintMap(ProgramStateRef State) {
2266e8d8bef9SDimitry Andric   ConstraintMap::Factory &F = State->get_context<ConstraintMap>();
2267e8d8bef9SDimitry Andric   ConstraintMap Result = F.getEmptyMap();
2268e8d8bef9SDimitry Andric 
2269e8d8bef9SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2270e8d8bef9SDimitry Andric   for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2271e8d8bef9SDimitry Andric     EquivalenceClass Class = ClassConstraint.first;
2272e8d8bef9SDimitry Andric     SymbolSet ClassMembers = Class.getClassMembers(State);
2273e8d8bef9SDimitry Andric     assert(!ClassMembers.isEmpty() &&
2274e8d8bef9SDimitry Andric            "Class must always have at least one member!");
2275e8d8bef9SDimitry Andric 
2276e8d8bef9SDimitry Andric     SymbolRef Representative = *ClassMembers.begin();
2277e8d8bef9SDimitry Andric     Result = F.add(Result, Representative, ClassConstraint.second);
2278e8d8bef9SDimitry Andric   }
2279e8d8bef9SDimitry Andric 
2280e8d8bef9SDimitry Andric   return Result;
2281e8d8bef9SDimitry Andric }
2282e8d8bef9SDimitry Andric 
2283e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2284e8d8bef9SDimitry Andric //                     EqualityClass implementation details
2285e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2286e8d8bef9SDimitry Andric 
2287fe6060f1SDimitry Andric LLVM_DUMP_METHOD void EquivalenceClass::dumpToStream(ProgramStateRef State,
2288fe6060f1SDimitry Andric                                                      raw_ostream &os) const {
2289fe6060f1SDimitry Andric   SymbolSet ClassMembers = getClassMembers(State);
2290fe6060f1SDimitry Andric   for (const SymbolRef &MemberSym : ClassMembers) {
2291fe6060f1SDimitry Andric     MemberSym->dump();
2292fe6060f1SDimitry Andric     os << "\n";
2293fe6060f1SDimitry Andric   }
2294fe6060f1SDimitry Andric }
2295fe6060f1SDimitry Andric 
2296e8d8bef9SDimitry Andric inline EquivalenceClass EquivalenceClass::find(ProgramStateRef State,
2297e8d8bef9SDimitry Andric                                                SymbolRef Sym) {
2298fe6060f1SDimitry Andric   assert(State && "State should not be null");
2299fe6060f1SDimitry Andric   assert(Sym && "Symbol should not be null");
2300e8d8bef9SDimitry Andric   // We store far from all Symbol -> Class mappings
2301e8d8bef9SDimitry Andric   if (const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2302e8d8bef9SDimitry Andric     return *NontrivialClass;
2303e8d8bef9SDimitry Andric 
2304e8d8bef9SDimitry Andric   // This is a trivial class of Sym.
2305e8d8bef9SDimitry Andric   return Sym;
2306e8d8bef9SDimitry Andric }
2307e8d8bef9SDimitry Andric 
2308fe6060f1SDimitry Andric inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2309e8d8bef9SDimitry Andric                                                ProgramStateRef State,
2310e8d8bef9SDimitry Andric                                                SymbolRef First,
2311e8d8bef9SDimitry Andric                                                SymbolRef Second) {
2312e8d8bef9SDimitry Andric   EquivalenceClass FirstClass = find(State, First);
2313e8d8bef9SDimitry Andric   EquivalenceClass SecondClass = find(State, Second);
2314e8d8bef9SDimitry Andric 
2315fe6060f1SDimitry Andric   return FirstClass.merge(F, State, SecondClass);
2316e8d8bef9SDimitry Andric }
2317e8d8bef9SDimitry Andric 
2318fe6060f1SDimitry Andric inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2319e8d8bef9SDimitry Andric                                                ProgramStateRef State,
2320e8d8bef9SDimitry Andric                                                EquivalenceClass Other) {
2321e8d8bef9SDimitry Andric   // It is already the same class.
2322e8d8bef9SDimitry Andric   if (*this == Other)
2323e8d8bef9SDimitry Andric     return State;
2324e8d8bef9SDimitry Andric 
2325e8d8bef9SDimitry Andric   // FIXME: As of now, we support only equivalence classes of the same type.
2326e8d8bef9SDimitry Andric   //        This limitation is connected to the lack of explicit casts in
2327e8d8bef9SDimitry Andric   //        our symbolic expression model.
2328e8d8bef9SDimitry Andric   //
2329e8d8bef9SDimitry Andric   //        That means that for `int x` and `char y` we don't distinguish
2330e8d8bef9SDimitry Andric   //        between these two very different cases:
2331e8d8bef9SDimitry Andric   //          * `x == y`
2332e8d8bef9SDimitry Andric   //          * `(char)x == y`
2333e8d8bef9SDimitry Andric   //
2334e8d8bef9SDimitry Andric   //        The moment we introduce symbolic casts, this restriction can be
2335e8d8bef9SDimitry Andric   //        lifted.
2336*0fca6ea1SDimitry Andric   if (getType()->getCanonicalTypeUnqualified() !=
2337*0fca6ea1SDimitry Andric       Other.getType()->getCanonicalTypeUnqualified())
2338e8d8bef9SDimitry Andric     return State;
2339e8d8bef9SDimitry Andric 
2340e8d8bef9SDimitry Andric   SymbolSet Members = getClassMembers(State);
2341e8d8bef9SDimitry Andric   SymbolSet OtherMembers = Other.getClassMembers(State);
2342e8d8bef9SDimitry Andric 
2343e8d8bef9SDimitry Andric   // We estimate the size of the class by the height of tree containing
2344e8d8bef9SDimitry Andric   // its members.  Merging is not a trivial operation, so it's easier to
2345e8d8bef9SDimitry Andric   // merge the smaller class into the bigger one.
2346e8d8bef9SDimitry Andric   if (Members.getHeight() >= OtherMembers.getHeight()) {
2347fe6060f1SDimitry Andric     return mergeImpl(F, State, Members, Other, OtherMembers);
2348e8d8bef9SDimitry Andric   } else {
2349fe6060f1SDimitry Andric     return Other.mergeImpl(F, State, OtherMembers, *this, Members);
2350e8d8bef9SDimitry Andric   }
2351e8d8bef9SDimitry Andric }
2352e8d8bef9SDimitry Andric 
2353e8d8bef9SDimitry Andric inline ProgramStateRef
2354fe6060f1SDimitry Andric EquivalenceClass::mergeImpl(RangeSet::Factory &RangeFactory,
2355e8d8bef9SDimitry Andric                             ProgramStateRef State, SymbolSet MyMembers,
2356e8d8bef9SDimitry Andric                             EquivalenceClass Other, SymbolSet OtherMembers) {
2357e8d8bef9SDimitry Andric   // Essentially what we try to recreate here is some kind of union-find
2358e8d8bef9SDimitry Andric   // data structure.  It does have certain limitations due to persistence
2359e8d8bef9SDimitry Andric   // and the need to remove elements from classes.
2360e8d8bef9SDimitry Andric   //
2361e8d8bef9SDimitry Andric   // In this setting, EquialityClass object is the representative of the class
2362e8d8bef9SDimitry Andric   // or the parent element.  ClassMap is a mapping of class members to their
2363e8d8bef9SDimitry Andric   // parent. Unlike the union-find structure, they all point directly to the
2364e8d8bef9SDimitry Andric   // class representative because we don't have an opportunity to actually do
2365e8d8bef9SDimitry Andric   // path compression when dealing with immutability.  This means that we
2366e8d8bef9SDimitry Andric   // compress paths every time we do merges.  It also means that we lose
2367e8d8bef9SDimitry Andric   // the main amortized complexity benefit from the original data structure.
2368e8d8bef9SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2369e8d8bef9SDimitry Andric   ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2370e8d8bef9SDimitry Andric 
2371e8d8bef9SDimitry Andric   // 1. If the merged classes have any constraints associated with them, we
2372e8d8bef9SDimitry Andric   //    need to transfer them to the class we have left.
2373e8d8bef9SDimitry Andric   //
2374e8d8bef9SDimitry Andric   // Intersection here makes perfect sense because both of these constraints
2375e8d8bef9SDimitry Andric   // must hold for the whole new class.
2376bdd1243dSDimitry Andric   if (std::optional<RangeSet> NewClassConstraint =
2377fe6060f1SDimitry Andric           intersect(RangeFactory, getConstraint(State, *this),
2378e8d8bef9SDimitry Andric                     getConstraint(State, Other))) {
2379e8d8bef9SDimitry Andric     // NOTE: Essentially, NewClassConstraint should NEVER be infeasible because
2380e8d8bef9SDimitry Andric     //       range inferrer shouldn't generate ranges incompatible with
2381e8d8bef9SDimitry Andric     //       equivalence classes. However, at the moment, due to imperfections
2382e8d8bef9SDimitry Andric     //       in the solver, it is possible and the merge function can also
2383e8d8bef9SDimitry Andric     //       return infeasible states aka null states.
2384e8d8bef9SDimitry Andric     if (NewClassConstraint->isEmpty())
2385e8d8bef9SDimitry Andric       // Infeasible state
2386e8d8bef9SDimitry Andric       return nullptr;
2387e8d8bef9SDimitry Andric 
2388e8d8bef9SDimitry Andric     // No need in tracking constraints of a now-dissolved class.
2389e8d8bef9SDimitry Andric     Constraints = CRF.remove(Constraints, Other);
2390e8d8bef9SDimitry Andric     // Assign new constraints for this class.
2391e8d8bef9SDimitry Andric     Constraints = CRF.add(Constraints, *this, *NewClassConstraint);
2392e8d8bef9SDimitry Andric 
2393fe6060f1SDimitry Andric     assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2394fe6060f1SDimitry Andric                                        "a state with infeasible constraints");
2395fe6060f1SDimitry Andric 
2396e8d8bef9SDimitry Andric     State = State->set<ConstraintRange>(Constraints);
2397e8d8bef9SDimitry Andric   }
2398e8d8bef9SDimitry Andric 
2399e8d8bef9SDimitry Andric   // 2. Get ALL equivalence-related maps
2400e8d8bef9SDimitry Andric   ClassMapTy Classes = State->get<ClassMap>();
2401e8d8bef9SDimitry Andric   ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2402e8d8bef9SDimitry Andric 
2403e8d8bef9SDimitry Andric   ClassMembersTy Members = State->get<ClassMembers>();
2404e8d8bef9SDimitry Andric   ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2405e8d8bef9SDimitry Andric 
2406e8d8bef9SDimitry Andric   DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2407e8d8bef9SDimitry Andric   DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2408e8d8bef9SDimitry Andric 
2409e8d8bef9SDimitry Andric   ClassSet::Factory &CF = State->get_context<ClassSet>();
2410e8d8bef9SDimitry Andric   SymbolSet::Factory &F = getMembersFactory(State);
2411e8d8bef9SDimitry Andric 
2412e8d8bef9SDimitry Andric   // 2. Merge members of the Other class into the current class.
2413e8d8bef9SDimitry Andric   SymbolSet NewClassMembers = MyMembers;
2414e8d8bef9SDimitry Andric   for (SymbolRef Sym : OtherMembers) {
2415e8d8bef9SDimitry Andric     NewClassMembers = F.add(NewClassMembers, Sym);
2416e8d8bef9SDimitry Andric     // *this is now the class for all these new symbols.
2417e8d8bef9SDimitry Andric     Classes = CMF.add(Classes, Sym, *this);
2418e8d8bef9SDimitry Andric   }
2419e8d8bef9SDimitry Andric 
2420e8d8bef9SDimitry Andric   // 3. Adjust member mapping.
2421e8d8bef9SDimitry Andric   //
2422e8d8bef9SDimitry Andric   // No need in tracking members of a now-dissolved class.
2423e8d8bef9SDimitry Andric   Members = MF.remove(Members, Other);
2424e8d8bef9SDimitry Andric   // Now only the current class is mapped to all the symbols.
2425e8d8bef9SDimitry Andric   Members = MF.add(Members, *this, NewClassMembers);
2426e8d8bef9SDimitry Andric 
2427e8d8bef9SDimitry Andric   // 4. Update disequality relations
2428e8d8bef9SDimitry Andric   ClassSet DisequalToOther = Other.getDisequalClasses(DisequalityInfo, CF);
2429fe6060f1SDimitry Andric   // We are about to merge two classes but they are already known to be
2430fe6060f1SDimitry Andric   // non-equal. This is a contradiction.
2431fe6060f1SDimitry Andric   if (DisequalToOther.contains(*this))
2432fe6060f1SDimitry Andric     return nullptr;
2433fe6060f1SDimitry Andric 
2434e8d8bef9SDimitry Andric   if (!DisequalToOther.isEmpty()) {
2435e8d8bef9SDimitry Andric     ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo, CF);
2436e8d8bef9SDimitry Andric     DisequalityInfo = DF.remove(DisequalityInfo, Other);
2437e8d8bef9SDimitry Andric 
2438e8d8bef9SDimitry Andric     for (EquivalenceClass DisequalClass : DisequalToOther) {
2439e8d8bef9SDimitry Andric       DisequalToThis = CF.add(DisequalToThis, DisequalClass);
2440e8d8bef9SDimitry Andric 
2441e8d8bef9SDimitry Andric       // Disequality is a symmetric relation meaning that if
2442e8d8bef9SDimitry Andric       // DisequalToOther not null then the set for DisequalClass is not
2443e8d8bef9SDimitry Andric       // empty and has at least Other.
2444e8d8bef9SDimitry Andric       ClassSet OriginalSetLinkedToOther =
2445e8d8bef9SDimitry Andric           *DisequalityInfo.lookup(DisequalClass);
2446e8d8bef9SDimitry Andric 
2447e8d8bef9SDimitry Andric       // Other will be eliminated and we should replace it with the bigger
2448e8d8bef9SDimitry Andric       // united class.
2449e8d8bef9SDimitry Andric       ClassSet NewSet = CF.remove(OriginalSetLinkedToOther, Other);
2450e8d8bef9SDimitry Andric       NewSet = CF.add(NewSet, *this);
2451e8d8bef9SDimitry Andric 
2452e8d8bef9SDimitry Andric       DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2453e8d8bef9SDimitry Andric     }
2454e8d8bef9SDimitry Andric 
2455e8d8bef9SDimitry Andric     DisequalityInfo = DF.add(DisequalityInfo, *this, DisequalToThis);
2456e8d8bef9SDimitry Andric     State = State->set<DisequalityMap>(DisequalityInfo);
2457e8d8bef9SDimitry Andric   }
2458e8d8bef9SDimitry Andric 
2459e8d8bef9SDimitry Andric   // 5. Update the state
2460e8d8bef9SDimitry Andric   State = State->set<ClassMap>(Classes);
2461e8d8bef9SDimitry Andric   State = State->set<ClassMembers>(Members);
2462e8d8bef9SDimitry Andric 
2463e8d8bef9SDimitry Andric   return State;
2464e8d8bef9SDimitry Andric }
2465e8d8bef9SDimitry Andric 
2466e8d8bef9SDimitry Andric inline SymbolSet::Factory &
2467e8d8bef9SDimitry Andric EquivalenceClass::getMembersFactory(ProgramStateRef State) {
2468e8d8bef9SDimitry Andric   return State->get_context<SymbolSet>();
2469e8d8bef9SDimitry Andric }
2470e8d8bef9SDimitry Andric 
2471fe6060f1SDimitry Andric SymbolSet EquivalenceClass::getClassMembers(ProgramStateRef State) const {
2472e8d8bef9SDimitry Andric   if (const SymbolSet *Members = State->get<ClassMembers>(*this))
2473e8d8bef9SDimitry Andric     return *Members;
2474e8d8bef9SDimitry Andric 
2475e8d8bef9SDimitry Andric   // This class is trivial, so we need to construct a set
2476e8d8bef9SDimitry Andric   // with just that one symbol from the class.
2477e8d8bef9SDimitry Andric   SymbolSet::Factory &F = getMembersFactory(State);
2478e8d8bef9SDimitry Andric   return F.add(F.getEmptySet(), getRepresentativeSymbol());
2479e8d8bef9SDimitry Andric }
2480e8d8bef9SDimitry Andric 
2481fe6060f1SDimitry Andric bool EquivalenceClass::isTrivial(ProgramStateRef State) const {
2482e8d8bef9SDimitry Andric   return State->get<ClassMembers>(*this) == nullptr;
2483e8d8bef9SDimitry Andric }
2484e8d8bef9SDimitry Andric 
2485e8d8bef9SDimitry Andric bool EquivalenceClass::isTriviallyDead(ProgramStateRef State,
2486fe6060f1SDimitry Andric                                        SymbolReaper &Reaper) const {
2487e8d8bef9SDimitry Andric   return isTrivial(State) && Reaper.isDead(getRepresentativeSymbol());
2488e8d8bef9SDimitry Andric }
2489e8d8bef9SDimitry Andric 
2490fe6060f1SDimitry Andric inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2491e8d8bef9SDimitry Andric                                                       ProgramStateRef State,
2492e8d8bef9SDimitry Andric                                                       SymbolRef First,
2493e8d8bef9SDimitry Andric                                                       SymbolRef Second) {
2494fe6060f1SDimitry Andric   return markDisequal(RF, State, find(State, First), find(State, Second));
2495e8d8bef9SDimitry Andric }
2496e8d8bef9SDimitry Andric 
2497fe6060f1SDimitry Andric inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2498e8d8bef9SDimitry Andric                                                       ProgramStateRef State,
2499e8d8bef9SDimitry Andric                                                       EquivalenceClass First,
2500e8d8bef9SDimitry Andric                                                       EquivalenceClass Second) {
2501fe6060f1SDimitry Andric   return First.markDisequal(RF, State, Second);
2502e8d8bef9SDimitry Andric }
2503e8d8bef9SDimitry Andric 
2504e8d8bef9SDimitry Andric inline ProgramStateRef
2505fe6060f1SDimitry Andric EquivalenceClass::markDisequal(RangeSet::Factory &RF, ProgramStateRef State,
2506e8d8bef9SDimitry Andric                                EquivalenceClass Other) const {
2507e8d8bef9SDimitry Andric   // If we know that two classes are equal, we can only produce an infeasible
2508e8d8bef9SDimitry Andric   // state.
2509e8d8bef9SDimitry Andric   if (*this == Other) {
2510e8d8bef9SDimitry Andric     return nullptr;
2511e8d8bef9SDimitry Andric   }
2512e8d8bef9SDimitry Andric 
2513e8d8bef9SDimitry Andric   DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2514e8d8bef9SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2515e8d8bef9SDimitry Andric 
2516e8d8bef9SDimitry Andric   // Disequality is a symmetric relation, so if we mark A as disequal to B,
2517e8d8bef9SDimitry Andric   // we should also mark B as disequalt to A.
2518fe6060f1SDimitry Andric   if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *this,
2519fe6060f1SDimitry Andric                             Other) ||
2520fe6060f1SDimitry Andric       !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, Other,
2521fe6060f1SDimitry Andric                             *this))
2522fe6060f1SDimitry Andric     return nullptr;
2523fe6060f1SDimitry Andric 
2524fe6060f1SDimitry Andric   assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2525fe6060f1SDimitry Andric                                      "a state with infeasible constraints");
2526e8d8bef9SDimitry Andric 
2527e8d8bef9SDimitry Andric   State = State->set<DisequalityMap>(DisequalityInfo);
2528e8d8bef9SDimitry Andric   State = State->set<ConstraintRange>(Constraints);
2529e8d8bef9SDimitry Andric 
2530e8d8bef9SDimitry Andric   return State;
2531e8d8bef9SDimitry Andric }
2532e8d8bef9SDimitry Andric 
2533fe6060f1SDimitry Andric inline bool EquivalenceClass::addToDisequalityInfo(
2534e8d8bef9SDimitry Andric     DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2535fe6060f1SDimitry Andric     RangeSet::Factory &RF, ProgramStateRef State, EquivalenceClass First,
2536fe6060f1SDimitry Andric     EquivalenceClass Second) {
2537e8d8bef9SDimitry Andric 
2538e8d8bef9SDimitry Andric   // 1. Get all of the required factories.
2539e8d8bef9SDimitry Andric   DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2540e8d8bef9SDimitry Andric   ClassSet::Factory &CF = State->get_context<ClassSet>();
2541e8d8bef9SDimitry Andric   ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2542e8d8bef9SDimitry Andric 
2543e8d8bef9SDimitry Andric   // 2. Add Second to the set of classes disequal to First.
2544e8d8bef9SDimitry Andric   const ClassSet *CurrentSet = Info.lookup(First);
2545e8d8bef9SDimitry Andric   ClassSet NewSet = CurrentSet ? *CurrentSet : CF.getEmptySet();
2546e8d8bef9SDimitry Andric   NewSet = CF.add(NewSet, Second);
2547e8d8bef9SDimitry Andric 
2548e8d8bef9SDimitry Andric   Info = F.add(Info, First, NewSet);
2549e8d8bef9SDimitry Andric 
2550e8d8bef9SDimitry Andric   // 3. If Second is known to be a constant, we can delete this point
2551e8d8bef9SDimitry Andric   //    from the constraint asociated with First.
2552e8d8bef9SDimitry Andric   //
2553e8d8bef9SDimitry Andric   //    So, if Second == 10, it means that First != 10.
2554e8d8bef9SDimitry Andric   //    At the same time, the same logic does not apply to ranges.
2555e8d8bef9SDimitry Andric   if (const RangeSet *SecondConstraint = Constraints.lookup(Second))
2556e8d8bef9SDimitry Andric     if (const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2557e8d8bef9SDimitry Andric 
2558e8d8bef9SDimitry Andric       RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
2559fe6060f1SDimitry Andric           RF, State, First.getRepresentativeSymbol());
2560e8d8bef9SDimitry Andric 
2561fe6060f1SDimitry Andric       FirstConstraint = RF.deletePoint(FirstConstraint, *Point);
2562fe6060f1SDimitry Andric 
2563fe6060f1SDimitry Andric       // If the First class is about to be constrained with an empty
2564fe6060f1SDimitry Andric       // range-set, the state is infeasible.
2565fe6060f1SDimitry Andric       if (FirstConstraint.isEmpty())
2566fe6060f1SDimitry Andric         return false;
2567fe6060f1SDimitry Andric 
2568e8d8bef9SDimitry Andric       Constraints = CRF.add(Constraints, First, FirstConstraint);
2569e8d8bef9SDimitry Andric     }
2570fe6060f1SDimitry Andric 
2571fe6060f1SDimitry Andric   return true;
2572e8d8bef9SDimitry Andric }
2573e8d8bef9SDimitry Andric 
2574bdd1243dSDimitry Andric inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2575e8d8bef9SDimitry Andric                                                       SymbolRef FirstSym,
2576e8d8bef9SDimitry Andric                                                       SymbolRef SecondSym) {
2577fe6060f1SDimitry Andric   return EquivalenceClass::areEqual(State, find(State, FirstSym),
2578fe6060f1SDimitry Andric                                     find(State, SecondSym));
2579fe6060f1SDimitry Andric }
2580e8d8bef9SDimitry Andric 
2581bdd1243dSDimitry Andric inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2582fe6060f1SDimitry Andric                                                       EquivalenceClass First,
2583fe6060f1SDimitry Andric                                                       EquivalenceClass Second) {
2584e8d8bef9SDimitry Andric   // The same equivalence class => symbols are equal.
2585e8d8bef9SDimitry Andric   if (First == Second)
2586e8d8bef9SDimitry Andric     return true;
2587e8d8bef9SDimitry Andric 
2588e8d8bef9SDimitry Andric   // Let's check if we know anything about these two classes being not equal to
2589e8d8bef9SDimitry Andric   // each other.
2590e8d8bef9SDimitry Andric   ClassSet DisequalToFirst = First.getDisequalClasses(State);
2591e8d8bef9SDimitry Andric   if (DisequalToFirst.contains(Second))
2592e8d8bef9SDimitry Andric     return false;
2593e8d8bef9SDimitry Andric 
2594e8d8bef9SDimitry Andric   // It is not clear.
2595bdd1243dSDimitry Andric   return std::nullopt;
2596e8d8bef9SDimitry Andric }
2597e8d8bef9SDimitry Andric 
2598bdd1243dSDimitry Andric [[nodiscard]] ProgramStateRef
2599349cc55cSDimitry Andric EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) {
2600349cc55cSDimitry Andric 
2601349cc55cSDimitry Andric   SymbolSet ClsMembers = getClassMembers(State);
2602349cc55cSDimitry Andric   assert(ClsMembers.contains(Old));
2603349cc55cSDimitry Andric 
2604349cc55cSDimitry Andric   // Remove `Old`'s Class->Sym relation.
2605349cc55cSDimitry Andric   SymbolSet::Factory &F = getMembersFactory(State);
2606349cc55cSDimitry Andric   ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2607349cc55cSDimitry Andric   ClsMembers = F.remove(ClsMembers, Old);
2608349cc55cSDimitry Andric   // Ensure another precondition of the removeMember function (we can check
2609349cc55cSDimitry Andric   // this only with isEmpty, thus we have to do the remove first).
2610349cc55cSDimitry Andric   assert(!ClsMembers.isEmpty() &&
2611349cc55cSDimitry Andric          "Class should have had at least two members before member removal");
2612349cc55cSDimitry Andric   // Overwrite the existing members assigned to this class.
2613349cc55cSDimitry Andric   ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2614349cc55cSDimitry Andric   ClassMembersMap = EMFactory.add(ClassMembersMap, *this, ClsMembers);
2615349cc55cSDimitry Andric   State = State->set<ClassMembers>(ClassMembersMap);
2616349cc55cSDimitry Andric 
261781ad6265SDimitry Andric   // Remove `Old`'s Sym->Class relation.
261881ad6265SDimitry Andric   ClassMapTy Classes = State->get<ClassMap>();
261981ad6265SDimitry Andric   ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
262081ad6265SDimitry Andric   Classes = CMF.remove(Classes, Old);
262181ad6265SDimitry Andric   State = State->set<ClassMap>(Classes);
262281ad6265SDimitry Andric 
2623349cc55cSDimitry Andric   return State;
2624349cc55cSDimitry Andric }
2625349cc55cSDimitry Andric 
2626349cc55cSDimitry Andric // Re-evaluate an SVal with top-level `State->assume` logic.
2627bdd1243dSDimitry Andric [[nodiscard]] ProgramStateRef
2628bdd1243dSDimitry Andric reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue) {
2629349cc55cSDimitry Andric   if (!Constraint)
2630349cc55cSDimitry Andric     return State;
2631349cc55cSDimitry Andric 
2632349cc55cSDimitry Andric   const auto DefinedVal = TheValue.castAs<DefinedSVal>();
2633349cc55cSDimitry Andric 
2634349cc55cSDimitry Andric   // If the SVal is 0, we can simply interpret that as `false`.
2635349cc55cSDimitry Andric   if (Constraint->encodesFalseRange())
2636349cc55cSDimitry Andric     return State->assume(DefinedVal, false);
2637349cc55cSDimitry Andric 
2638349cc55cSDimitry Andric   // If the constraint does not encode 0 then we can interpret that as `true`
2639349cc55cSDimitry Andric   // AND as a Range(Set).
2640349cc55cSDimitry Andric   if (Constraint->encodesTrueRange()) {
2641349cc55cSDimitry Andric     State = State->assume(DefinedVal, true);
2642349cc55cSDimitry Andric     if (!State)
2643349cc55cSDimitry Andric       return nullptr;
2644349cc55cSDimitry Andric     // Fall through, re-assume based on the range values as well.
2645349cc55cSDimitry Andric   }
2646349cc55cSDimitry Andric   // Overestimate the individual Ranges with the RangeSet' lowest and
2647349cc55cSDimitry Andric   // highest values.
2648349cc55cSDimitry Andric   return State->assumeInclusiveRange(DefinedVal, Constraint->getMinValue(),
2649349cc55cSDimitry Andric                                      Constraint->getMaxValue(), true);
2650349cc55cSDimitry Andric }
2651349cc55cSDimitry Andric 
2652fe6060f1SDimitry Andric // Iterate over all symbols and try to simplify them. Once a symbol is
2653fe6060f1SDimitry Andric // simplified then we check if we can merge the simplified symbol's equivalence
2654fe6060f1SDimitry Andric // class to this class. This way, we simplify not just the symbols but the
2655fe6060f1SDimitry Andric // classes as well: we strive to keep the number of the classes to be the
2656fe6060f1SDimitry Andric // absolute minimum.
2657bdd1243dSDimitry Andric [[nodiscard]] ProgramStateRef
2658fe6060f1SDimitry Andric EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
2659fe6060f1SDimitry Andric                            ProgramStateRef State, EquivalenceClass Class) {
2660fe6060f1SDimitry Andric   SymbolSet ClassMembers = Class.getClassMembers(State);
2661fe6060f1SDimitry Andric   for (const SymbolRef &MemberSym : ClassMembers) {
2662349cc55cSDimitry Andric 
26630eae32dcSDimitry Andric     const SVal SimplifiedMemberVal = simplifyToSVal(State, MemberSym);
2664349cc55cSDimitry Andric     const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol();
2665349cc55cSDimitry Andric 
2666349cc55cSDimitry Andric     // The symbol is collapsed to a constant, check if the current State is
2667349cc55cSDimitry Andric     // still feasible.
2668349cc55cSDimitry Andric     if (const auto CI = SimplifiedMemberVal.getAs<nonloc::ConcreteInt>()) {
2669349cc55cSDimitry Andric       const llvm::APSInt &SV = CI->getValue();
2670349cc55cSDimitry Andric       const RangeSet *ClassConstraint = getConstraint(State, Class);
2671349cc55cSDimitry Andric       // We have found a contradiction.
2672349cc55cSDimitry Andric       if (ClassConstraint && !ClassConstraint->contains(SV))
2673349cc55cSDimitry Andric         return nullptr;
2674349cc55cSDimitry Andric     }
2675349cc55cSDimitry Andric 
2676fe6060f1SDimitry Andric     if (SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
2677fe6060f1SDimitry Andric       // The simplified symbol should be the member of the original Class,
2678fe6060f1SDimitry Andric       // however, it might be in another existing class at the moment. We
2679fe6060f1SDimitry Andric       // have to merge these classes.
2680349cc55cSDimitry Andric       ProgramStateRef OldState = State;
2681fe6060f1SDimitry Andric       State = merge(F, State, MemberSym, SimplifiedMemberSym);
2682fe6060f1SDimitry Andric       if (!State)
2683fe6060f1SDimitry Andric         return nullptr;
2684349cc55cSDimitry Andric       // No state change, no merge happened actually.
2685349cc55cSDimitry Andric       if (OldState == State)
2686349cc55cSDimitry Andric         continue;
2687349cc55cSDimitry Andric 
26881ac55f4cSDimitry Andric       // Be aware that `SimplifiedMemberSym` might refer to an already dead
26891ac55f4cSDimitry Andric       // symbol. In that case, the eqclass of that might not be the same as the
26901ac55f4cSDimitry Andric       // eqclass of `MemberSym`. This is because the dead symbols are not
26911ac55f4cSDimitry Andric       // preserved in the `ClassMap`, hence
26921ac55f4cSDimitry Andric       // `find(State, SimplifiedMemberSym)` will result in a trivial eqclass
26931ac55f4cSDimitry Andric       // compared to the eqclass of `MemberSym`.
26941ac55f4cSDimitry Andric       // These eqclasses should be the same if `SimplifiedMemberSym` is alive.
26951ac55f4cSDimitry Andric       // --> assert(find(State, MemberSym) == find(State, SimplifiedMemberSym))
26961ac55f4cSDimitry Andric       //
26971ac55f4cSDimitry Andric       // Note that `MemberSym` must be alive here since that is from the
26981ac55f4cSDimitry Andric       // `ClassMembers` where all the symbols are alive.
26991ac55f4cSDimitry Andric 
2700349cc55cSDimitry Andric       // Remove the old and more complex symbol.
2701349cc55cSDimitry Andric       State = find(State, MemberSym).removeMember(State, MemberSym);
2702349cc55cSDimitry Andric 
2703349cc55cSDimitry Andric       // Query the class constraint again b/c that may have changed during the
2704349cc55cSDimitry Andric       // merge above.
2705349cc55cSDimitry Andric       const RangeSet *ClassConstraint = getConstraint(State, Class);
2706349cc55cSDimitry Andric 
2707349cc55cSDimitry Andric       // Re-evaluate an SVal with top-level `State->assume`, this ignites
2708349cc55cSDimitry Andric       // a RECURSIVE algorithm that will reach a FIXPOINT.
2709349cc55cSDimitry Andric       //
2710349cc55cSDimitry Andric       // About performance and complexity: Let us assume that in a State we
2711349cc55cSDimitry Andric       // have N non-trivial equivalence classes and that all constraints and
2712349cc55cSDimitry Andric       // disequality info is related to non-trivial classes. In the worst case,
2713349cc55cSDimitry Andric       // we can simplify only one symbol of one class in each iteration. The
2714349cc55cSDimitry Andric       // number of symbols in one class cannot grow b/c we replace the old
2715349cc55cSDimitry Andric       // symbol with the simplified one. Also, the number of the equivalence
2716349cc55cSDimitry Andric       // classes can decrease only, b/c the algorithm does a merge operation
2717349cc55cSDimitry Andric       // optionally. We need N iterations in this case to reach the fixpoint.
2718349cc55cSDimitry Andric       // Thus, the steps needed to be done in the worst case is proportional to
2719349cc55cSDimitry Andric       // N*N.
2720349cc55cSDimitry Andric       //
2721349cc55cSDimitry Andric       // This worst case scenario can be extended to that case when we have
2722349cc55cSDimitry Andric       // trivial classes in the constraints and in the disequality map. This
2723349cc55cSDimitry Andric       // case can be reduced to the case with a State where there are only
2724349cc55cSDimitry Andric       // non-trivial classes. This is because a merge operation on two trivial
2725349cc55cSDimitry Andric       // classes results in one non-trivial class.
2726349cc55cSDimitry Andric       State = reAssume(State, ClassConstraint, SimplifiedMemberVal);
2727349cc55cSDimitry Andric       if (!State)
2728349cc55cSDimitry Andric         return nullptr;
2729fe6060f1SDimitry Andric     }
2730fe6060f1SDimitry Andric   }
2731fe6060f1SDimitry Andric   return State;
2732fe6060f1SDimitry Andric }
2733fe6060f1SDimitry Andric 
2734e8d8bef9SDimitry Andric inline ClassSet EquivalenceClass::getDisequalClasses(ProgramStateRef State,
2735e8d8bef9SDimitry Andric                                                      SymbolRef Sym) {
2736e8d8bef9SDimitry Andric   return find(State, Sym).getDisequalClasses(State);
2737e8d8bef9SDimitry Andric }
2738e8d8bef9SDimitry Andric 
2739e8d8bef9SDimitry Andric inline ClassSet
2740e8d8bef9SDimitry Andric EquivalenceClass::getDisequalClasses(ProgramStateRef State) const {
2741e8d8bef9SDimitry Andric   return getDisequalClasses(State->get<DisequalityMap>(),
2742e8d8bef9SDimitry Andric                             State->get_context<ClassSet>());
2743e8d8bef9SDimitry Andric }
2744e8d8bef9SDimitry Andric 
2745e8d8bef9SDimitry Andric inline ClassSet
2746e8d8bef9SDimitry Andric EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2747e8d8bef9SDimitry Andric                                      ClassSet::Factory &Factory) const {
2748e8d8bef9SDimitry Andric   if (const ClassSet *DisequalClasses = Map.lookup(*this))
2749e8d8bef9SDimitry Andric     return *DisequalClasses;
2750e8d8bef9SDimitry Andric 
2751e8d8bef9SDimitry Andric   return Factory.getEmptySet();
2752e8d8bef9SDimitry Andric }
2753e8d8bef9SDimitry Andric 
2754e8d8bef9SDimitry Andric bool EquivalenceClass::isClassDataConsistent(ProgramStateRef State) {
2755e8d8bef9SDimitry Andric   ClassMembersTy Members = State->get<ClassMembers>();
2756e8d8bef9SDimitry Andric 
2757e8d8bef9SDimitry Andric   for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2758e8d8bef9SDimitry Andric     for (SymbolRef Member : ClassMembersPair.second) {
2759e8d8bef9SDimitry Andric       // Every member of the class should have a mapping back to the class.
2760e8d8bef9SDimitry Andric       if (find(State, Member) == ClassMembersPair.first) {
2761e8d8bef9SDimitry Andric         continue;
2762e8d8bef9SDimitry Andric       }
2763e8d8bef9SDimitry Andric 
2764e8d8bef9SDimitry Andric       return false;
2765e8d8bef9SDimitry Andric     }
2766e8d8bef9SDimitry Andric   }
2767e8d8bef9SDimitry Andric 
2768e8d8bef9SDimitry Andric   DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2769e8d8bef9SDimitry Andric   for (std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2770e8d8bef9SDimitry Andric     EquivalenceClass Class = DisequalityInfo.first;
2771e8d8bef9SDimitry Andric     ClassSet DisequalClasses = DisequalityInfo.second;
2772e8d8bef9SDimitry Andric 
2773e8d8bef9SDimitry Andric     // There is no use in keeping empty sets in the map.
2774e8d8bef9SDimitry Andric     if (DisequalClasses.isEmpty())
2775e8d8bef9SDimitry Andric       return false;
2776e8d8bef9SDimitry Andric 
2777e8d8bef9SDimitry Andric     // Disequality is symmetrical, i.e. for every Class A and B that A != B,
2778e8d8bef9SDimitry Andric     // B != A should also be true.
2779e8d8bef9SDimitry Andric     for (EquivalenceClass DisequalClass : DisequalClasses) {
2780e8d8bef9SDimitry Andric       const ClassSet *DisequalToDisequalClasses =
2781e8d8bef9SDimitry Andric           Disequalities.lookup(DisequalClass);
2782e8d8bef9SDimitry Andric 
2783e8d8bef9SDimitry Andric       // It should be a set of at least one element: Class
2784e8d8bef9SDimitry Andric       if (!DisequalToDisequalClasses ||
2785e8d8bef9SDimitry Andric           !DisequalToDisequalClasses->contains(Class))
2786e8d8bef9SDimitry Andric         return false;
2787e8d8bef9SDimitry Andric     }
2788e8d8bef9SDimitry Andric   }
2789e8d8bef9SDimitry Andric 
2790e8d8bef9SDimitry Andric   return true;
2791e8d8bef9SDimitry Andric }
2792e8d8bef9SDimitry Andric 
2793e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2794e8d8bef9SDimitry Andric //                    RangeConstraintManager implementation
2795e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2796e8d8bef9SDimitry Andric 
27970b57cec5SDimitry Andric bool RangeConstraintManager::canReasonAbout(SVal X) const {
2798bdd1243dSDimitry Andric   std::optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
27990b57cec5SDimitry Andric   if (SymVal && SymVal->isExpression()) {
28000b57cec5SDimitry Andric     const SymExpr *SE = SymVal->getSymbol();
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric     if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
28030b57cec5SDimitry Andric       switch (SIE->getOpcode()) {
28040b57cec5SDimitry Andric       // We don't reason yet about bitwise-constraints on symbolic values.
28050b57cec5SDimitry Andric       case BO_And:
28060b57cec5SDimitry Andric       case BO_Or:
28070b57cec5SDimitry Andric       case BO_Xor:
28080b57cec5SDimitry Andric         return false;
28090b57cec5SDimitry Andric       // We don't reason yet about these arithmetic constraints on
28100b57cec5SDimitry Andric       // symbolic values.
28110b57cec5SDimitry Andric       case BO_Mul:
28120b57cec5SDimitry Andric       case BO_Div:
28130b57cec5SDimitry Andric       case BO_Rem:
28140b57cec5SDimitry Andric       case BO_Shl:
28150b57cec5SDimitry Andric       case BO_Shr:
28160b57cec5SDimitry Andric         return false;
28170b57cec5SDimitry Andric       // All other cases.
28180b57cec5SDimitry Andric       default:
28190b57cec5SDimitry Andric         return true;
28200b57cec5SDimitry Andric       }
28210b57cec5SDimitry Andric     }
28220b57cec5SDimitry Andric 
28230b57cec5SDimitry Andric     if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
28240b57cec5SDimitry Andric       // FIXME: Handle <=> here.
28250b57cec5SDimitry Andric       if (BinaryOperator::isEqualityOp(SSE->getOpcode()) ||
28260b57cec5SDimitry Andric           BinaryOperator::isRelationalOp(SSE->getOpcode())) {
28270b57cec5SDimitry Andric         // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
28280b57cec5SDimitry Andric         // We've recently started producing Loc <> NonLoc comparisons (that
28290b57cec5SDimitry Andric         // result from casts of one of the operands between eg. intptr_t and
28300b57cec5SDimitry Andric         // void *), but we can't reason about them yet.
28310b57cec5SDimitry Andric         if (Loc::isLocType(SSE->getLHS()->getType())) {
28320b57cec5SDimitry Andric           return Loc::isLocType(SSE->getRHS()->getType());
28330b57cec5SDimitry Andric         }
28340b57cec5SDimitry Andric       }
28350b57cec5SDimitry Andric     }
28360b57cec5SDimitry Andric 
28370b57cec5SDimitry Andric     return false;
28380b57cec5SDimitry Andric   }
28390b57cec5SDimitry Andric 
28400b57cec5SDimitry Andric   return true;
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
28440b57cec5SDimitry Andric                                                     SymbolRef Sym) {
2845e8d8bef9SDimitry Andric   const RangeSet *Ranges = getConstraint(State, Sym);
28460b57cec5SDimitry Andric 
28470b57cec5SDimitry Andric   // If we don't have any information about this symbol, it's underconstrained.
28480b57cec5SDimitry Andric   if (!Ranges)
28490b57cec5SDimitry Andric     return ConditionTruthVal();
28500b57cec5SDimitry Andric 
28510b57cec5SDimitry Andric   // If we have a concrete value, see if it's zero.
28520b57cec5SDimitry Andric   if (const llvm::APSInt *Value = Ranges->getConcreteValue())
28530b57cec5SDimitry Andric     return *Value == 0;
28540b57cec5SDimitry Andric 
28550b57cec5SDimitry Andric   BasicValueFactory &BV = getBasicVals();
28560b57cec5SDimitry Andric   APSIntType IntType = BV.getAPSIntType(Sym->getType());
28570b57cec5SDimitry Andric   llvm::APSInt Zero = IntType.getZeroValue();
28580b57cec5SDimitry Andric 
28590b57cec5SDimitry Andric   // Check if zero is in the set of possible values.
2860fe6060f1SDimitry Andric   if (!Ranges->contains(Zero))
28610b57cec5SDimitry Andric     return false;
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric   // Zero is a possible value, but it is not the /only/ possible value.
28640b57cec5SDimitry Andric   return ConditionTruthVal();
28650b57cec5SDimitry Andric }
28660b57cec5SDimitry Andric 
28670b57cec5SDimitry Andric const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St,
28680b57cec5SDimitry Andric                                                       SymbolRef Sym) const {
2869e8d8bef9SDimitry Andric   const RangeSet *T = getConstraint(St, Sym);
28700b57cec5SDimitry Andric   return T ? T->getConcreteValue() : nullptr;
28710b57cec5SDimitry Andric }
28720b57cec5SDimitry Andric 
28735f757f3fSDimitry Andric const llvm::APSInt *RangeConstraintManager::getSymMinVal(ProgramStateRef St,
28745f757f3fSDimitry Andric                                                          SymbolRef Sym) const {
28755f757f3fSDimitry Andric   const RangeSet *T = getConstraint(St, Sym);
28765f757f3fSDimitry Andric   if (!T || T->isEmpty())
28775f757f3fSDimitry Andric     return nullptr;
28785f757f3fSDimitry Andric   return &T->getMinValue();
28795f757f3fSDimitry Andric }
28805f757f3fSDimitry Andric 
28815f757f3fSDimitry Andric const llvm::APSInt *RangeConstraintManager::getSymMaxVal(ProgramStateRef St,
28825f757f3fSDimitry Andric                                                          SymbolRef Sym) const {
28835f757f3fSDimitry Andric   const RangeSet *T = getConstraint(St, Sym);
28845f757f3fSDimitry Andric   if (!T || T->isEmpty())
28855f757f3fSDimitry Andric     return nullptr;
28865f757f3fSDimitry Andric   return &T->getMaxValue();
28875f757f3fSDimitry Andric }
28885f757f3fSDimitry Andric 
2889e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2890e8d8bef9SDimitry Andric //                Remove dead symbols from existing constraints
2891e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
2892e8d8bef9SDimitry Andric 
28930b57cec5SDimitry Andric /// Scan all symbols referenced by the constraints. If the symbol is not alive
28940b57cec5SDimitry Andric /// as marked in LSymbols, mark it as dead in DSymbols.
28950b57cec5SDimitry Andric ProgramStateRef
28960b57cec5SDimitry Andric RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
28970b57cec5SDimitry Andric                                            SymbolReaper &SymReaper) {
2898e8d8bef9SDimitry Andric   ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2899e8d8bef9SDimitry Andric   ClassMembersTy NewClassMembersMap = ClassMembersMap;
2900e8d8bef9SDimitry Andric   ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2901e8d8bef9SDimitry Andric   SymbolSet::Factory &SetFactory = State->get_context<SymbolSet>();
29020b57cec5SDimitry Andric 
2903e8d8bef9SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2904e8d8bef9SDimitry Andric   ConstraintRangeTy NewConstraints = Constraints;
2905e8d8bef9SDimitry Andric   ConstraintRangeTy::Factory &ConstraintFactory =
2906e8d8bef9SDimitry Andric       State->get_context<ConstraintRange>();
2907e8d8bef9SDimitry Andric 
2908e8d8bef9SDimitry Andric   ClassMapTy Map = State->get<ClassMap>();
2909e8d8bef9SDimitry Andric   ClassMapTy NewMap = Map;
2910e8d8bef9SDimitry Andric   ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2911e8d8bef9SDimitry Andric 
2912e8d8bef9SDimitry Andric   DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2913e8d8bef9SDimitry Andric   DisequalityMapTy::Factory &DisequalityFactory =
2914e8d8bef9SDimitry Andric       State->get_context<DisequalityMap>();
2915e8d8bef9SDimitry Andric   ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
2916e8d8bef9SDimitry Andric 
2917e8d8bef9SDimitry Andric   bool ClassMapChanged = false;
2918e8d8bef9SDimitry Andric   bool MembersMapChanged = false;
2919e8d8bef9SDimitry Andric   bool ConstraintMapChanged = false;
2920e8d8bef9SDimitry Andric   bool DisequalitiesChanged = false;
2921e8d8bef9SDimitry Andric 
2922e8d8bef9SDimitry Andric   auto removeDeadClass = [&](EquivalenceClass Class) {
2923e8d8bef9SDimitry Andric     // Remove associated constraint ranges.
2924e8d8bef9SDimitry Andric     Constraints = ConstraintFactory.remove(Constraints, Class);
2925e8d8bef9SDimitry Andric     ConstraintMapChanged = true;
2926e8d8bef9SDimitry Andric 
2927e8d8bef9SDimitry Andric     // Update disequality information to not hold any information on the
2928e8d8bef9SDimitry Andric     // removed class.
2929e8d8bef9SDimitry Andric     ClassSet DisequalClasses =
2930e8d8bef9SDimitry Andric         Class.getDisequalClasses(Disequalities, ClassSetFactory);
2931e8d8bef9SDimitry Andric     if (!DisequalClasses.isEmpty()) {
2932e8d8bef9SDimitry Andric       for (EquivalenceClass DisequalClass : DisequalClasses) {
2933e8d8bef9SDimitry Andric         ClassSet DisequalToDisequalSet =
2934e8d8bef9SDimitry Andric             DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
2935e8d8bef9SDimitry Andric         // DisequalToDisequalSet is guaranteed to be non-empty for consistent
2936e8d8bef9SDimitry Andric         // disequality info.
2937e8d8bef9SDimitry Andric         assert(!DisequalToDisequalSet.isEmpty());
2938e8d8bef9SDimitry Andric         ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet, Class);
2939e8d8bef9SDimitry Andric 
2940e8d8bef9SDimitry Andric         // No need in keeping an empty set.
2941e8d8bef9SDimitry Andric         if (NewSet.isEmpty()) {
2942e8d8bef9SDimitry Andric           Disequalities =
2943e8d8bef9SDimitry Andric               DisequalityFactory.remove(Disequalities, DisequalClass);
2944e8d8bef9SDimitry Andric         } else {
2945e8d8bef9SDimitry Andric           Disequalities =
2946e8d8bef9SDimitry Andric               DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
2947e8d8bef9SDimitry Andric         }
2948e8d8bef9SDimitry Andric       }
2949e8d8bef9SDimitry Andric       // Remove the data for the class
2950e8d8bef9SDimitry Andric       Disequalities = DisequalityFactory.remove(Disequalities, Class);
2951e8d8bef9SDimitry Andric       DisequalitiesChanged = true;
2952e8d8bef9SDimitry Andric     }
2953e8d8bef9SDimitry Andric   };
2954e8d8bef9SDimitry Andric 
2955e8d8bef9SDimitry Andric   // 1. Let's see if dead symbols are trivial and have associated constraints.
2956e8d8bef9SDimitry Andric   for (std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
2957e8d8bef9SDimitry Andric        Constraints) {
2958e8d8bef9SDimitry Andric     EquivalenceClass Class = ClassConstraintPair.first;
2959e8d8bef9SDimitry Andric     if (Class.isTriviallyDead(State, SymReaper)) {
2960e8d8bef9SDimitry Andric       // If this class is trivial, we can remove its constraints right away.
2961e8d8bef9SDimitry Andric       removeDeadClass(Class);
2962e8d8bef9SDimitry Andric     }
2963e8d8bef9SDimitry Andric   }
2964e8d8bef9SDimitry Andric 
2965e8d8bef9SDimitry Andric   // 2. We don't need to track classes for dead symbols.
2966e8d8bef9SDimitry Andric   for (std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
2967e8d8bef9SDimitry Andric     SymbolRef Sym = SymbolClassPair.first;
2968e8d8bef9SDimitry Andric 
29690b57cec5SDimitry Andric     if (SymReaper.isDead(Sym)) {
2970e8d8bef9SDimitry Andric       ClassMapChanged = true;
2971e8d8bef9SDimitry Andric       NewMap = ClassFactory.remove(NewMap, Sym);
29720b57cec5SDimitry Andric     }
29730b57cec5SDimitry Andric   }
29740b57cec5SDimitry Andric 
2975e8d8bef9SDimitry Andric   // 3. Remove dead members from classes and remove dead non-trivial classes
2976e8d8bef9SDimitry Andric   //    and their constraints.
2977e8d8bef9SDimitry Andric   for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
2978e8d8bef9SDimitry Andric        ClassMembersMap) {
2979e8d8bef9SDimitry Andric     EquivalenceClass Class = ClassMembersPair.first;
2980e8d8bef9SDimitry Andric     SymbolSet LiveMembers = ClassMembersPair.second;
2981e8d8bef9SDimitry Andric     bool MembersChanged = false;
2982e8d8bef9SDimitry Andric 
2983e8d8bef9SDimitry Andric     for (SymbolRef Member : ClassMembersPair.second) {
2984e8d8bef9SDimitry Andric       if (SymReaper.isDead(Member)) {
2985e8d8bef9SDimitry Andric         MembersChanged = true;
2986e8d8bef9SDimitry Andric         LiveMembers = SetFactory.remove(LiveMembers, Member);
2987e8d8bef9SDimitry Andric       }
2988e8d8bef9SDimitry Andric     }
2989e8d8bef9SDimitry Andric 
2990e8d8bef9SDimitry Andric     // Check if the class changed.
2991e8d8bef9SDimitry Andric     if (!MembersChanged)
2992e8d8bef9SDimitry Andric       continue;
2993e8d8bef9SDimitry Andric 
2994e8d8bef9SDimitry Andric     MembersMapChanged = true;
2995e8d8bef9SDimitry Andric 
2996e8d8bef9SDimitry Andric     if (LiveMembers.isEmpty()) {
2997e8d8bef9SDimitry Andric       // The class is dead now, we need to wipe it out of the members map...
2998e8d8bef9SDimitry Andric       NewClassMembersMap = EMFactory.remove(NewClassMembersMap, Class);
2999e8d8bef9SDimitry Andric 
3000e8d8bef9SDimitry Andric       // ...and remove all of its constraints.
3001e8d8bef9SDimitry Andric       removeDeadClass(Class);
3002e8d8bef9SDimitry Andric     } else {
3003e8d8bef9SDimitry Andric       // We need to change the members associated with the class.
3004e8d8bef9SDimitry Andric       NewClassMembersMap =
3005e8d8bef9SDimitry Andric           EMFactory.add(NewClassMembersMap, Class, LiveMembers);
3006e8d8bef9SDimitry Andric     }
3007e8d8bef9SDimitry Andric   }
3008e8d8bef9SDimitry Andric 
3009e8d8bef9SDimitry Andric   // 4. Update the state with new maps.
3010e8d8bef9SDimitry Andric   //
3011e8d8bef9SDimitry Andric   // Here we try to be humble and update a map only if it really changed.
3012e8d8bef9SDimitry Andric   if (ClassMapChanged)
3013e8d8bef9SDimitry Andric     State = State->set<ClassMap>(NewMap);
3014e8d8bef9SDimitry Andric 
3015e8d8bef9SDimitry Andric   if (MembersMapChanged)
3016e8d8bef9SDimitry Andric     State = State->set<ClassMembers>(NewClassMembersMap);
3017e8d8bef9SDimitry Andric 
3018e8d8bef9SDimitry Andric   if (ConstraintMapChanged)
3019e8d8bef9SDimitry Andric     State = State->set<ConstraintRange>(Constraints);
3020e8d8bef9SDimitry Andric 
3021e8d8bef9SDimitry Andric   if (DisequalitiesChanged)
3022e8d8bef9SDimitry Andric     State = State->set<DisequalityMap>(Disequalities);
3023e8d8bef9SDimitry Andric 
3024e8d8bef9SDimitry Andric   assert(EquivalenceClass::isClassDataConsistent(State));
3025e8d8bef9SDimitry Andric 
3026e8d8bef9SDimitry Andric   return State;
30270b57cec5SDimitry Andric }
30280b57cec5SDimitry Andric 
30290b57cec5SDimitry Andric RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
30300b57cec5SDimitry Andric                                           SymbolRef Sym) {
3031fe6060f1SDimitry Andric   return SymbolicRangeInferrer::inferRange(F, State, Sym);
30320b57cec5SDimitry Andric }
30330b57cec5SDimitry Andric 
3034fe6060f1SDimitry Andric ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State,
3035fe6060f1SDimitry Andric                                                  SymbolRef Sym,
3036fe6060f1SDimitry Andric                                                  RangeSet Range) {
3037fe6060f1SDimitry Andric   return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range);
3038e8d8bef9SDimitry Andric }
3039e8d8bef9SDimitry Andric 
30400b57cec5SDimitry Andric //===------------------------------------------------------------------------===
30410b57cec5SDimitry Andric // assumeSymX methods: protected interface for RangeConstraintManager.
3042*0fca6ea1SDimitry Andric //===------------------------------------------------------------------------===
30430b57cec5SDimitry Andric 
30440b57cec5SDimitry Andric // The syntax for ranges below is mathematical, using [x, y] for closed ranges
30450b57cec5SDimitry Andric // and (x, y) for open ranges. These ranges are modular, corresponding with
30460b57cec5SDimitry Andric // a common treatment of C integer overflow. This means that these methods
30470b57cec5SDimitry Andric // do not have to worry about overflow; RangeSet::Intersect can handle such a
30480b57cec5SDimitry Andric // "wraparound" range.
30490b57cec5SDimitry Andric // As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
30500b57cec5SDimitry Andric // UINT_MAX, 0, 1, and 2.
30510b57cec5SDimitry Andric 
30520b57cec5SDimitry Andric ProgramStateRef
30530b57cec5SDimitry Andric RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
30540b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
30550b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
30560b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
30570b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
30580b57cec5SDimitry Andric   if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
30590b57cec5SDimitry Andric     return St;
30600b57cec5SDimitry Andric 
3061e8d8bef9SDimitry Andric   llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3062fe6060f1SDimitry Andric   RangeSet New = getRange(St, Sym);
3063fe6060f1SDimitry Andric   New = F.deletePoint(New, Point);
30640b57cec5SDimitry Andric 
3065fe6060f1SDimitry Andric   return setRange(St, Sym, New);
30660b57cec5SDimitry Andric }
30670b57cec5SDimitry Andric 
30680b57cec5SDimitry Andric ProgramStateRef
30690b57cec5SDimitry Andric RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
30700b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
30710b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
30720b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
30730b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
30740b57cec5SDimitry Andric   if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
30750b57cec5SDimitry Andric     return nullptr;
30760b57cec5SDimitry Andric 
30770b57cec5SDimitry Andric   // [Int-Adjustment, Int-Adjustment]
30780b57cec5SDimitry Andric   llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3079fe6060f1SDimitry Andric   RangeSet New = getRange(St, Sym);
3080fe6060f1SDimitry Andric   New = F.intersect(New, AdjInt);
3081e8d8bef9SDimitry Andric 
3082fe6060f1SDimitry Andric   return setRange(St, Sym, New);
30830b57cec5SDimitry Andric }
30840b57cec5SDimitry Andric 
30850b57cec5SDimitry Andric RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
30860b57cec5SDimitry Andric                                                SymbolRef Sym,
30870b57cec5SDimitry Andric                                                const llvm::APSInt &Int,
30880b57cec5SDimitry Andric                                                const llvm::APSInt &Adjustment) {
30890b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
30900b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
30910b57cec5SDimitry Andric   switch (AdjustmentType.testInRange(Int, true)) {
30920b57cec5SDimitry Andric   case APSIntType::RTR_Below:
30930b57cec5SDimitry Andric     return F.getEmptySet();
30940b57cec5SDimitry Andric   case APSIntType::RTR_Within:
30950b57cec5SDimitry Andric     break;
30960b57cec5SDimitry Andric   case APSIntType::RTR_Above:
30970b57cec5SDimitry Andric     return getRange(St, Sym);
30980b57cec5SDimitry Andric   }
30990b57cec5SDimitry Andric 
31000b57cec5SDimitry Andric   // Special case for Int == Min. This is always false.
31010b57cec5SDimitry Andric   llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
31020b57cec5SDimitry Andric   llvm::APSInt Min = AdjustmentType.getMinValue();
31030b57cec5SDimitry Andric   if (ComparisonVal == Min)
31040b57cec5SDimitry Andric     return F.getEmptySet();
31050b57cec5SDimitry Andric 
31060b57cec5SDimitry Andric   llvm::APSInt Lower = Min - Adjustment;
31070b57cec5SDimitry Andric   llvm::APSInt Upper = ComparisonVal - Adjustment;
31080b57cec5SDimitry Andric   --Upper;
31090b57cec5SDimitry Andric 
3110fe6060f1SDimitry Andric   RangeSet Result = getRange(St, Sym);
3111fe6060f1SDimitry Andric   return F.intersect(Result, Lower, Upper);
31120b57cec5SDimitry Andric }
31130b57cec5SDimitry Andric 
31140b57cec5SDimitry Andric ProgramStateRef
31150b57cec5SDimitry Andric RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
31160b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
31170b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
31180b57cec5SDimitry Andric   RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
3119fe6060f1SDimitry Andric   return setRange(St, Sym, New);
31200b57cec5SDimitry Andric }
31210b57cec5SDimitry Andric 
31220b57cec5SDimitry Andric RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St,
31230b57cec5SDimitry Andric                                                SymbolRef Sym,
31240b57cec5SDimitry Andric                                                const llvm::APSInt &Int,
31250b57cec5SDimitry Andric                                                const llvm::APSInt &Adjustment) {
31260b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
31270b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
31280b57cec5SDimitry Andric   switch (AdjustmentType.testInRange(Int, true)) {
31290b57cec5SDimitry Andric   case APSIntType::RTR_Below:
31300b57cec5SDimitry Andric     return getRange(St, Sym);
31310b57cec5SDimitry Andric   case APSIntType::RTR_Within:
31320b57cec5SDimitry Andric     break;
31330b57cec5SDimitry Andric   case APSIntType::RTR_Above:
31340b57cec5SDimitry Andric     return F.getEmptySet();
31350b57cec5SDimitry Andric   }
31360b57cec5SDimitry Andric 
31370b57cec5SDimitry Andric   // Special case for Int == Max. This is always false.
31380b57cec5SDimitry Andric   llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
31390b57cec5SDimitry Andric   llvm::APSInt Max = AdjustmentType.getMaxValue();
31400b57cec5SDimitry Andric   if (ComparisonVal == Max)
31410b57cec5SDimitry Andric     return F.getEmptySet();
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric   llvm::APSInt Lower = ComparisonVal - Adjustment;
31440b57cec5SDimitry Andric   llvm::APSInt Upper = Max - Adjustment;
31450b57cec5SDimitry Andric   ++Lower;
31460b57cec5SDimitry Andric 
3147fe6060f1SDimitry Andric   RangeSet SymRange = getRange(St, Sym);
3148fe6060f1SDimitry Andric   return F.intersect(SymRange, Lower, Upper);
31490b57cec5SDimitry Andric }
31500b57cec5SDimitry Andric 
31510b57cec5SDimitry Andric ProgramStateRef
31520b57cec5SDimitry Andric RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
31530b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
31540b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
31550b57cec5SDimitry Andric   RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
3156fe6060f1SDimitry Andric   return setRange(St, Sym, New);
31570b57cec5SDimitry Andric }
31580b57cec5SDimitry Andric 
31590b57cec5SDimitry Andric RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St,
31600b57cec5SDimitry Andric                                                SymbolRef Sym,
31610b57cec5SDimitry Andric                                                const llvm::APSInt &Int,
31620b57cec5SDimitry Andric                                                const llvm::APSInt &Adjustment) {
31630b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
31640b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
31650b57cec5SDimitry Andric   switch (AdjustmentType.testInRange(Int, true)) {
31660b57cec5SDimitry Andric   case APSIntType::RTR_Below:
31670b57cec5SDimitry Andric     return getRange(St, Sym);
31680b57cec5SDimitry Andric   case APSIntType::RTR_Within:
31690b57cec5SDimitry Andric     break;
31700b57cec5SDimitry Andric   case APSIntType::RTR_Above:
31710b57cec5SDimitry Andric     return F.getEmptySet();
31720b57cec5SDimitry Andric   }
31730b57cec5SDimitry Andric 
31740b57cec5SDimitry Andric   // Special case for Int == Min. This is always feasible.
31750b57cec5SDimitry Andric   llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
31760b57cec5SDimitry Andric   llvm::APSInt Min = AdjustmentType.getMinValue();
31770b57cec5SDimitry Andric   if (ComparisonVal == Min)
31780b57cec5SDimitry Andric     return getRange(St, Sym);
31790b57cec5SDimitry Andric 
31800b57cec5SDimitry Andric   llvm::APSInt Max = AdjustmentType.getMaxValue();
31810b57cec5SDimitry Andric   llvm::APSInt Lower = ComparisonVal - Adjustment;
31820b57cec5SDimitry Andric   llvm::APSInt Upper = Max - Adjustment;
31830b57cec5SDimitry Andric 
3184fe6060f1SDimitry Andric   RangeSet SymRange = getRange(St, Sym);
3185fe6060f1SDimitry Andric   return F.intersect(SymRange, Lower, Upper);
31860b57cec5SDimitry Andric }
31870b57cec5SDimitry Andric 
31880b57cec5SDimitry Andric ProgramStateRef
31890b57cec5SDimitry Andric RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
31900b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
31910b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
31920b57cec5SDimitry Andric   RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
3193fe6060f1SDimitry Andric   return setRange(St, Sym, New);
31940b57cec5SDimitry Andric }
31950b57cec5SDimitry Andric 
3196e8d8bef9SDimitry Andric RangeSet
3197e8d8bef9SDimitry Andric RangeConstraintManager::getSymLERange(llvm::function_ref<RangeSet()> RS,
31980b57cec5SDimitry Andric                                       const llvm::APSInt &Int,
31990b57cec5SDimitry Andric                                       const llvm::APSInt &Adjustment) {
32000b57cec5SDimitry Andric   // Before we do any real work, see if the value can even show up.
32010b57cec5SDimitry Andric   APSIntType AdjustmentType(Adjustment);
32020b57cec5SDimitry Andric   switch (AdjustmentType.testInRange(Int, true)) {
32030b57cec5SDimitry Andric   case APSIntType::RTR_Below:
32040b57cec5SDimitry Andric     return F.getEmptySet();
32050b57cec5SDimitry Andric   case APSIntType::RTR_Within:
32060b57cec5SDimitry Andric     break;
32070b57cec5SDimitry Andric   case APSIntType::RTR_Above:
32080b57cec5SDimitry Andric     return RS();
32090b57cec5SDimitry Andric   }
32100b57cec5SDimitry Andric 
32110b57cec5SDimitry Andric   // Special case for Int == Max. This is always feasible.
32120b57cec5SDimitry Andric   llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
32130b57cec5SDimitry Andric   llvm::APSInt Max = AdjustmentType.getMaxValue();
32140b57cec5SDimitry Andric   if (ComparisonVal == Max)
32150b57cec5SDimitry Andric     return RS();
32160b57cec5SDimitry Andric 
32170b57cec5SDimitry Andric   llvm::APSInt Min = AdjustmentType.getMinValue();
32180b57cec5SDimitry Andric   llvm::APSInt Lower = Min - Adjustment;
32190b57cec5SDimitry Andric   llvm::APSInt Upper = ComparisonVal - Adjustment;
32200b57cec5SDimitry Andric 
3221fe6060f1SDimitry Andric   RangeSet Default = RS();
3222fe6060f1SDimitry Andric   return F.intersect(Default, Lower, Upper);
32230b57cec5SDimitry Andric }
32240b57cec5SDimitry Andric 
32250b57cec5SDimitry Andric RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St,
32260b57cec5SDimitry Andric                                                SymbolRef Sym,
32270b57cec5SDimitry Andric                                                const llvm::APSInt &Int,
32280b57cec5SDimitry Andric                                                const llvm::APSInt &Adjustment) {
32290b57cec5SDimitry Andric   return getSymLERange([&] { return getRange(St, Sym); }, Int, Adjustment);
32300b57cec5SDimitry Andric }
32310b57cec5SDimitry Andric 
32320b57cec5SDimitry Andric ProgramStateRef
32330b57cec5SDimitry Andric RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
32340b57cec5SDimitry Andric                                     const llvm::APSInt &Int,
32350b57cec5SDimitry Andric                                     const llvm::APSInt &Adjustment) {
32360b57cec5SDimitry Andric   RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
3237fe6060f1SDimitry Andric   return setRange(St, Sym, New);
32380b57cec5SDimitry Andric }
32390b57cec5SDimitry Andric 
32400b57cec5SDimitry Andric ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange(
32410b57cec5SDimitry Andric     ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
32420b57cec5SDimitry Andric     const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
32430b57cec5SDimitry Andric   RangeSet New = getSymGERange(State, Sym, From, Adjustment);
32440b57cec5SDimitry Andric   if (New.isEmpty())
32450b57cec5SDimitry Andric     return nullptr;
32460b57cec5SDimitry Andric   RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment);
3247fe6060f1SDimitry Andric   return setRange(State, Sym, Out);
32480b57cec5SDimitry Andric }
32490b57cec5SDimitry Andric 
32500b57cec5SDimitry Andric ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
32510b57cec5SDimitry Andric     ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
32520b57cec5SDimitry Andric     const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
32530b57cec5SDimitry Andric   RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
32540b57cec5SDimitry Andric   RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
3255fe6060f1SDimitry Andric   RangeSet New(F.add(RangeLT, RangeGT));
3256fe6060f1SDimitry Andric   return setRange(State, Sym, New);
32570b57cec5SDimitry Andric }
32580b57cec5SDimitry Andric 
32590b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
32600b57cec5SDimitry Andric // Pretty-printing.
32610b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
32620b57cec5SDimitry Andric 
32630b57cec5SDimitry Andric void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
32640b57cec5SDimitry Andric                                        const char *NL, unsigned int Space,
32650b57cec5SDimitry Andric                                        bool IsDot) const {
3266fe6060f1SDimitry Andric   printConstraints(Out, State, NL, Space, IsDot);
3267fe6060f1SDimitry Andric   printEquivalenceClasses(Out, State, NL, Space, IsDot);
3268fe6060f1SDimitry Andric   printDisequalities(Out, State, NL, Space, IsDot);
3269fe6060f1SDimitry Andric }
3270fe6060f1SDimitry Andric 
3271fcaf7f86SDimitry Andric void RangeConstraintManager::printValue(raw_ostream &Out, ProgramStateRef State,
3272fcaf7f86SDimitry Andric                                         SymbolRef Sym) {
3273fcaf7f86SDimitry Andric   const RangeSet RS = getRange(State, Sym);
3274*0fca6ea1SDimitry Andric   if (RS.isEmpty()) {
3275*0fca6ea1SDimitry Andric     Out << "<empty rangeset>";
3276*0fca6ea1SDimitry Andric     return;
3277*0fca6ea1SDimitry Andric   }
3278fcaf7f86SDimitry Andric   Out << RS.getBitWidth() << (RS.isUnsigned() ? "u:" : "s:");
3279fcaf7f86SDimitry Andric   RS.dump(Out);
3280fcaf7f86SDimitry Andric }
3281fcaf7f86SDimitry Andric 
3282fe6060f1SDimitry Andric static std::string toString(const SymbolRef &Sym) {
3283fe6060f1SDimitry Andric   std::string S;
3284fe6060f1SDimitry Andric   llvm::raw_string_ostream O(S);
3285fe6060f1SDimitry Andric   Sym->dumpToStream(O);
3286*0fca6ea1SDimitry Andric   return S;
3287fe6060f1SDimitry Andric }
3288fe6060f1SDimitry Andric 
3289fe6060f1SDimitry Andric void RangeConstraintManager::printConstraints(raw_ostream &Out,
3290fe6060f1SDimitry Andric                                               ProgramStateRef State,
3291fe6060f1SDimitry Andric                                               const char *NL,
3292fe6060f1SDimitry Andric                                               unsigned int Space,
3293fe6060f1SDimitry Andric                                               bool IsDot) const {
32940b57cec5SDimitry Andric   ConstraintRangeTy Constraints = State->get<ConstraintRange>();
32950b57cec5SDimitry Andric 
32960b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << "\"constraints\": ";
32970b57cec5SDimitry Andric   if (Constraints.isEmpty()) {
32980b57cec5SDimitry Andric     Out << "null," << NL;
32990b57cec5SDimitry Andric     return;
33000b57cec5SDimitry Andric   }
33010b57cec5SDimitry Andric 
3302fe6060f1SDimitry Andric   std::map<std::string, RangeSet> OrderedConstraints;
3303fe6060f1SDimitry Andric   for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
3304fe6060f1SDimitry Andric     SymbolSet ClassMembers = P.first.getClassMembers(State);
3305fe6060f1SDimitry Andric     for (const SymbolRef &ClassMember : ClassMembers) {
3306fe6060f1SDimitry Andric       bool insertion_took_place;
3307fe6060f1SDimitry Andric       std::tie(std::ignore, insertion_took_place) =
3308fe6060f1SDimitry Andric           OrderedConstraints.insert({toString(ClassMember), P.second});
3309fe6060f1SDimitry Andric       assert(insertion_took_place &&
3310fe6060f1SDimitry Andric              "two symbols should not have the same dump");
3311fe6060f1SDimitry Andric     }
3312fe6060f1SDimitry Andric   }
3313fe6060f1SDimitry Andric 
33140b57cec5SDimitry Andric   ++Space;
33150b57cec5SDimitry Andric   Out << '[' << NL;
3316e8d8bef9SDimitry Andric   bool First = true;
3317fe6060f1SDimitry Andric   for (std::pair<std::string, RangeSet> P : OrderedConstraints) {
3318e8d8bef9SDimitry Andric     if (First) {
3319e8d8bef9SDimitry Andric       First = false;
3320e8d8bef9SDimitry Andric     } else {
33210b57cec5SDimitry Andric       Out << ',';
33220b57cec5SDimitry Andric       Out << NL;
33230b57cec5SDimitry Andric     }
3324e8d8bef9SDimitry Andric     Indent(Out, Space, IsDot)
3325fe6060f1SDimitry Andric         << "{ \"symbol\": \"" << P.first << "\", \"range\": \"";
3326fe6060f1SDimitry Andric     P.second.dump(Out);
3327e8d8bef9SDimitry Andric     Out << "\" }";
3328e8d8bef9SDimitry Andric   }
3329fe6060f1SDimitry Andric   Out << NL;
3330fe6060f1SDimitry Andric 
3331fe6060f1SDimitry Andric   --Space;
3332fe6060f1SDimitry Andric   Indent(Out, Space, IsDot) << "]," << NL;
3333fe6060f1SDimitry Andric }
3334fe6060f1SDimitry Andric 
3335fe6060f1SDimitry Andric static std::string toString(ProgramStateRef State, EquivalenceClass Class) {
3336fe6060f1SDimitry Andric   SymbolSet ClassMembers = Class.getClassMembers(State);
3337fe6060f1SDimitry Andric   llvm::SmallVector<SymbolRef, 8> ClassMembersSorted(ClassMembers.begin(),
3338fe6060f1SDimitry Andric                                                      ClassMembers.end());
3339fe6060f1SDimitry Andric   llvm::sort(ClassMembersSorted,
3340fe6060f1SDimitry Andric              [](const SymbolRef &LHS, const SymbolRef &RHS) {
3341fe6060f1SDimitry Andric                return toString(LHS) < toString(RHS);
3342fe6060f1SDimitry Andric              });
3343fe6060f1SDimitry Andric 
3344fe6060f1SDimitry Andric   bool FirstMember = true;
3345fe6060f1SDimitry Andric 
3346fe6060f1SDimitry Andric   std::string Str;
3347fe6060f1SDimitry Andric   llvm::raw_string_ostream Out(Str);
3348fe6060f1SDimitry Andric   Out << "[ ";
3349fe6060f1SDimitry Andric   for (SymbolRef ClassMember : ClassMembersSorted) {
3350fe6060f1SDimitry Andric     if (FirstMember)
3351fe6060f1SDimitry Andric       FirstMember = false;
3352fe6060f1SDimitry Andric     else
3353fe6060f1SDimitry Andric       Out << ", ";
3354fe6060f1SDimitry Andric     Out << "\"" << ClassMember << "\"";
3355fe6060f1SDimitry Andric   }
3356fe6060f1SDimitry Andric   Out << " ]";
3357*0fca6ea1SDimitry Andric   return Str;
3358fe6060f1SDimitry Andric }
3359fe6060f1SDimitry Andric 
3360fe6060f1SDimitry Andric void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3361fe6060f1SDimitry Andric                                                      ProgramStateRef State,
3362fe6060f1SDimitry Andric                                                      const char *NL,
3363fe6060f1SDimitry Andric                                                      unsigned int Space,
3364fe6060f1SDimitry Andric                                                      bool IsDot) const {
3365fe6060f1SDimitry Andric   ClassMembersTy Members = State->get<ClassMembers>();
3366fe6060f1SDimitry Andric 
3367fe6060f1SDimitry Andric   Indent(Out, Space, IsDot) << "\"equivalence_classes\": ";
3368fe6060f1SDimitry Andric   if (Members.isEmpty()) {
3369fe6060f1SDimitry Andric     Out << "null," << NL;
3370fe6060f1SDimitry Andric     return;
3371fe6060f1SDimitry Andric   }
3372fe6060f1SDimitry Andric 
3373fe6060f1SDimitry Andric   std::set<std::string> MembersStr;
3374fe6060f1SDimitry Andric   for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3375fe6060f1SDimitry Andric     MembersStr.insert(toString(State, ClassToSymbolSet.first));
3376fe6060f1SDimitry Andric 
3377fe6060f1SDimitry Andric   ++Space;
3378fe6060f1SDimitry Andric   Out << '[' << NL;
3379fe6060f1SDimitry Andric   bool FirstClass = true;
3380fe6060f1SDimitry Andric   for (const std::string &Str : MembersStr) {
3381fe6060f1SDimitry Andric     if (FirstClass) {
3382fe6060f1SDimitry Andric       FirstClass = false;
3383fe6060f1SDimitry Andric     } else {
3384fe6060f1SDimitry Andric       Out << ',';
3385fe6060f1SDimitry Andric       Out << NL;
3386fe6060f1SDimitry Andric     }
3387fe6060f1SDimitry Andric     Indent(Out, Space, IsDot);
3388fe6060f1SDimitry Andric     Out << Str;
3389fe6060f1SDimitry Andric   }
3390fe6060f1SDimitry Andric   Out << NL;
3391fe6060f1SDimitry Andric 
3392fe6060f1SDimitry Andric   --Space;
3393fe6060f1SDimitry Andric   Indent(Out, Space, IsDot) << "]," << NL;
3394fe6060f1SDimitry Andric }
3395fe6060f1SDimitry Andric 
3396fe6060f1SDimitry Andric void RangeConstraintManager::printDisequalities(raw_ostream &Out,
3397fe6060f1SDimitry Andric                                                 ProgramStateRef State,
3398fe6060f1SDimitry Andric                                                 const char *NL,
3399fe6060f1SDimitry Andric                                                 unsigned int Space,
3400fe6060f1SDimitry Andric                                                 bool IsDot) const {
3401fe6060f1SDimitry Andric   DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3402fe6060f1SDimitry Andric 
3403fe6060f1SDimitry Andric   Indent(Out, Space, IsDot) << "\"disequality_info\": ";
3404fe6060f1SDimitry Andric   if (Disequalities.isEmpty()) {
3405fe6060f1SDimitry Andric     Out << "null," << NL;
3406fe6060f1SDimitry Andric     return;
3407fe6060f1SDimitry Andric   }
3408fe6060f1SDimitry Andric 
3409fe6060f1SDimitry Andric   // Transform the disequality info to an ordered map of
3410fe6060f1SDimitry Andric   // [string -> (ordered set of strings)]
3411fe6060f1SDimitry Andric   using EqClassesStrTy = std::set<std::string>;
3412fe6060f1SDimitry Andric   using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3413fe6060f1SDimitry Andric   DisequalityInfoStrTy DisequalityInfoStr;
3414fe6060f1SDimitry Andric   for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3415fe6060f1SDimitry Andric     EquivalenceClass Class = ClassToDisEqSet.first;
3416fe6060f1SDimitry Andric     ClassSet DisequalClasses = ClassToDisEqSet.second;
3417fe6060f1SDimitry Andric     EqClassesStrTy MembersStr;
3418fe6060f1SDimitry Andric     for (EquivalenceClass DisEqClass : DisequalClasses)
3419fe6060f1SDimitry Andric       MembersStr.insert(toString(State, DisEqClass));
3420fe6060f1SDimitry Andric     DisequalityInfoStr.insert({toString(State, Class), MembersStr});
3421fe6060f1SDimitry Andric   }
3422fe6060f1SDimitry Andric 
3423fe6060f1SDimitry Andric   ++Space;
3424fe6060f1SDimitry Andric   Out << '[' << NL;
3425fe6060f1SDimitry Andric   bool FirstClass = true;
3426fe6060f1SDimitry Andric   for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3427fe6060f1SDimitry Andric        DisequalityInfoStr) {
3428fe6060f1SDimitry Andric     const std::string &Class = ClassToDisEqSet.first;
3429fe6060f1SDimitry Andric     if (FirstClass) {
3430fe6060f1SDimitry Andric       FirstClass = false;
3431fe6060f1SDimitry Andric     } else {
3432fe6060f1SDimitry Andric       Out << ',';
3433fe6060f1SDimitry Andric       Out << NL;
3434fe6060f1SDimitry Andric     }
3435fe6060f1SDimitry Andric     Indent(Out, Space, IsDot) << "{" << NL;
3436fe6060f1SDimitry Andric     unsigned int DisEqSpace = Space + 1;
3437fe6060f1SDimitry Andric     Indent(Out, DisEqSpace, IsDot) << "\"class\": ";
3438fe6060f1SDimitry Andric     Out << Class;
3439fe6060f1SDimitry Andric     const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3440fe6060f1SDimitry Andric     if (!DisequalClasses.empty()) {
3441fe6060f1SDimitry Andric       Out << "," << NL;
3442fe6060f1SDimitry Andric       Indent(Out, DisEqSpace, IsDot) << "\"disequal_to\": [" << NL;
3443fe6060f1SDimitry Andric       unsigned int DisEqClassSpace = DisEqSpace + 1;
3444fe6060f1SDimitry Andric       Indent(Out, DisEqClassSpace, IsDot);
3445fe6060f1SDimitry Andric       bool FirstDisEqClass = true;
3446fe6060f1SDimitry Andric       for (const std::string &DisEqClass : DisequalClasses) {
3447fe6060f1SDimitry Andric         if (FirstDisEqClass) {
3448fe6060f1SDimitry Andric           FirstDisEqClass = false;
3449fe6060f1SDimitry Andric         } else {
3450fe6060f1SDimitry Andric           Out << ',' << NL;
3451fe6060f1SDimitry Andric           Indent(Out, DisEqClassSpace, IsDot);
3452fe6060f1SDimitry Andric         }
3453fe6060f1SDimitry Andric         Out << DisEqClass;
3454fe6060f1SDimitry Andric       }
3455fe6060f1SDimitry Andric       Out << "]" << NL;
3456fe6060f1SDimitry Andric     }
3457fe6060f1SDimitry Andric     Indent(Out, Space, IsDot) << "}";
3458e8d8bef9SDimitry Andric   }
3459e8d8bef9SDimitry Andric   Out << NL;
34600b57cec5SDimitry Andric 
34610b57cec5SDimitry Andric   --Space;
34620b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << "]," << NL;
34630b57cec5SDimitry Andric }
3464