RangeConstraintManager.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. //== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines RangeConstraintManager, a class that tracks simple
  11. // equality and inequality constraints on symbolic values of ProgramState.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "SimpleConstraintManager.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
  18. #include "llvm/ADT/FoldingSet.h"
  19. #include "llvm/ADT/ImmutableSet.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/raw_ostream.h"
  22. using namespace clang;
  23. using namespace ento;
  24. /// A Range represents the closed range [from, to]. The caller must
  25. /// guarantee that from <= to. Note that Range is immutable, so as not
  26. /// to subvert RangeSet's immutability.
  27. namespace {
  28. class Range : public std::pair<const llvm::APSInt*,
  29. const llvm::APSInt*> {
  30. public:
  31. Range(const llvm::APSInt &from, const llvm::APSInt &to)
  32. : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) {
  33. assert(from <= to);
  34. }
  35. bool Includes(const llvm::APSInt &v) const {
  36. return *first <= v && v <= *second;
  37. }
  38. const llvm::APSInt &From() const {
  39. return *first;
  40. }
  41. const llvm::APSInt &To() const {
  42. return *second;
  43. }
  44. const llvm::APSInt *getConcreteValue() const {
  45. return &From() == &To() ? &From() : nullptr;
  46. }
  47. void Profile(llvm::FoldingSetNodeID &ID) const {
  48. ID.AddPointer(&From());
  49. ID.AddPointer(&To());
  50. }
  51. };
  52. class RangeTrait : public llvm::ImutContainerInfo<Range> {
  53. public:
  54. // When comparing if one Range is less than another, we should compare
  55. // the actual APSInt values instead of their pointers. This keeps the order
  56. // consistent (instead of comparing by pointer values) and can potentially
  57. // be used to speed up some of the operations in RangeSet.
  58. static inline bool isLess(key_type_ref lhs, key_type_ref rhs) {
  59. return *lhs.first < *rhs.first || (!(*rhs.first < *lhs.first) &&
  60. *lhs.second < *rhs.second);
  61. }
  62. };
  63. /// RangeSet contains a set of ranges. If the set is empty, then
  64. /// there the value of a symbol is overly constrained and there are no
  65. /// possible values for that symbol.
  66. class RangeSet {
  67. typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet;
  68. PrimRangeSet ranges; // no need to make const, since it is an
  69. // ImmutableSet - this allows default operator=
  70. // to work.
  71. public:
  72. typedef PrimRangeSet::Factory Factory;
  73. typedef PrimRangeSet::iterator iterator;
  74. RangeSet(PrimRangeSet RS) : ranges(RS) {}
  75. /// Create a new set with all ranges of this set and RS.
  76. /// Possible intersections are not checked here.
  77. RangeSet addRange(Factory &F, const RangeSet &RS) {
  78. PrimRangeSet Ranges(RS.ranges);
  79. for (const auto &range : ranges)
  80. Ranges = F.add(Ranges, range);
  81. return RangeSet(Ranges);
  82. }
  83. iterator begin() const { return ranges.begin(); }
  84. iterator end() const { return ranges.end(); }
  85. bool isEmpty() const { return ranges.isEmpty(); }
  86. /// Construct a new RangeSet representing '{ [from, to] }'.
  87. RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to)
  88. : ranges(F.add(F.getEmptySet(), Range(from, to))) {}
  89. /// Profile - Generates a hash profile of this RangeSet for use
  90. /// by FoldingSet.
  91. void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); }
  92. /// getConcreteValue - If a symbol is contrained to equal a specific integer
  93. /// constant then this method returns that value. Otherwise, it returns
  94. /// NULL.
  95. const llvm::APSInt* getConcreteValue() const {
  96. return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr;
  97. }
  98. private:
  99. void IntersectInRange(BasicValueFactory &BV, Factory &F,
  100. const llvm::APSInt &Lower,
  101. const llvm::APSInt &Upper,
  102. PrimRangeSet &newRanges,
  103. PrimRangeSet::iterator &i,
  104. PrimRangeSet::iterator &e) const {
  105. // There are six cases for each range R in the set:
  106. // 1. R is entirely before the intersection range.
  107. // 2. R is entirely after the intersection range.
  108. // 3. R contains the entire intersection range.
  109. // 4. R starts before the intersection range and ends in the middle.
  110. // 5. R starts in the middle of the intersection range and ends after it.
  111. // 6. R is entirely contained in the intersection range.
  112. // These correspond to each of the conditions below.
  113. for (/* i = begin(), e = end() */; i != e; ++i) {
  114. if (i->To() < Lower) {
  115. continue;
  116. }
  117. if (i->From() > Upper) {
  118. break;
  119. }
  120. if (i->Includes(Lower)) {
  121. if (i->Includes(Upper)) {
  122. newRanges = F.add(newRanges, Range(BV.getValue(Lower),
  123. BV.getValue(Upper)));
  124. break;
  125. } else
  126. newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To()));
  127. } else {
  128. if (i->Includes(Upper)) {
  129. newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper)));
  130. break;
  131. } else
  132. newRanges = F.add(newRanges, *i);
  133. }
  134. }
  135. }
  136. const llvm::APSInt &getMinValue() const {
  137. assert(!isEmpty());
  138. return ranges.begin()->From();
  139. }
  140. bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
  141. // This function has nine cases, the cartesian product of range-testing
  142. // both the upper and lower bounds against the symbol's type.
  143. // Each case requires a different pinning operation.
  144. // The function returns false if the described range is entirely outside
  145. // the range of values for the associated symbol.
  146. APSIntType Type(getMinValue());
  147. APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
  148. APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
  149. switch (LowerTest) {
  150. case APSIntType::RTR_Below:
  151. switch (UpperTest) {
  152. case APSIntType::RTR_Below:
  153. // The entire range is outside the symbol's set of possible values.
  154. // If this is a conventionally-ordered range, the state is infeasible.
  155. if (Lower < Upper)
  156. return false;
  157. // However, if the range wraps around, it spans all possible values.
  158. Lower = Type.getMinValue();
  159. Upper = Type.getMaxValue();
  160. break;
  161. case APSIntType::RTR_Within:
  162. // The range starts below what's possible but ends within it. Pin.
  163. Lower = Type.getMinValue();
  164. Type.apply(Upper);
  165. break;
  166. case APSIntType::RTR_Above:
  167. // The range spans all possible values for the symbol. Pin.
  168. Lower = Type.getMinValue();
  169. Upper = Type.getMaxValue();
  170. break;
  171. }
  172. break;
  173. case APSIntType::RTR_Within:
  174. switch (UpperTest) {
  175. case APSIntType::RTR_Below:
  176. // The range wraps around, but all lower values are not possible.
  177. Type.apply(Lower);
  178. Upper = Type.getMaxValue();
  179. break;
  180. case APSIntType::RTR_Within:
  181. // The range may or may not wrap around, but both limits are valid.
  182. Type.apply(Lower);
  183. Type.apply(Upper);
  184. break;
  185. case APSIntType::RTR_Above:
  186. // The range starts within what's possible but ends above it. Pin.
  187. Type.apply(Lower);
  188. Upper = Type.getMaxValue();
  189. break;
  190. }
  191. break;
  192. case APSIntType::RTR_Above:
  193. switch (UpperTest) {
  194. case APSIntType::RTR_Below:
  195. // The range wraps but is outside the symbol's set of possible values.
  196. return false;
  197. case APSIntType::RTR_Within:
  198. // The range starts above what's possible but ends within it (wrap).
  199. Lower = Type.getMinValue();
  200. Type.apply(Upper);
  201. break;
  202. case APSIntType::RTR_Above:
  203. // The entire range is outside the symbol's set of possible values.
  204. // If this is a conventionally-ordered range, the state is infeasible.
  205. if (Lower < Upper)
  206. return false;
  207. // However, if the range wraps around, it spans all possible values.
  208. Lower = Type.getMinValue();
  209. Upper = Type.getMaxValue();
  210. break;
  211. }
  212. break;
  213. }
  214. return true;
  215. }
  216. public:
  217. // Returns a set containing the values in the receiving set, intersected with
  218. // the closed range [Lower, Upper]. Unlike the Range type, this range uses
  219. // modular arithmetic, corresponding to the common treatment of C integer
  220. // overflow. Thus, if the Lower bound is greater than the Upper bound, the
  221. // range is taken to wrap around. This is equivalent to taking the
  222. // intersection with the two ranges [Min, Upper] and [Lower, Max],
  223. // or, alternatively, /removing/ all integers between Upper and Lower.
  224. RangeSet Intersect(BasicValueFactory &BV, Factory &F,
  225. llvm::APSInt Lower, llvm::APSInt Upper) const {
  226. if (!pin(Lower, Upper))
  227. return F.getEmptySet();
  228. PrimRangeSet newRanges = F.getEmptySet();
  229. PrimRangeSet::iterator i = begin(), e = end();
  230. if (Lower <= Upper)
  231. IntersectInRange(BV, F, Lower, Upper, newRanges, i, e);
  232. else {
  233. // The order of the next two statements is important!
  234. // IntersectInRange() does not reset the iteration state for i and e.
  235. // Therefore, the lower range most be handled first.
  236. IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e);
  237. IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e);
  238. }
  239. return newRanges;
  240. }
  241. void print(raw_ostream &os) const {
  242. bool isFirst = true;
  243. os << "{ ";
  244. for (iterator i = begin(), e = end(); i != e; ++i) {
  245. if (isFirst)
  246. isFirst = false;
  247. else
  248. os << ", ";
  249. os << '[' << i->From().toString(10) << ", " << i->To().toString(10)
  250. << ']';
  251. }
  252. os << " }";
  253. }
  254. bool operator==(const RangeSet &other) const {
  255. return ranges == other.ranges;
  256. }
  257. };
  258. } // end anonymous namespace
  259. REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange,
  260. CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef,
  261. RangeSet))
  262. namespace {
  263. class RangeConstraintManager : public SimpleConstraintManager{
  264. RangeSet GetRange(ProgramStateRef state, SymbolRef sym);
  265. public:
  266. RangeConstraintManager(SubEngine *subengine, SValBuilder &SVB)
  267. : SimpleConstraintManager(subengine, SVB) {}
  268. ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym,
  269. const llvm::APSInt& Int,
  270. const llvm::APSInt& Adjustment) override;
  271. ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym,
  272. const llvm::APSInt& Int,
  273. const llvm::APSInt& Adjustment) override;
  274. ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym,
  275. const llvm::APSInt& Int,
  276. const llvm::APSInt& Adjustment) override;
  277. ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym,
  278. const llvm::APSInt& Int,
  279. const llvm::APSInt& Adjustment) override;
  280. ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym,
  281. const llvm::APSInt& Int,
  282. const llvm::APSInt& Adjustment) override;
  283. ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym,
  284. const llvm::APSInt& Int,
  285. const llvm::APSInt& Adjustment) override;
  286. ProgramStateRef assumeSymbolWithinInclusiveRange(
  287. ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
  288. const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
  289. ProgramStateRef assumeSymbolOutOfInclusiveRange(
  290. ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
  291. const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
  292. const llvm::APSInt* getSymVal(ProgramStateRef St,
  293. SymbolRef sym) const override;
  294. ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
  295. ProgramStateRef removeDeadBindings(ProgramStateRef St,
  296. SymbolReaper& SymReaper) override;
  297. void print(ProgramStateRef St, raw_ostream &Out,
  298. const char* nl, const char *sep) override;
  299. private:
  300. RangeSet::Factory F;
  301. RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
  302. const llvm::APSInt &Int,
  303. const llvm::APSInt &Adjustment);
  304. RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym,
  305. const llvm::APSInt &Int,
  306. const llvm::APSInt &Adjustment);
  307. RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
  308. const llvm::APSInt &Int,
  309. const llvm::APSInt &Adjustment);
  310. RangeSet getSymLERange(const RangeSet &RS, const llvm::APSInt &Int,
  311. const llvm::APSInt &Adjustment);
  312. RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
  313. const llvm::APSInt &Int,
  314. const llvm::APSInt &Adjustment);
  315. };
  316. } // end anonymous namespace
  317. std::unique_ptr<ConstraintManager>
  318. ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) {
  319. return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder());
  320. }
  321. const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St,
  322. SymbolRef sym) const {
  323. const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym);
  324. return T ? T->getConcreteValue() : nullptr;
  325. }
  326. ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
  327. SymbolRef Sym) {
  328. const RangeSet *Ranges = State->get<ConstraintRange>(Sym);
  329. // If we don't have any information about this symbol, it's underconstrained.
  330. if (!Ranges)
  331. return ConditionTruthVal();
  332. // If we have a concrete value, see if it's zero.
  333. if (const llvm::APSInt *Value = Ranges->getConcreteValue())
  334. return *Value == 0;
  335. BasicValueFactory &BV = getBasicVals();
  336. APSIntType IntType = BV.getAPSIntType(Sym->getType());
  337. llvm::APSInt Zero = IntType.getZeroValue();
  338. // Check if zero is in the set of possible values.
  339. if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty())
  340. return false;
  341. // Zero is a possible value, but it is not the /only/ possible value.
  342. return ConditionTruthVal();
  343. }
  344. /// Scan all symbols referenced by the constraints. If the symbol is not alive
  345. /// as marked in LSymbols, mark it as dead in DSymbols.
  346. ProgramStateRef
  347. RangeConstraintManager::removeDeadBindings(ProgramStateRef state,
  348. SymbolReaper& SymReaper) {
  349. ConstraintRangeTy CR = state->get<ConstraintRange>();
  350. ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>();
  351. for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) {
  352. SymbolRef sym = I.getKey();
  353. if (SymReaper.maybeDead(sym))
  354. CR = CRFactory.remove(CR, sym);
  355. }
  356. return state->set<ConstraintRange>(CR);
  357. }
  358. RangeSet
  359. RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
  360. if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym))
  361. return *V;
  362. // Lazily generate a new RangeSet representing all possible values for the
  363. // given symbol type.
  364. BasicValueFactory &BV = getBasicVals();
  365. QualType T = sym->getType();
  366. RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
  367. // Special case: references are known to be non-zero.
  368. if (T->isReferenceType()) {
  369. APSIntType IntType = BV.getAPSIntType(T);
  370. Result = Result.Intersect(BV, F, ++IntType.getZeroValue(),
  371. --IntType.getZeroValue());
  372. }
  373. return Result;
  374. }
  375. //===------------------------------------------------------------------------===
  376. // assumeSymX methods: public interface for RangeConstraintManager.
  377. //===------------------------------------------------------------------------===/
  378. // The syntax for ranges below is mathematical, using [x, y] for closed ranges
  379. // and (x, y) for open ranges. These ranges are modular, corresponding with
  380. // a common treatment of C integer overflow. This means that these methods
  381. // do not have to worry about overflow; RangeSet::Intersect can handle such a
  382. // "wraparound" range.
  383. // As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
  384. // UINT_MAX, 0, 1, and 2.
  385. ProgramStateRef
  386. RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
  387. const llvm::APSInt &Int,
  388. const llvm::APSInt &Adjustment) {
  389. // Before we do any real work, see if the value can even show up.
  390. APSIntType AdjustmentType(Adjustment);
  391. if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
  392. return St;
  393. llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment;
  394. llvm::APSInt Upper = Lower;
  395. --Lower;
  396. ++Upper;
  397. // [Int-Adjustment+1, Int-Adjustment-1]
  398. // Notice that the lower bound is greater than the upper bound.
  399. RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower);
  400. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  401. }
  402. ProgramStateRef
  403. RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
  404. const llvm::APSInt &Int,
  405. const llvm::APSInt &Adjustment) {
  406. // Before we do any real work, see if the value can even show up.
  407. APSIntType AdjustmentType(Adjustment);
  408. if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
  409. return nullptr;
  410. // [Int-Adjustment, Int-Adjustment]
  411. llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
  412. RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt);
  413. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  414. }
  415. RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
  416. SymbolRef Sym,
  417. const llvm::APSInt &Int,
  418. const llvm::APSInt &Adjustment) {
  419. // Before we do any real work, see if the value can even show up.
  420. APSIntType AdjustmentType(Adjustment);
  421. switch (AdjustmentType.testInRange(Int, true)) {
  422. case APSIntType::RTR_Below:
  423. return F.getEmptySet();
  424. case APSIntType::RTR_Within:
  425. break;
  426. case APSIntType::RTR_Above:
  427. return GetRange(St, Sym);
  428. }
  429. // Special case for Int == Min. This is always false.
  430. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
  431. llvm::APSInt Min = AdjustmentType.getMinValue();
  432. if (ComparisonVal == Min)
  433. return F.getEmptySet();
  434. llvm::APSInt Lower = Min - Adjustment;
  435. llvm::APSInt Upper = ComparisonVal - Adjustment;
  436. --Upper;
  437. return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
  438. }
  439. ProgramStateRef
  440. RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
  441. const llvm::APSInt &Int,
  442. const llvm::APSInt &Adjustment) {
  443. RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
  444. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  445. }
  446. RangeSet
  447. RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym,
  448. const llvm::APSInt &Int,
  449. const llvm::APSInt &Adjustment) {
  450. // Before we do any real work, see if the value can even show up.
  451. APSIntType AdjustmentType(Adjustment);
  452. switch (AdjustmentType.testInRange(Int, true)) {
  453. case APSIntType::RTR_Below:
  454. return GetRange(St, Sym);
  455. case APSIntType::RTR_Within:
  456. break;
  457. case APSIntType::RTR_Above:
  458. return F.getEmptySet();
  459. }
  460. // Special case for Int == Max. This is always false.
  461. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
  462. llvm::APSInt Max = AdjustmentType.getMaxValue();
  463. if (ComparisonVal == Max)
  464. return F.getEmptySet();
  465. llvm::APSInt Lower = ComparisonVal - Adjustment;
  466. llvm::APSInt Upper = Max - Adjustment;
  467. ++Lower;
  468. return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
  469. }
  470. ProgramStateRef
  471. RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
  472. const llvm::APSInt &Int,
  473. const llvm::APSInt &Adjustment) {
  474. RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
  475. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  476. }
  477. RangeSet
  478. RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym,
  479. const llvm::APSInt &Int,
  480. const llvm::APSInt &Adjustment) {
  481. // Before we do any real work, see if the value can even show up.
  482. APSIntType AdjustmentType(Adjustment);
  483. switch (AdjustmentType.testInRange(Int, true)) {
  484. case APSIntType::RTR_Below:
  485. return GetRange(St, Sym);
  486. case APSIntType::RTR_Within:
  487. break;
  488. case APSIntType::RTR_Above:
  489. return F.getEmptySet();
  490. }
  491. // Special case for Int == Min. This is always feasible.
  492. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
  493. llvm::APSInt Min = AdjustmentType.getMinValue();
  494. if (ComparisonVal == Min)
  495. return GetRange(St, Sym);
  496. llvm::APSInt Max = AdjustmentType.getMaxValue();
  497. llvm::APSInt Lower = ComparisonVal - Adjustment;
  498. llvm::APSInt Upper = Max - Adjustment;
  499. return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
  500. }
  501. ProgramStateRef
  502. RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
  503. const llvm::APSInt &Int,
  504. const llvm::APSInt &Adjustment) {
  505. RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
  506. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  507. }
  508. RangeSet
  509. RangeConstraintManager::getSymLERange(const RangeSet &RS,
  510. const llvm::APSInt &Int,
  511. const llvm::APSInt &Adjustment) {
  512. // Before we do any real work, see if the value can even show up.
  513. APSIntType AdjustmentType(Adjustment);
  514. switch (AdjustmentType.testInRange(Int, true)) {
  515. case APSIntType::RTR_Below:
  516. return F.getEmptySet();
  517. case APSIntType::RTR_Within:
  518. break;
  519. case APSIntType::RTR_Above:
  520. return RS;
  521. }
  522. // Special case for Int == Max. This is always feasible.
  523. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
  524. llvm::APSInt Max = AdjustmentType.getMaxValue();
  525. if (ComparisonVal == Max)
  526. return RS;
  527. llvm::APSInt Min = AdjustmentType.getMinValue();
  528. llvm::APSInt Lower = Min - Adjustment;
  529. llvm::APSInt Upper = ComparisonVal - Adjustment;
  530. return RS.Intersect(getBasicVals(), F, Lower, Upper);
  531. }
  532. RangeSet
  533. RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym,
  534. const llvm::APSInt &Int,
  535. const llvm::APSInt &Adjustment) {
  536. // Before we do any real work, see if the value can even show up.
  537. APSIntType AdjustmentType(Adjustment);
  538. switch (AdjustmentType.testInRange(Int, true)) {
  539. case APSIntType::RTR_Below:
  540. return F.getEmptySet();
  541. case APSIntType::RTR_Within:
  542. break;
  543. case APSIntType::RTR_Above:
  544. return GetRange(St, Sym);
  545. }
  546. // Special case for Int == Max. This is always feasible.
  547. llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
  548. llvm::APSInt Max = AdjustmentType.getMaxValue();
  549. if (ComparisonVal == Max)
  550. return GetRange(St, Sym);
  551. llvm::APSInt Min = AdjustmentType.getMinValue();
  552. llvm::APSInt Lower = Min - Adjustment;
  553. llvm::APSInt Upper = ComparisonVal - Adjustment;
  554. return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper);
  555. }
  556. ProgramStateRef
  557. RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
  558. const llvm::APSInt &Int,
  559. const llvm::APSInt &Adjustment) {
  560. RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
  561. return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New);
  562. }
  563. ProgramStateRef
  564. RangeConstraintManager::assumeSymbolWithinInclusiveRange(
  565. ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
  566. const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
  567. RangeSet New = getSymGERange(State, Sym, From, Adjustment);
  568. if (New.isEmpty())
  569. return nullptr;
  570. New = getSymLERange(New, To, Adjustment);
  571. return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
  572. }
  573. ProgramStateRef
  574. RangeConstraintManager::assumeSymbolOutOfInclusiveRange(
  575. ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
  576. const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
  577. RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
  578. RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
  579. RangeSet New(RangeLT.addRange(F, RangeGT));
  580. return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New);
  581. }
  582. //===------------------------------------------------------------------------===
  583. // Pretty-printing.
  584. //===------------------------------------------------------------------------===/
  585. void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out,
  586. const char* nl, const char *sep) {
  587. ConstraintRangeTy Ranges = St->get<ConstraintRange>();
  588. if (Ranges.isEmpty()) {
  589. Out << nl << sep << "Ranges are empty." << nl;
  590. return;
  591. }
  592. Out << nl << sep << "Ranges of symbol values:";
  593. for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){
  594. Out << nl << ' ' << I.getKey() << " : ";
  595. I.getData().print(Out);
  596. }
  597. Out << nl;
  598. }