blob: 321381b045ad35c2a6c422b478a571082774b050 [file] [log] [blame]
Ted Kremenek45021952009-02-14 17:08:39 +00001//== 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
15#include "SimpleConstraintManager.h"
Ted Kremenek1309f9a2010-01-25 04:41:41 +000016#include "clang/Checker/PathSensitive/GRExprEngine.h"
17#include "clang/Checker/PathSensitive/GRState.h"
18#include "clang/Checker/PathSensitive/Checker.h"
Ted Kremenek45021952009-02-14 17:08:39 +000019
20namespace clang {
21
22SimpleConstraintManager::~SimpleConstraintManager() {}
23
Ted Kremenek66b52712009-03-11 02:22:59 +000024bool SimpleConstraintManager::canReasonAbout(SVal X) const {
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000025 if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) {
26 const SymExpr *SE = SymVal->getSymbolicExpression();
Mike Stump1eb44332009-09-09 15:08:12 +000027
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000028 if (isa<SymbolData>(SE))
29 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000030
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000031 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
32 switch (SIE->getOpcode()) {
33 // We don't reason yet about bitwise-constraints on symbolic values.
34 case BinaryOperator::And:
35 case BinaryOperator::Or:
36 case BinaryOperator::Xor:
37 return false;
Jordy Roseba0f61c2010-06-18 22:49:11 +000038 // We don't reason yet about these arithmetic constraints on
39 // symbolic values.
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000040 case BinaryOperator::Mul:
41 case BinaryOperator::Div:
42 case BinaryOperator::Rem:
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000043 case BinaryOperator::Shl:
44 case BinaryOperator::Shr:
45 return false;
46 // All other cases.
47 default:
48 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000049 }
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000050 }
51
52 return false;
Ted Kremenek7de20fe2009-03-11 02:29:48 +000053 }
54
Ted Kremenek66b52712009-03-11 02:22:59 +000055 return true;
56}
Mike Stump1eb44332009-09-09 15:08:12 +000057
Ted Kremeneka591bc02009-06-18 22:57:13 +000058const GRState *SimpleConstraintManager::Assume(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +000059 DefinedSVal Cond,
60 bool Assumption) {
Ted Kremenek45021952009-02-14 17:08:39 +000061 if (isa<NonLoc>(Cond))
Ted Kremeneka591bc02009-06-18 22:57:13 +000062 return Assume(state, cast<NonLoc>(Cond), Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000063 else
Ted Kremeneka591bc02009-06-18 22:57:13 +000064 return Assume(state, cast<Loc>(Cond), Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000065}
66
Ted Kremenek32a58082010-01-05 00:15:18 +000067const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc cond,
68 bool assumption) {
69 state = AssumeAux(state, cond, assumption);
70 return SU.ProcessAssume(state, cond, assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000071}
72
Ted Kremeneka591bc02009-06-18 22:57:13 +000073const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
74 Loc Cond, bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +000075
Ted Kremeneka591bc02009-06-18 22:57:13 +000076 BasicValueFactory &BasicVals = state->getBasicVals();
Ted Kremenek45021952009-02-14 17:08:39 +000077
78 switch (Cond.getSubKind()) {
79 default:
80 assert (false && "'Assume' not implemented for this Loc.");
Ted Kremeneka591bc02009-06-18 22:57:13 +000081 return state;
Ted Kremenek45021952009-02-14 17:08:39 +000082
Ted Kremenek45021952009-02-14 17:08:39 +000083 case loc::MemRegionKind: {
84 // FIXME: Should this go into the storemanager?
Mike Stump1eb44332009-09-09 15:08:12 +000085
Ted Kremeneka591bc02009-06-18 22:57:13 +000086 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
87 const SubRegion *SubR = dyn_cast<SubRegion>(R);
Ted Kremenek45021952009-02-14 17:08:39 +000088
89 while (SubR) {
90 // FIXME: now we only find the first symbolic region.
Ted Kremeneka591bc02009-06-18 22:57:13 +000091 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
Jordy Roseba0f61c2010-06-18 22:49:11 +000092 const llvm::APSInt &zero = BasicVals.getZeroWithPtrWidth();
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000093 if (Assumption)
Jordy Roseba0f61c2010-06-18 22:49:11 +000094 return AssumeSymNE(state, SymR->getSymbol(), zero, zero);
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000095 else
Jordy Roseba0f61c2010-06-18 22:49:11 +000096 return AssumeSymEQ(state, SymR->getSymbol(), zero, zero);
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000097 }
Ted Kremenek45021952009-02-14 17:08:39 +000098 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
99 }
Mike Stump1eb44332009-09-09 15:08:12 +0000100
Ted Kremenek45021952009-02-14 17:08:39 +0000101 // FALL-THROUGH.
102 }
Mike Stump1eb44332009-09-09 15:08:12 +0000103
Ted Kremenek45021952009-02-14 17:08:39 +0000104 case loc::GotoLabelKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000105 return Assumption ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000106
107 case loc::ConcreteIntKind: {
Mike Stump1eb44332009-09-09 15:08:12 +0000108 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000109 bool isFeasible = b ? Assumption : !Assumption;
110 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000111 }
112 } // end switch
113}
114
Ted Kremeneka591bc02009-06-18 22:57:13 +0000115const GRState *SimpleConstraintManager::Assume(const GRState *state,
Ted Kremenek32a58082010-01-05 00:15:18 +0000116 NonLoc cond,
117 bool assumption) {
118 state = AssumeAux(state, cond, assumption);
119 return SU.ProcessAssume(state, cond, assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000120}
121
Jordy Roseba0f61c2010-06-18 22:49:11 +0000122static BinaryOperator::Opcode NegateComparison(BinaryOperator::Opcode op) {
123 // FIXME: This should probably be part of BinaryOperator, since this isn't
124 // the only place it's used. (This code was copied from SimpleSValuator.cpp.)
125 switch (op) {
126 default:
127 assert(false && "Invalid opcode.");
128 case BinaryOperator::LT: return BinaryOperator::GE;
129 case BinaryOperator::GT: return BinaryOperator::LE;
130 case BinaryOperator::LE: return BinaryOperator::GT;
131 case BinaryOperator::GE: return BinaryOperator::LT;
132 case BinaryOperator::EQ: return BinaryOperator::NE;
133 case BinaryOperator::NE: return BinaryOperator::EQ;
134 }
135}
136
Ted Kremeneka591bc02009-06-18 22:57:13 +0000137const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
138 NonLoc Cond,
139 bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +0000140
Jordy Roseba0f61c2010-06-18 22:49:11 +0000141 // We cannot reason about SymSymExprs,
142 // and can only reason about some SymIntExprs.
Zhongxing Xua129eb92009-03-25 05:58:37 +0000143 if (!canReasonAbout(Cond)) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000144 // Just return the current state indicating that the path is feasible.
145 // This may be an over-approximation of what is possible.
146 return state;
Mike Stump1eb44332009-09-09 15:08:12 +0000147 }
Zhongxing Xua129eb92009-03-25 05:58:37 +0000148
Ted Kremeneka591bc02009-06-18 22:57:13 +0000149 BasicValueFactory &BasicVals = state->getBasicVals();
150 SymbolManager &SymMgr = state->getSymbolManager();
Ted Kremenek45021952009-02-14 17:08:39 +0000151
152 switch (Cond.getSubKind()) {
153 default:
154 assert(false && "'Assume' not implemented for this NonLoc");
155
156 case nonloc::SymbolValKind: {
157 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
158 SymbolRef sym = SV.getSymbol();
Mike Stump1eb44332009-09-09 15:08:12 +0000159 QualType T = SymMgr.getType(sym);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000160 const llvm::APSInt &zero = BasicVals.getValue(0, T);
Jordy Roseba0f61c2010-06-18 22:49:11 +0000161 if (Assumption)
162 return AssumeSymNE(state, sym, zero, zero);
163 else
164 return AssumeSymEQ(state, sym, zero, zero);
Ted Kremenek45021952009-02-14 17:08:39 +0000165 }
166
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000167 case nonloc::SymExprValKind: {
168 nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
Ted Kremenek80417472009-09-25 00:18:15 +0000169
Jordy Roseba0f61c2010-06-18 22:49:11 +0000170 // For now, we only handle expressions whose RHS is an integer.
171 // All other expressions are assumed to be feasible.
172 const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression());
173 if (!SE)
174 return state;
Mike Stump1eb44332009-09-09 15:08:12 +0000175
Jordy Roseba0f61c2010-06-18 22:49:11 +0000176 BinaryOperator::Opcode op = SE->getOpcode();
Jordy Rose5ca129c2010-06-27 01:20:56 +0000177 // Implicitly compare non-comparison expressions to 0.
178 if (!BinaryOperator::isComparisonOp(op)) {
179 QualType T = SymMgr.getType(SE);
180 const llvm::APSInt &zero = BasicVals.getValue(0, T);
181 op = (Assumption ? BinaryOperator::NE : BinaryOperator::EQ);
182 return AssumeSymRel(state, SE, op, zero);
183 }
Jordy Roseba0f61c2010-06-18 22:49:11 +0000184
185 // From here on out, op is the real comparison we'll be testing.
186 if (!Assumption)
187 op = NegateComparison(op);
188
Jordy Roseb4954a42010-06-21 20:15:15 +0000189 return AssumeSymRel(state, SE->getLHS(), op, SE->getRHS());
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000190 }
Ted Kremenek45021952009-02-14 17:08:39 +0000191
192 case nonloc::ConcreteIntKind: {
193 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000194 bool isFeasible = b ? Assumption : !Assumption;
195 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000196 }
197
198 case nonloc::LocAsIntegerKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000199 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
200 Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000201 } // end switch
202}
203
Jordy Roseba0f61c2010-06-18 22:49:11 +0000204const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
205 const SymExpr *LHS,
206 BinaryOperator::Opcode op,
207 const llvm::APSInt& Int) {
208 assert(BinaryOperator::isComparisonOp(op) &&
209 "Non-comparison ops should be rewritten as comparisons to zero.");
Ted Kremenek45021952009-02-14 17:08:39 +0000210
Jordy Roseba0f61c2010-06-18 22:49:11 +0000211 // 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.
Jordy Roseb4954a42010-06-21 20:15:15 +0000218 llvm::APSInt Adjustment;
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000219
Jordy Roseba0f61c2010-06-18 22:49:11 +0000220 // First check if the LHS is a simple symbol reference.
221 SymbolRef Sym = dyn_cast<SymbolData>(LHS);
Jordy Roseb4954a42010-06-21 20:15:15 +0000222 if (Sym) {
223 Adjustment = 0;
224 } else {
Jordy Roseba0f61c2010-06-18 22:49:11 +0000225 // Next, see if it's a "($sym+constant1)" expression.
226 const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS);
Mike Stump1eb44332009-09-09 15:08:12 +0000227
Jordy Roseba0f61c2010-06-18 22:49:11 +0000228 // We don't handle "($sym1+$sym2)".
229 // Give up and assume the constraint is feasible.
230 if (!SE)
231 return state;
232
233 // We don't handle "(<expr>+constant1)".
234 // Give up and assume the constraint is feasible.
235 Sym = dyn_cast<SymbolData>(SE->getLHS());
236 if (!Sym)
237 return state;
238
239 // Get the constant out of the expression "($sym+constant1)".
240 switch (SE->getOpcode()) {
241 case BinaryOperator::Add:
242 Adjustment = SE->getRHS();
243 break;
244 case BinaryOperator::Sub:
245 Adjustment = -SE->getRHS();
246 break;
247 default:
248 // We don't handle non-additive operators.
249 // Give up and assume the constraint is feasible.
250 return state;
251 }
252 }
253
Jordy Roseb4954a42010-06-21 20:15:15 +0000254 // FIXME: This next section is a hack. It silently converts the integers to
255 // be of the same type as the symbol, which is not always correct. Really the
256 // comparisons should be performed using the Int's type, then mapped back to
257 // the symbol's range of values.
258 GRStateManager &StateMgr = state->getStateManager();
259 ASTContext &Ctx = StateMgr.getContext();
260
261 QualType T = Sym->getType(Ctx);
262 assert(T->isIntegerType() || Loc::IsLocType(T));
263 unsigned bitwidth = Ctx.getTypeSize(T);
264 bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
265
266 // Convert the adjustment.
267 Adjustment.setIsUnsigned(isSymUnsigned);
268 Adjustment.extOrTrunc(bitwidth);
269
270 // Convert the right-hand side integer.
271 llvm::APSInt ConvertedInt(Int, isSymUnsigned);
272 ConvertedInt.extOrTrunc(bitwidth);
273
Jordy Roseba0f61c2010-06-18 22:49:11 +0000274 switch (op) {
Ted Kremenek45021952009-02-14 17:08:39 +0000275 default:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000276 // No logic yet for other operators. Assume the constraint is feasible.
277 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000278
279 case BinaryOperator::EQ:
Jordy Roseb4954a42010-06-21 20:15:15 +0000280 return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000281
282 case BinaryOperator::NE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000283 return AssumeSymNE(state, Sym, ConvertedInt, Adjustment);
Jordy Roseba0f61c2010-06-18 22:49:11 +0000284
Ted Kremenek45021952009-02-14 17:08:39 +0000285 case BinaryOperator::GT:
Jordy Roseb4954a42010-06-21 20:15:15 +0000286 return AssumeSymGT(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000287
288 case BinaryOperator::GE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000289 return AssumeSymGE(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000290
291 case BinaryOperator::LT:
Jordy Roseb4954a42010-06-21 20:15:15 +0000292 return AssumeSymLT(state, Sym, ConvertedInt, Adjustment);
Mike Stump1eb44332009-09-09 15:08:12 +0000293
Ted Kremenek45021952009-02-14 17:08:39 +0000294 case BinaryOperator::LE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000295 return AssumeSymLE(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000296 } // end switch
297}
298
Ted Kremeneka591bc02009-06-18 22:57:13 +0000299const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000300 DefinedSVal Idx,
301 DefinedSVal UpperBound,
Mike Stump1eb44332009-09-09 15:08:12 +0000302 bool Assumption) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000303
Ted Kremenek45021952009-02-14 17:08:39 +0000304 // Only support ConcreteInt for now.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000305 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
306 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000307
Ted Kremenekf1b82272009-06-18 23:20:05 +0000308 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
Ted Kremenek45021952009-02-14 17:08:39 +0000309 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
310 // IdxV might be too narrow.
311 if (IdxV.getBitWidth() < Zero.getBitWidth())
312 IdxV.extend(Zero.getBitWidth());
313 // UBV might be too narrow, too.
314 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
315 if (UBV.getBitWidth() < Zero.getBitWidth())
316 UBV.extend(Zero.getBitWidth());
317
318 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000319 bool isFeasible = Assumption ? InBound : !InBound;
320 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000321}
322
323} // end of namespace clang