blob: a1594a9e9eeed2d962ae5a2a4c986135a51eb50f [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();
177 // FIXME: We should implicitly compare non-comparison expressions to 0.
178 if (!BinaryOperator::isComparisonOp(op))
179 return state;
180
181 // From here on out, op is the real comparison we'll be testing.
182 if (!Assumption)
183 op = NegateComparison(op);
184
Jordy Roseb4954a42010-06-21 20:15:15 +0000185 return AssumeSymRel(state, SE->getLHS(), op, SE->getRHS());
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000186 }
Ted Kremenek45021952009-02-14 17:08:39 +0000187
188 case nonloc::ConcreteIntKind: {
189 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000190 bool isFeasible = b ? Assumption : !Assumption;
191 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000192 }
193
194 case nonloc::LocAsIntegerKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000195 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
196 Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000197 } // end switch
198}
199
Jordy Roseba0f61c2010-06-18 22:49:11 +0000200const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
201 const SymExpr *LHS,
202 BinaryOperator::Opcode op,
203 const llvm::APSInt& Int) {
204 assert(BinaryOperator::isComparisonOp(op) &&
205 "Non-comparison ops should be rewritten as comparisons to zero.");
Ted Kremenek45021952009-02-14 17:08:39 +0000206
Jordy Roseba0f61c2010-06-18 22:49:11 +0000207 // We only handle simple comparisons of the form "$sym == constant"
208 // or "($sym+constant1) == constant2".
209 // The adjustment is "constant1" in the above expression. It's used to
210 // "slide" the solution range around for modular arithmetic. For example,
211 // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
212 // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
213 // the subclasses of SimpleConstraintManager to handle the adjustment.
Jordy Roseb4954a42010-06-21 20:15:15 +0000214 llvm::APSInt Adjustment;
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000215
Jordy Roseba0f61c2010-06-18 22:49:11 +0000216 // First check if the LHS is a simple symbol reference.
217 SymbolRef Sym = dyn_cast<SymbolData>(LHS);
Jordy Roseb4954a42010-06-21 20:15:15 +0000218 if (Sym) {
219 Adjustment = 0;
220 } else {
Jordy Roseba0f61c2010-06-18 22:49:11 +0000221 // Next, see if it's a "($sym+constant1)" expression.
222 const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS);
Mike Stump1eb44332009-09-09 15:08:12 +0000223
Jordy Roseba0f61c2010-06-18 22:49:11 +0000224 // We don't handle "($sym1+$sym2)".
225 // Give up and assume the constraint is feasible.
226 if (!SE)
227 return state;
228
229 // We don't handle "(<expr>+constant1)".
230 // Give up and assume the constraint is feasible.
231 Sym = dyn_cast<SymbolData>(SE->getLHS());
232 if (!Sym)
233 return state;
234
235 // Get the constant out of the expression "($sym+constant1)".
236 switch (SE->getOpcode()) {
237 case BinaryOperator::Add:
238 Adjustment = SE->getRHS();
239 break;
240 case BinaryOperator::Sub:
241 Adjustment = -SE->getRHS();
242 break;
243 default:
244 // We don't handle non-additive operators.
245 // Give up and assume the constraint is feasible.
246 return state;
247 }
248 }
249
Jordy Roseb4954a42010-06-21 20:15:15 +0000250 // FIXME: This next section is a hack. It silently converts the integers to
251 // be of the same type as the symbol, which is not always correct. Really the
252 // comparisons should be performed using the Int's type, then mapped back to
253 // the symbol's range of values.
254 GRStateManager &StateMgr = state->getStateManager();
255 ASTContext &Ctx = StateMgr.getContext();
256
257 QualType T = Sym->getType(Ctx);
258 assert(T->isIntegerType() || Loc::IsLocType(T));
259 unsigned bitwidth = Ctx.getTypeSize(T);
260 bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);
261
262 // Convert the adjustment.
263 Adjustment.setIsUnsigned(isSymUnsigned);
264 Adjustment.extOrTrunc(bitwidth);
265
266 // Convert the right-hand side integer.
267 llvm::APSInt ConvertedInt(Int, isSymUnsigned);
268 ConvertedInt.extOrTrunc(bitwidth);
269
Jordy Roseba0f61c2010-06-18 22:49:11 +0000270 switch (op) {
Ted Kremenek45021952009-02-14 17:08:39 +0000271 default:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000272 // No logic yet for other operators. Assume the constraint is feasible.
273 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000274
275 case BinaryOperator::EQ:
Jordy Roseb4954a42010-06-21 20:15:15 +0000276 return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000277
278 case BinaryOperator::NE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000279 return AssumeSymNE(state, Sym, ConvertedInt, Adjustment);
Jordy Roseba0f61c2010-06-18 22:49:11 +0000280
Ted Kremenek45021952009-02-14 17:08:39 +0000281 case BinaryOperator::GT:
Jordy Roseb4954a42010-06-21 20:15:15 +0000282 return AssumeSymGT(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000283
284 case BinaryOperator::GE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000285 return AssumeSymGE(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000286
287 case BinaryOperator::LT:
Jordy Roseb4954a42010-06-21 20:15:15 +0000288 return AssumeSymLT(state, Sym, ConvertedInt, Adjustment);
Mike Stump1eb44332009-09-09 15:08:12 +0000289
Ted Kremenek45021952009-02-14 17:08:39 +0000290 case BinaryOperator::LE:
Jordy Roseb4954a42010-06-21 20:15:15 +0000291 return AssumeSymLE(state, Sym, ConvertedInt, Adjustment);
Ted Kremenek45021952009-02-14 17:08:39 +0000292 } // end switch
293}
294
Ted Kremeneka591bc02009-06-18 22:57:13 +0000295const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000296 DefinedSVal Idx,
297 DefinedSVal UpperBound,
Mike Stump1eb44332009-09-09 15:08:12 +0000298 bool Assumption) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000299
Ted Kremenek45021952009-02-14 17:08:39 +0000300 // Only support ConcreteInt for now.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000301 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
302 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000303
Ted Kremenekf1b82272009-06-18 23:20:05 +0000304 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
Ted Kremenek45021952009-02-14 17:08:39 +0000305 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
306 // IdxV might be too narrow.
307 if (IdxV.getBitWidth() < Zero.getBitWidth())
308 IdxV.extend(Zero.getBitWidth());
309 // UBV might be too narrow, too.
310 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
311 if (UBV.getBitWidth() < Zero.getBitWidth())
312 UBV.extend(Zero.getBitWidth());
313
314 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000315 bool isFeasible = Assumption ? InBound : !InBound;
316 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000317}
318
319} // end of namespace clang