SimpleConstraintManager.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. //== SimpleConstraintManager.cpp --------------------------------*- 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 SimpleConstraintManager, a class that holds code shared
  11. // between BasicConstraintManager and RangeConstraintManager.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "SimpleConstraintManager.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  17. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  18. namespace clang {
  19. namespace ento {
  20. SimpleConstraintManager::~SimpleConstraintManager() {}
  21. bool SimpleConstraintManager::canReasonAbout(SVal X) const {
  22. Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
  23. if (SymVal && SymVal->isExpression()) {
  24. const SymExpr *SE = SymVal->getSymbol();
  25. if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
  26. switch (SIE->getOpcode()) {
  27. // We don't reason yet about bitwise-constraints on symbolic values.
  28. case BO_And:
  29. case BO_Or:
  30. case BO_Xor:
  31. return false;
  32. // We don't reason yet about these arithmetic constraints on
  33. // symbolic values.
  34. case BO_Mul:
  35. case BO_Div:
  36. case BO_Rem:
  37. case BO_Shl:
  38. case BO_Shr:
  39. return false;
  40. // All other cases.
  41. default:
  42. return true;
  43. }
  44. }
  45. if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
  46. if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
  47. // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
  48. if (Loc::isLocType(SSE->getLHS()->getType())) {
  49. assert(Loc::isLocType(SSE->getRHS()->getType()));
  50. return true;
  51. }
  52. }
  53. }
  54. return false;
  55. }
  56. return true;
  57. }
  58. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
  59. DefinedSVal Cond,
  60. bool Assumption) {
  61. if (Optional<NonLoc> NV = Cond.getAs<NonLoc>())
  62. return assume(state, *NV, Assumption);
  63. return assume(state, Cond.castAs<Loc>(), Assumption);
  64. }
  65. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,
  66. bool assumption) {
  67. state = assumeAux(state, cond, assumption);
  68. if (NotifyAssumeClients && SU)
  69. return SU->processAssume(state, cond, assumption);
  70. return state;
  71. }
  72. ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
  73. Loc Cond, bool Assumption) {
  74. switch (Cond.getSubKind()) {
  75. default:
  76. assert (false && "'Assume' not implemented for this Loc.");
  77. return state;
  78. case loc::MemRegionKind: {
  79. // FIXME: Should this go into the storemanager?
  80. const MemRegion *R = Cond.castAs<loc::MemRegionVal>().getRegion();
  81. // FIXME: now we only find the first symbolic region.
  82. if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
  83. const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();
  84. if (Assumption)
  85. return assumeSymNE(state, SymR->getSymbol(), zero, zero);
  86. else
  87. return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
  88. }
  89. // FALL-THROUGH.
  90. }
  91. case loc::GotoLabelKind:
  92. return Assumption ? state : NULL;
  93. case loc::ConcreteIntKind: {
  94. bool b = Cond.castAs<loc::ConcreteInt>().getValue() != 0;
  95. bool isFeasible = b ? Assumption : !Assumption;
  96. return isFeasible ? state : NULL;
  97. }
  98. } // end switch
  99. }
  100. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
  101. NonLoc cond,
  102. bool assumption) {
  103. state = assumeAux(state, cond, assumption);
  104. if (NotifyAssumeClients && SU)
  105. return SU->processAssume(state, cond, assumption);
  106. return state;
  107. }
  108. ProgramStateRef
  109. SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
  110. SymbolRef Sym, bool Assumption) {
  111. BasicValueFactory &BVF = getBasicVals();
  112. QualType T = Sym->getType();
  113. // None of the constraint solvers currently support non-integer types.
  114. if (!T->isIntegralOrEnumerationType())
  115. return State;
  116. const llvm::APSInt &zero = BVF.getValue(0, T);
  117. if (Assumption)
  118. return assumeSymNE(State, Sym, zero, zero);
  119. else
  120. return assumeSymEQ(State, Sym, zero, zero);
  121. }
  122. ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
  123. NonLoc Cond,
  124. bool Assumption) {
  125. // We cannot reason about SymSymExprs, and can only reason about some
  126. // SymIntExprs.
  127. if (!canReasonAbout(Cond)) {
  128. // Just add the constraint to the expression without trying to simplify.
  129. SymbolRef sym = Cond.getAsSymExpr();
  130. return assumeAuxForSymbol(state, sym, Assumption);
  131. }
  132. switch (Cond.getSubKind()) {
  133. default:
  134. llvm_unreachable("'Assume' not implemented for this NonLoc");
  135. case nonloc::SymbolValKind: {
  136. nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
  137. SymbolRef sym = SV.getSymbol();
  138. assert(sym);
  139. // Handle SymbolData.
  140. if (!SV.isExpression()) {
  141. return assumeAuxForSymbol(state, sym, Assumption);
  142. // Handle symbolic expression.
  143. } else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) {
  144. // We can only simplify expressions whose RHS is an integer.
  145. BinaryOperator::Opcode op = SE->getOpcode();
  146. if (BinaryOperator::isComparisonOp(op)) {
  147. if (!Assumption)
  148. op = BinaryOperator::negateComparisonOp(op);
  149. return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
  150. }
  151. } else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) {
  152. // Translate "a != b" to "(b - a) != 0".
  153. // We invert the order of the operands as a heuristic for how loop
  154. // conditions are usually written ("begin != end") as compared to length
  155. // calculations ("end - begin"). The more correct thing to do would be to
  156. // canonicalize "a - b" and "b - a", which would allow us to treat
  157. // "a != b" and "b != a" the same.
  158. SymbolManager &SymMgr = getSymbolManager();
  159. BinaryOperator::Opcode Op = SSE->getOpcode();
  160. assert(BinaryOperator::isComparisonOp(Op));
  161. // For now, we only support comparing pointers.
  162. assert(Loc::isLocType(SSE->getLHS()->getType()));
  163. assert(Loc::isLocType(SSE->getRHS()->getType()));
  164. QualType DiffTy = SymMgr.getContext().getPointerDiffType();
  165. SymbolRef Subtraction = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
  166. SSE->getLHS(), DiffTy);
  167. const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
  168. Op = BinaryOperator::reverseComparisonOp(Op);
  169. if (!Assumption)
  170. Op = BinaryOperator::negateComparisonOp(Op);
  171. return assumeSymRel(state, Subtraction, Op, Zero);
  172. }
  173. // If we get here, there's nothing else we can do but treat the symbol as
  174. // opaque.
  175. return assumeAuxForSymbol(state, sym, Assumption);
  176. }
  177. case nonloc::ConcreteIntKind: {
  178. bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
  179. bool isFeasible = b ? Assumption : !Assumption;
  180. return isFeasible ? state : NULL;
  181. }
  182. case nonloc::LocAsIntegerKind:
  183. return assumeAux(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
  184. Assumption);
  185. } // end switch
  186. }
  187. static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
  188. // Is it a "($sym+constant1)" expression?
  189. if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
  190. BinaryOperator::Opcode Op = SE->getOpcode();
  191. if (Op == BO_Add || Op == BO_Sub) {
  192. Sym = SE->getLHS();
  193. Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
  194. // Don't forget to negate the adjustment if it's being subtracted.
  195. // This should happen /after/ promotion, in case the value being
  196. // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
  197. if (Op == BO_Sub)
  198. Adjustment = -Adjustment;
  199. }
  200. }
  201. }
  202. ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
  203. const SymExpr *LHS,
  204. BinaryOperator::Opcode op,
  205. const llvm::APSInt& Int) {
  206. assert(BinaryOperator::isComparisonOp(op) &&
  207. "Non-comparison ops should be rewritten as comparisons to zero.");
  208. // Get the type used for calculating wraparound.
  209. BasicValueFactory &BVF = getBasicVals();
  210. APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
  211. // We only handle simple comparisons of the form "$sym == constant"
  212. // or "($sym+constant1) == constant2".
  213. // The adjustment is "constant1" in the above expression. It's used to
  214. // "slide" the solution range around for modular arithmetic. For example,
  215. // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
  216. // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
  217. // the subclasses of SimpleConstraintManager to handle the adjustment.
  218. SymbolRef Sym = LHS;
  219. llvm::APSInt Adjustment = WraparoundType.getZeroValue();
  220. computeAdjustment(Sym, Adjustment);
  221. // Convert the right-hand side integer as necessary.
  222. APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
  223. llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
  224. // Prefer unsigned comparisons.
  225. if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
  226. ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
  227. Adjustment.setIsSigned(false);
  228. switch (op) {
  229. default:
  230. llvm_unreachable("invalid operation not caught by assertion above");
  231. case BO_EQ:
  232. return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
  233. case BO_NE:
  234. return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
  235. case BO_GT:
  236. return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
  237. case BO_GE:
  238. return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
  239. case BO_LT:
  240. return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
  241. case BO_LE:
  242. return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
  243. } // end switch
  244. }
  245. } // end of namespace ento
  246. } // end of namespace clang