1 //== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines SimpleConstraintManager, a class that holds code shared
11 // between BasicConstraintManager and RangeConstraintManager.
13 //===----------------------------------------------------------------------===//
15 #include "SimpleConstraintManager.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
24 SimpleConstraintManager::~SimpleConstraintManager() {}
26 bool SimpleConstraintManager::canReasonAbout(SVal X) const {
27 nonloc::SymbolVal *SymVal = dyn_cast<nonloc::SymbolVal>(&X);
28 if (SymVal && SymVal->isExpression()) {
29 const SymExpr *SE = SymVal->getSymbol();
31 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
32 switch (SIE->getOpcode()) {
33 // We don't reason yet about bitwise-constraints on symbolic values.
38 // We don't reason yet about these arithmetic constraints on
58 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
61 if (isa<NonLoc>(Cond))
62 return assume(state, cast<NonLoc>(Cond), Assumption);
64 return assume(state, cast<Loc>(Cond), Assumption);
67 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state, Loc cond,
69 state = assumeAux(state, cond, assumption);
70 if (NotifyAssumeClients && SU)
71 return SU->processAssume(state, cond, assumption);
75 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
76 Loc Cond, bool Assumption) {
77 switch (Cond.getSubKind()) {
79 assert (false && "'Assume' not implemented for this Loc.");
82 case loc::MemRegionKind: {
83 // FIXME: Should this go into the storemanager?
85 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
86 const SubRegion *SubR = dyn_cast<SubRegion>(R);
89 // FIXME: now we only find the first symbolic region.
90 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
91 const llvm::APSInt &zero = getBasicVals().getZeroWithPtrWidth();
93 return assumeSymNE(state, SymR->getSymbol(), zero, zero);
95 return assumeSymEQ(state, SymR->getSymbol(), zero, zero);
97 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
103 case loc::GotoLabelKind:
104 return Assumption ? state : NULL;
106 case loc::ConcreteIntKind: {
107 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
108 bool isFeasible = b ? Assumption : !Assumption;
109 return isFeasible ? state : NULL;
114 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
117 state = assumeAux(state, cond, assumption);
118 if (NotifyAssumeClients && SU)
119 return SU->processAssume(state, cond, assumption);
123 static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
124 // FIXME: This should probably be part of BinaryOperator, since this isn't
125 // the only place it's used. (This code was copied from SimpleSValBuilder.cpp.)
128 llvm_unreachable("Invalid opcode.");
129 case BO_LT: return BO_GE;
130 case BO_GT: return BO_LE;
131 case BO_LE: return BO_GT;
132 case BO_GE: return BO_LT;
133 case BO_EQ: return BO_NE;
134 case BO_NE: return BO_EQ;
140 SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
141 SymbolRef Sym, bool Assumption) {
142 BasicValueFactory &BVF = getBasicVals();
143 QualType T = Sym->getType();
145 // None of the constraint solvers currently support non-integer types.
146 if (!T->isIntegerType())
149 const llvm::APSInt &zero = BVF.getValue(0, T);
151 return assumeSymNE(State, Sym, zero, zero);
153 return assumeSymEQ(State, Sym, zero, zero);
156 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
160 // We cannot reason about SymSymExprs, and can only reason about some
162 if (!canReasonAbout(Cond)) {
163 // Just add the constraint to the expression without trying to simplify.
164 SymbolRef sym = Cond.getAsSymExpr();
165 return assumeAuxForSymbol(state, sym, Assumption);
168 BasicValueFactory &BasicVals = getBasicVals();
170 switch (Cond.getSubKind()) {
172 llvm_unreachable("'Assume' not implemented for this NonLoc");
174 case nonloc::SymbolValKind: {
175 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
176 SymbolRef sym = SV.getSymbol();
179 // Handle SymbolData.
180 if (!SV.isExpression()) {
181 return assumeAuxForSymbol(state, sym, Assumption);
183 // Handle symbolic expression.
185 // We can only simplify expressions whose RHS is an integer.
186 const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym);
188 return assumeAuxForSymbol(state, sym, Assumption);
190 BinaryOperator::Opcode op = SE->getOpcode();
191 // Implicitly compare non-comparison expressions to 0.
192 if (!BinaryOperator::isComparisonOp(op)) {
193 QualType T = SE->getType();
194 const llvm::APSInt &zero = BasicVals.getValue(0, T);
195 op = (Assumption ? BO_NE : BO_EQ);
196 return assumeSymRel(state, SE, op, zero);
198 // From here on out, op is the real comparison we'll be testing.
200 op = NegateComparison(op);
202 return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
206 case nonloc::ConcreteIntKind: {
207 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
208 bool isFeasible = b ? Assumption : !Assumption;
209 return isFeasible ? state : NULL;
212 case nonloc::LocAsIntegerKind:
213 return assumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
218 static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
219 // Is it a "($sym+constant1)" expression?
220 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
221 BinaryOperator::Opcode Op = SE->getOpcode();
222 if (Op == BO_Add || Op == BO_Sub) {
224 Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
226 // Don't forget to negate the adjustment if it's being subtracted.
227 // This should happen /after/ promotion, in case the value being
228 // subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
230 Adjustment = -Adjustment;
235 ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
237 BinaryOperator::Opcode op,
238 const llvm::APSInt& Int) {
239 assert(BinaryOperator::isComparisonOp(op) &&
240 "Non-comparison ops should be rewritten as comparisons to zero.");
242 // Get the type used for calculating wraparound.
243 BasicValueFactory &BVF = getBasicVals();
244 APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
246 // We only handle simple comparisons of the form "$sym == constant"
247 // or "($sym+constant1) == constant2".
248 // The adjustment is "constant1" in the above expression. It's used to
249 // "slide" the solution range around for modular arithmetic. For example,
250 // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
251 // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
252 // the subclasses of SimpleConstraintManager to handle the adjustment.
254 llvm::APSInt Adjustment = WraparoundType.getZeroValue();
255 computeAdjustment(Sym, Adjustment);
257 // Convert the right-hand side integer as necessary.
258 APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
259 llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
263 // No logic yet for other operators. assume the constraint is feasible.
267 return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
270 return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
273 return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
276 return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
279 return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
282 return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
286 } // end of namespace ento
288 } // end of namespace clang