BasicConstraintManager.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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 GRState.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "SimpleConstraintManager.h"
  15. #include "clang/StaticAnalyzer/PathSensitive/GRState.h"
  16. #include "clang/StaticAnalyzer/PathSensitive/GRStateTrait.h"
  17. #include "clang/StaticAnalyzer/PathSensitive/TransferFuncs.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,GRState::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 GRStateTrait<ConstNotEq> : public GRStatePartialTrait<ConstNotEqTy> {
  31. static inline void* GDMIndex() { return &ConstNotEqIndex; }
  32. };
  33. template<>
  34. struct GRStateTrait<ConstEq> : public GRStatePartialTrait<ConstEqTy> {
  35. static inline void* GDMIndex() { return &ConstEqIndex; }
  36. };
  37. }
  38. }
  39. namespace {
  40. // BasicConstraintManager only tracks equality and inequality constraints of
  41. // constants and integer variables.
  42. class BasicConstraintManager
  43. : public SimpleConstraintManager {
  44. GRState::IntSetTy::Factory ISetFactory;
  45. public:
  46. BasicConstraintManager(GRStateManager &statemgr, SubEngine &subengine)
  47. : SimpleConstraintManager(subengine),
  48. ISetFactory(statemgr.getAllocator()) {}
  49. const GRState *assumeSymNE(const GRState* state, SymbolRef sym,
  50. const llvm::APSInt& V,
  51. const llvm::APSInt& Adjustment);
  52. const GRState *assumeSymEQ(const GRState* state, SymbolRef sym,
  53. const llvm::APSInt& V,
  54. const llvm::APSInt& Adjustment);
  55. const GRState *assumeSymLT(const GRState* state, SymbolRef sym,
  56. const llvm::APSInt& V,
  57. const llvm::APSInt& Adjustment);
  58. const GRState *assumeSymGT(const GRState* state, SymbolRef sym,
  59. const llvm::APSInt& V,
  60. const llvm::APSInt& Adjustment);
  61. const GRState *assumeSymGE(const GRState* state, SymbolRef sym,
  62. const llvm::APSInt& V,
  63. const llvm::APSInt& Adjustment);
  64. const GRState *assumeSymLE(const GRState* state, SymbolRef sym,
  65. const llvm::APSInt& V,
  66. const llvm::APSInt& Adjustment);
  67. const GRState* AddEQ(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
  68. const GRState* AddNE(const GRState* state, SymbolRef sym, const llvm::APSInt& V);
  69. const llvm::APSInt* getSymVal(const GRState* state, SymbolRef sym) const;
  70. bool isNotEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
  71. const;
  72. bool isEqual(const GRState* state, SymbolRef sym, const llvm::APSInt& V)
  73. const;
  74. const GRState* removeDeadBindings(const GRState* state, SymbolReaper& SymReaper);
  75. void print(const GRState* state, llvm::raw_ostream& Out,
  76. const char* nl, const char *sep);
  77. };
  78. } // end anonymous namespace
  79. ConstraintManager* ento::CreateBasicConstraintManager(GRStateManager& statemgr,
  80. SubEngine &subengine) {
  81. return new BasicConstraintManager(statemgr, subengine);
  82. }
  83. const GRState*
  84. BasicConstraintManager::assumeSymNE(const GRState *state, SymbolRef sym,
  85. const llvm::APSInt &V,
  86. const llvm::APSInt &Adjustment) {
  87. // First, determine if sym == X, where X+Adjustment != V.
  88. llvm::APSInt Adjusted = V-Adjustment;
  89. if (const llvm::APSInt* X = getSymVal(state, sym)) {
  90. bool isFeasible = (*X != Adjusted);
  91. return isFeasible ? state : NULL;
  92. }
  93. // Second, determine if sym+Adjustment != V.
  94. if (isNotEqual(state, sym, Adjusted))
  95. return state;
  96. // If we reach here, sym is not a constant and we don't know if it is != V.
  97. // Make that assumption.
  98. return AddNE(state, sym, Adjusted);
  99. }
  100. const GRState*
  101. BasicConstraintManager::assumeSymEQ(const GRState *state, SymbolRef sym,
  102. const llvm::APSInt &V,
  103. const llvm::APSInt &Adjustment) {
  104. // First, determine if sym == X, where X+Adjustment != V.
  105. llvm::APSInt Adjusted = V-Adjustment;
  106. if (const llvm::APSInt* X = getSymVal(state, sym)) {
  107. bool isFeasible = (*X == Adjusted);
  108. return isFeasible ? state : NULL;
  109. }
  110. // Second, determine if sym+Adjustment != V.
  111. if (isNotEqual(state, sym, Adjusted))
  112. return NULL;
  113. // If we reach here, sym is not a constant and we don't know if it is == V.
  114. // Make that assumption.
  115. return AddEQ(state, sym, Adjusted);
  116. }
  117. // The logic for these will be handled in another ConstraintManager.
  118. const GRState*
  119. BasicConstraintManager::assumeSymLT(const GRState *state, SymbolRef sym,
  120. const llvm::APSInt &V,
  121. const llvm::APSInt &Adjustment) {
  122. // Is 'V' the smallest possible value?
  123. if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
  124. // sym cannot be any value less than 'V'. This path is infeasible.
  125. return NULL;
  126. }
  127. // FIXME: For now have assuming x < y be the same as assuming sym != V;
  128. return assumeSymNE(state, sym, V, Adjustment);
  129. }
  130. const GRState*
  131. BasicConstraintManager::assumeSymGT(const GRState *state, SymbolRef sym,
  132. const llvm::APSInt &V,
  133. const llvm::APSInt &Adjustment) {
  134. // Is 'V' the largest possible value?
  135. if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
  136. // sym cannot be any value greater than 'V'. This path is infeasible.
  137. return NULL;
  138. }
  139. // FIXME: For now have assuming x > y be the same as assuming sym != V;
  140. return assumeSymNE(state, sym, V, Adjustment);
  141. }
  142. const GRState*
  143. BasicConstraintManager::assumeSymGE(const GRState *state, SymbolRef sym,
  144. const llvm::APSInt &V,
  145. const llvm::APSInt &Adjustment) {
  146. // Reject a path if the value of sym is a constant X and !(X+Adj >= V).
  147. if (const llvm::APSInt *X = getSymVal(state, sym)) {
  148. bool isFeasible = (*X >= V-Adjustment);
  149. return isFeasible ? state : NULL;
  150. }
  151. // Sym is not a constant, but it is worth looking to see if V is the
  152. // maximum integer value.
  153. if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) {
  154. llvm::APSInt Adjusted = V-Adjustment;
  155. // If we know that sym != V (after adjustment), then this condition
  156. // is infeasible since there is no other value greater than V.
  157. bool isFeasible = !isNotEqual(state, sym, Adjusted);
  158. // If the path is still feasible then as a consequence we know that
  159. // 'sym+Adjustment == V' because there are no larger values.
  160. // Add this constraint.
  161. return isFeasible ? AddEQ(state, sym, Adjusted) : NULL;
  162. }
  163. return state;
  164. }
  165. const GRState*
  166. BasicConstraintManager::assumeSymLE(const GRState *state, SymbolRef sym,
  167. const llvm::APSInt &V,
  168. const llvm::APSInt &Adjustment) {
  169. // Reject a path if the value of sym is a constant X and !(X+Adj <= V).
  170. if (const llvm::APSInt* X = getSymVal(state, sym)) {
  171. bool isFeasible = (*X <= V-Adjustment);
  172. return isFeasible ? state : NULL;
  173. }
  174. // Sym is not a constant, but it is worth looking to see if V is the
  175. // minimum integer value.
  176. if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) {
  177. llvm::APSInt Adjusted = V-Adjustment;
  178. // If we know that sym != V (after adjustment), then this condition
  179. // is infeasible since there is no other value less than V.
  180. bool isFeasible = !isNotEqual(state, sym, Adjusted);
  181. // If the path is still feasible then as a consequence we know that
  182. // 'sym+Adjustment == V' because there are no smaller values.
  183. // Add this constraint.
  184. return isFeasible ? AddEQ(state, sym, Adjusted) : NULL;
  185. }
  186. return state;
  187. }
  188. const GRState* BasicConstraintManager::AddEQ(const GRState* state, SymbolRef sym,
  189. const llvm::APSInt& V) {
  190. // Create a new state with the old binding replaced.
  191. return state->set<ConstEq>(sym, &state->getBasicVals().getValue(V));
  192. }
  193. const GRState* BasicConstraintManager::AddNE(const GRState* state, SymbolRef sym,
  194. const llvm::APSInt& V) {
  195. // First, retrieve the NE-set associated with the given symbol.
  196. ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
  197. GRState::IntSetTy S = T ? *T : ISetFactory.getEmptySet();
  198. // Now add V to the NE set.
  199. S = ISetFactory.add(S, &state->getBasicVals().getValue(V));
  200. // Create a new state with the old binding replaced.
  201. return state->set<ConstNotEq>(sym, S);
  202. }
  203. const llvm::APSInt* BasicConstraintManager::getSymVal(const GRState* state,
  204. SymbolRef sym) const {
  205. const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
  206. return T ? *T : NULL;
  207. }
  208. bool BasicConstraintManager::isNotEqual(const GRState* state, SymbolRef sym,
  209. const llvm::APSInt& V) const {
  210. // Retrieve the NE-set associated with the given symbol.
  211. const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);
  212. // See if V is present in the NE-set.
  213. return T ? T->contains(&state->getBasicVals().getValue(V)) : false;
  214. }
  215. bool BasicConstraintManager::isEqual(const GRState* state, SymbolRef sym,
  216. const llvm::APSInt& V) const {
  217. // Retrieve the EQ-set associated with the given symbol.
  218. const ConstEqTy::data_type* T = state->get<ConstEq>(sym);
  219. // See if V is present in the EQ-set.
  220. return T ? **T == V : false;
  221. }
  222. /// Scan all symbols referenced by the constraints. If the symbol is not alive
  223. /// as marked in LSymbols, mark it as dead in DSymbols.
  224. const GRState*
  225. BasicConstraintManager::removeDeadBindings(const GRState* state,
  226. SymbolReaper& SymReaper) {
  227. ConstEqTy CE = state->get<ConstEq>();
  228. ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>();
  229. for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) {
  230. SymbolRef sym = I.getKey();
  231. if (SymReaper.maybeDead(sym))
  232. CE = CEFactory.remove(CE, sym);
  233. }
  234. state = state->set<ConstEq>(CE);
  235. ConstNotEqTy CNE = state->get<ConstNotEq>();
  236. ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>();
  237. for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) {
  238. SymbolRef sym = I.getKey();
  239. if (SymReaper.maybeDead(sym))
  240. CNE = CNEFactory.remove(CNE, sym);
  241. }
  242. return state->set<ConstNotEq>(CNE);
  243. }
  244. void BasicConstraintManager::print(const GRState* state, llvm::raw_ostream& Out,
  245. const char* nl, const char *sep) {
  246. // Print equality constraints.
  247. ConstEqTy CE = state->get<ConstEq>();
  248. if (!CE.isEmpty()) {
  249. Out << nl << sep << "'==' constraints:";
  250. for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I)
  251. Out << nl << " $" << I.getKey() << " : " << *I.getData();
  252. }
  253. // Print != constraints.
  254. ConstNotEqTy CNE = state->get<ConstNotEq>();
  255. if (!CNE.isEmpty()) {
  256. Out << nl << sep << "'!=' constraints:";
  257. for (ConstNotEqTy::iterator I = CNE.begin(), EI = CNE.end(); I!=EI; ++I) {
  258. Out << nl << " $" << I.getKey() << " : ";
  259. bool isFirst = true;
  260. GRState::IntSetTy::iterator J = I.getData().begin(),
  261. EJ = I.getData().end();
  262. for ( ; J != EJ; ++J) {
  263. if (isFirst) isFirst = false;
  264. else Out << ", ";
  265. Out << (*J)->getSExtValue(); // Hack: should print to raw_ostream.
  266. }
  267. }
  268. }
  269. }