BasicConstraintManager.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. //== BasicConstraintManager.cpp - Manage basic 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 BasicConstraintManager, 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/Support/raw_ostream.h"
  19. using namespace clang;
  20. using namespace ento;
  21. namespace { class ConstNotEq {}; }
  22. namespace { class ConstEq {}; }
  23. typedef llvm::ImmutableMap<SymbolRef,ProgramState::IntSetTy> ConstNotEqTy;
  24. typedef llvm::ImmutableMap<SymbolRef,const llvm::APSInt*> ConstEqTy;
  25. static int ConstEqIndex = 0;
  26. static int ConstNotEqIndex = 0;
  27. namespace clang {
  28. namespace ento {
  29. template<>
  30. struct ProgramStateTrait<ConstNotEq> :
  31. public ProgramStatePartialTrait<ConstNotEqTy> {
  32. static inline void *GDMIndex() { return &ConstNotEqIndex; }
  33. };
  34. template<>
  35. struct ProgramStateTrait<ConstEq> : public ProgramStatePartialTrait<ConstEqTy> {
  36. static inline void *GDMIndex() { return &ConstEqIndex; }
  37. };
  38. }
  39. }
  40. namespace {
  41. // BasicConstraintManager only tracks equality and inequality constraints of
  42. // constants and integer variables.
  43. class BasicConstraintManager
  44. : public SimpleConstraintManager {
  45. ProgramState::IntSetTy::Factory ISetFactory;
  46. public:
  47. BasicConstraintManager(ProgramStateManager &statemgr, SubEngine &subengine)
  48. : SimpleConstraintManager(subengine, statemgr.getBasicVals()),
  49. ISetFactory(statemgr.getAllocator()) {}
  50. ProgramStateRef assumeSymEquality(ProgramStateRef State, SymbolRef Sym,
  51. const llvm::APSInt &V,
  52. const llvm::APSInt &Adjustment,
  53. bool Assumption);
  54. ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
  55. const llvm::APSInt &V,
  56. const llvm::APSInt &Adjustment) {
  57. return assumeSymEquality(State, Sym, V, Adjustment, false);
  58. }
  59. ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
  60. const llvm::APSInt &V,
  61. const llvm::APSInt &Adjustment) {
  62. return assumeSymEquality(State, Sym, V, Adjustment, true);
  63. }
  64. ProgramStateRef assumeSymLT(ProgramStateRef state,
  65. SymbolRef sym,
  66. const llvm::APSInt& V,
  67. const llvm::APSInt& Adjustment);
  68. ProgramStateRef assumeSymGT(ProgramStateRef state,
  69. SymbolRef sym,
  70. const llvm::APSInt& V,
  71. const llvm::APSInt& Adjustment);
  72. ProgramStateRef assumeSymGE(ProgramStateRef state,
  73. SymbolRef sym,
  74. const llvm::APSInt& V,
  75. const llvm::APSInt& Adjustment);
  76. ProgramStateRef assumeSymLE(ProgramStateRef state,
  77. SymbolRef sym,
  78. const llvm::APSInt& V,
  79. const llvm::APSInt& Adjustment);
  80. ProgramStateRef AddEQ(ProgramStateRef state,
  81. SymbolRef sym,
  82. const llvm::APSInt& V);
  83. ProgramStateRef AddNE(ProgramStateRef state,
  84. SymbolRef sym,
  85. const llvm::APSInt& V);
  86. const llvm::APSInt* getSymVal(ProgramStateRef state,
  87. SymbolRef sym) const;
  88. bool isNotEqual(ProgramStateRef state,
  89. SymbolRef sym,
  90. const llvm::APSInt& V) const;
  91. bool isEqual(ProgramStateRef state,
  92. SymbolRef sym,
  93. const llvm::APSInt& V) const;
  94. ProgramStateRef removeDeadBindings(ProgramStateRef state,
  95. SymbolReaper& SymReaper);
  96. bool performTest(llvm::APSInt SymVal, llvm::APSInt Adjustment,
  97. BinaryOperator::Opcode Op, llvm::APSInt ComparisonVal);
  98. void print(ProgramStateRef state,
  99. raw_ostream &Out,
  100. const char* nl,
  101. const char *sep);
  102. };
  103. } // end anonymous namespace
  104. ConstraintManager*
  105. ento::CreateBasicConstraintManager(ProgramStateManager& statemgr,
  106. SubEngine &subengine) {
  107. return new BasicConstraintManager(statemgr, subengine);
  108. }
  109. // FIXME: This is a more general utility and should live somewhere else.
  110. bool BasicConstraintManager::performTest(llvm::APSInt SymVal,
  111. llvm::APSInt Adjustment,
  112. BinaryOperator::Opcode Op,
  113. llvm::APSInt ComparisonVal) {
  114. APSIntType Type(Adjustment);
  115. Type.apply(SymVal);
  116. Type.apply(ComparisonVal);
  117. SymVal += Adjustment;
  118. assert(BinaryOperator::isComparisonOp(Op));
  119. BasicValueFactory &BVF = getBasicVals();
  120. const llvm::APSInt *Result = BVF.evalAPSInt(Op, SymVal, ComparisonVal);
  121. assert(Result && "Comparisons should always have valid results.");
  122. return Result->getBoolValue();
  123. }
  124. ProgramStateRef
  125. BasicConstraintManager::assumeSymEquality(ProgramStateRef State, SymbolRef Sym,
  126. const llvm::APSInt &V,
  127. const llvm::APSInt &Adjustment,
  128. bool Assumption) {
  129. // Before we do any real work, see if the value can even show up.
  130. APSIntType AdjustmentType(Adjustment);
  131. if (AdjustmentType.testInRange(V) != APSIntType::RTR_Within)
  132. return Assumption ? NULL : State;
  133. // Get the symbol type.
  134. BasicValueFactory &BVF = getBasicVals();
  135. ASTContext &Ctx = BVF.getContext();
  136. APSIntType SymbolType = BVF.getAPSIntType(Sym->getType(Ctx));
  137. // First, see if the adjusted value is within range for the symbol.
  138. llvm::APSInt Adjusted = AdjustmentType.convert(V) - Adjustment;
  139. if (SymbolType.testInRange(Adjusted) != APSIntType::RTR_Within)
  140. return Assumption ? NULL : State;
  141. // Now we can do things properly in the symbol space.
  142. SymbolType.apply(Adjusted);
  143. // Second, determine if sym == X, where X+Adjustment != V.
  144. if (const llvm::APSInt *X = getSymVal(State, Sym)) {
  145. bool IsFeasible = (*X == Adjusted);
  146. return (IsFeasible == Assumption) ? State : NULL;
  147. }
  148. // Third, determine if we already know sym+Adjustment != V.
  149. if (isNotEqual(State, Sym, Adjusted))
  150. return Assumption ? NULL : State;
  151. // If we reach here, sym is not a constant and we don't know if it is != V.
  152. // Make the correct assumption.
  153. if (Assumption)
  154. return AddEQ(State, Sym, Adjusted);
  155. else
  156. return AddNE(State, Sym, Adjusted);
  157. }
  158. // The logic for these will be handled in another ConstraintManager.
  159. // Approximate it here anyway by handling some edge cases.
  160. ProgramStateRef
  161. BasicConstraintManager::assumeSymLT(ProgramStateRef state,
  162. SymbolRef sym,
  163. const llvm::APSInt &V,
  164. const llvm::APSInt &Adjustment) {
  165. APSIntType ComparisonType(V), AdjustmentType(Adjustment);
  166. // Is 'V' out of range above the type?
  167. llvm::APSInt Max = AdjustmentType.getMaxValue();
  168. if (V > ComparisonType.convert(Max)) {
  169. // This path is trivially feasible.
  170. return state;
  171. }
  172. // Is 'V' the smallest possible value, or out of range below the type?
  173. llvm::APSInt Min = AdjustmentType.getMinValue();
  174. if (V <= ComparisonType.convert(Min)) {
  175. // sym cannot be any value less than 'V'. This path is infeasible.
  176. return NULL;
  177. }
  178. // Reject a path if the value of sym is a constant X and !(X+Adj < V).
  179. if (const llvm::APSInt *X = getSymVal(state, sym)) {
  180. bool isFeasible = performTest(*X, Adjustment, BO_LT, V);
  181. return isFeasible ? state : NULL;
  182. }
  183. // FIXME: For now have assuming x < y be the same as assuming sym != V;
  184. return assumeSymNE(state, sym, V, Adjustment);
  185. }
  186. ProgramStateRef
  187. BasicConstraintManager::assumeSymGT(ProgramStateRef state,
  188. SymbolRef sym,
  189. const llvm::APSInt &V,
  190. const llvm::APSInt &Adjustment) {
  191. APSIntType ComparisonType(V), AdjustmentType(Adjustment);
  192. // Is 'V' the largest possible value, or out of range above the type?
  193. llvm::APSInt Max = AdjustmentType.getMaxValue();
  194. if (V >= ComparisonType.convert(Max)) {
  195. // sym cannot be any value greater than 'V'. This path is infeasible.
  196. return NULL;
  197. }
  198. // Is 'V' out of range below the type?
  199. llvm::APSInt Min = AdjustmentType.getMinValue();
  200. if (V < ComparisonType.convert(Min)) {
  201. // This path is trivially feasible.
  202. return state;
  203. }
  204. // Reject a path if the value of sym is a constant X and !(X+Adj > V).
  205. if (const llvm::APSInt *X = getSymVal(state, sym)) {
  206. bool isFeasible = performTest(*X, Adjustment, BO_GT, V);
  207. return isFeasible ? state : NULL;
  208. }
  209. // FIXME: For now have assuming x > y be the same as assuming sym != V;
  210. return assumeSymNE(state, sym, V, Adjustment);
  211. }
  212. ProgramStateRef
  213. BasicConstraintManager::assumeSymGE(ProgramStateRef state,
  214. SymbolRef sym,
  215. const llvm::APSInt &V,
  216. const llvm::APSInt &Adjustment) {
  217. APSIntType ComparisonType(V), AdjustmentType(Adjustment);
  218. // Is 'V' the largest possible value, or out of range above the type?
  219. llvm::APSInt Max = AdjustmentType.getMaxValue();
  220. ComparisonType.apply(Max);
  221. if (V > Max) {
  222. // sym cannot be any value greater than 'V'. This path is infeasible.
  223. return NULL;
  224. } else if (V == Max) {
  225. // If the path is feasible then as a consequence we know that
  226. // 'sym+Adjustment == V' because there are no larger values.
  227. // Add this constraint.
  228. return assumeSymEQ(state, sym, V, Adjustment);
  229. }
  230. // Is 'V' out of range below the type?
  231. llvm::APSInt Min = AdjustmentType.getMinValue();
  232. if (V < ComparisonType.convert(Min)) {
  233. // This path is trivially feasible.
  234. return state;
  235. }
  236. // Reject a path if the value of sym is a constant X and !(X+Adj >= V).
  237. if (const llvm::APSInt *X = getSymVal(state, sym)) {
  238. bool isFeasible = performTest(*X, Adjustment, BO_GE, V);
  239. return isFeasible ? state : NULL;
  240. }
  241. return state;
  242. }
  243. ProgramStateRef
  244. BasicConstraintManager::assumeSymLE(ProgramStateRef state,
  245. SymbolRef sym,
  246. const llvm::APSInt &V,
  247. const llvm::APSInt &Adjustment) {
  248. APSIntType ComparisonType(V), AdjustmentType(Adjustment);
  249. // Is 'V' out of range above the type?
  250. llvm::APSInt Max = AdjustmentType.getMaxValue();
  251. if (V > ComparisonType.convert(Max)) {
  252. // This path is trivially feasible.
  253. return state;
  254. }
  255. // Is 'V' the smallest possible value, or out of range below the type?
  256. llvm::APSInt Min = AdjustmentType.getMinValue();
  257. ComparisonType.apply(Min);
  258. if (V < Min) {
  259. // sym cannot be any value less than 'V'. This path is infeasible.
  260. return NULL;
  261. } else if (V == Min) {
  262. // If the path is feasible then as a consequence we know that
  263. // 'sym+Adjustment == V' because there are no smaller values.
  264. // Add this constraint.
  265. return assumeSymEQ(state, sym, V, Adjustment);
  266. }
  267. // Reject a path if the value of sym is a constant X and !(X+Adj >= V).
  268. if (const llvm::APSInt *X = getSymVal(state, sym)) {
  269. bool isFeasible = performTest(*X, Adjustment, BO_LE, V);
  270. return isFeasible ? state : NULL;
  271. }
  272. return state;
  273. }
  274. ProgramStateRef BasicConstraintManager::AddEQ(ProgramStateRef state,
  275. SymbolRef sym,
  276. const llvm::APSInt& V) {
  277. // Now that we have an actual value, we can throw out the NE-set.
  278. // Create a new state with the old bindings replaced.
  279. state = state->remove<ConstNotEq>(sym);
  280. return state->set<ConstEq>(sym, &getBasicVals().getValue(V));
  281. }
  282. ProgramStateRef BasicConstraintManager::AddNE(ProgramStateRef state,
  283. SymbolRef sym,
  284. const llvm::APSInt& V) {
  285. // First, retrieve the NE-set associated with the given symbol.
  286. ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
  287. ProgramState::IntSetTy S = T ? *T : ISetFactory.getEmptySet();
  288. // Now add V to the NE set.
  289. S = ISetFactory.add(S, &getBasicVals().getValue(V));
  290. // Create a new state with the old binding replaced.
  291. return state->set<ConstNotEq>(sym, S);
  292. }
  293. const llvm::APSInt* BasicConstraintManager::getSymVal(ProgramStateRef state,
  294. SymbolRef sym) const {
  295. const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
  296. return T ? *T : NULL;
  297. }
  298. bool BasicConstraintManager::isNotEqual(ProgramStateRef state,
  299. SymbolRef sym,
  300. const llvm::APSInt& V) const {
  301. // Retrieve the NE-set associated with the given symbol.
  302. const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
  303. // See if V is present in the NE-set.
  304. return T ? T->contains(&getBasicVals().getValue(V)) : false;
  305. }
  306. bool BasicConstraintManager::isEqual(ProgramStateRef state,
  307. SymbolRef sym,
  308. const llvm::APSInt& V) const {
  309. // Retrieve the EQ-set associated with the given symbol.
  310. const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
  311. // See if V is present in the EQ-set.
  312. return T ? **T == V : false;
  313. }
  314. /// Scan all symbols referenced by the constraints. If the symbol is not alive
  315. /// as marked in LSymbols, mark it as dead in DSymbols.
  316. ProgramStateRef
  317. BasicConstraintManager::removeDeadBindings(ProgramStateRef state,
  318. SymbolReaper& SymReaper) {
  319. ConstEqTy CE = state->get<ConstEq>();
  320. ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
  321. for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
  322. SymbolRef sym = I.getKey();
  323. if (SymReaper.maybeDead(sym))
  324. CE = CEFactory.remove(CE, sym);
  325. }
  326. state = state->set<ConstEq>(CE);
  327. ConstNotEqTy CNE = state->get<ConstNotEq>();
  328. ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
  329. for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
  330. SymbolRef sym = I.getKey();
  331. if (SymReaper.maybeDead(sym))
  332. CNE = CNEFactory.remove(CNE, sym);
  333. }
  334. return state->set<ConstNotEq>(CNE);
  335. }
  336. void BasicConstraintManager::print(ProgramStateRef state,
  337. raw_ostream &Out,
  338. const char* nl, const char *sep) {
  339. // Print equality constraints.
  340. ConstEqTy CE = state->get<ConstEq>();
  341. if (!CE.isEmpty()) {
  342. Out << nl << sep << "'==' constraints:";
  343. for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I)
  344. Out << nl << " $" << I.getKey() << " : " << *I.getData();
  345. }
  346. // Print != constraints.
  347. ConstNotEqTy CNE = state->get<ConstNotEq>();
  348. if (!CNE.isEmpty()) {
  349. Out << nl << sep << "'!=' constraints:";
  350. for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
  351. Out << nl << " $" << I.getKey() << " : ";
  352. bool isFirst = true;
  353. ProgramState::IntSetTy::iterator J = I.getData().begin(),
  354. EJ = I.getData().end();
  355. for ( ; J != EJ; ++J) {
  356. if (isFirst) isFirst = false;
  357. else Out << ", ";
  358. Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
  359. }
  360. }
  361. }
  362. }