blob: 23c3b4175835984289116d03973bcb60dfb01502 [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"
16#include "clang/Analysis/PathSensitive/GRExprEngine.h"
17#include "clang/Analysis/PathSensitive/GRState.h"
Zhongxing Xub94b81a2009-12-31 06:13:07 +000018#include "clang/Analysis/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;
38 // We don't reason yet about arithmetic constraints on symbolic values.
39 case BinaryOperator::Mul:
40 case BinaryOperator::Div:
41 case BinaryOperator::Rem:
42 case BinaryOperator::Add:
43 case BinaryOperator::Sub:
44 case BinaryOperator::Shl:
45 case BinaryOperator::Shr:
46 return false;
47 // All other cases.
48 default:
49 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000050 }
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000051 }
52
53 return false;
Ted Kremenek7de20fe2009-03-11 02:29:48 +000054 }
55
Ted Kremenek66b52712009-03-11 02:22:59 +000056 return true;
57}
Mike Stump1eb44332009-09-09 15:08:12 +000058
Ted Kremeneka591bc02009-06-18 22:57:13 +000059const GRState *SimpleConstraintManager::Assume(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +000060 DefinedSVal Cond,
61 bool Assumption) {
Ted Kremenek45021952009-02-14 17:08:39 +000062 if (isa<NonLoc>(Cond))
Ted Kremeneka591bc02009-06-18 22:57:13 +000063 return Assume(state, cast<NonLoc>(Cond), Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000064 else
Ted Kremeneka591bc02009-06-18 22:57:13 +000065 return Assume(state, cast<Loc>(Cond), Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000066}
67
Ted Kremeneka591bc02009-06-18 22:57:13 +000068const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
69 bool Assumption) {
70
71 state = AssumeAux(state, Cond, Assumption);
72
Ted Kremenek45021952009-02-14 17:08:39 +000073 // EvalAssume is used to call into the GRTransferFunction object to perform
74 // any checker-specific update of the state based on this assumption being
Mike Stump1eb44332009-09-09 15:08:12 +000075 // true or false.
Zhongxing Xub94b81a2009-12-31 06:13:07 +000076
77 if (!state)
78 return 0;
79
80 std::vector<std::pair<void *, Checker*> >::iterator
81 I = state->checker_begin(), E = state->checker_end();
82
83 for (; I != E; ++I) {
84 state = I->second->EvalAssume(state, Cond, Assumption);
85 }
86 return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000087}
88
Ted Kremeneka591bc02009-06-18 22:57:13 +000089const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
90 Loc Cond, bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +000091
Ted Kremeneka591bc02009-06-18 22:57:13 +000092 BasicValueFactory &BasicVals = state->getBasicVals();
Ted Kremenek45021952009-02-14 17:08:39 +000093
94 switch (Cond.getSubKind()) {
95 default:
96 assert (false && "'Assume' not implemented for this Loc.");
Ted Kremeneka591bc02009-06-18 22:57:13 +000097 return state;
Ted Kremenek45021952009-02-14 17:08:39 +000098
Ted Kremenek45021952009-02-14 17:08:39 +000099 case loc::MemRegionKind: {
100 // FIXME: Should this go into the storemanager?
Mike Stump1eb44332009-09-09 15:08:12 +0000101
Ted Kremeneka591bc02009-06-18 22:57:13 +0000102 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
103 const SubRegion *SubR = dyn_cast<SubRegion>(R);
Ted Kremenek45021952009-02-14 17:08:39 +0000104
105 while (SubR) {
106 // FIXME: now we only find the first symbolic region.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000107 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
Zhongxing Xu3330dcb2009-04-10 06:06:13 +0000108 if (Assumption)
Mike Stump1eb44332009-09-09 15:08:12 +0000109 return AssumeSymNE(state, SymR->getSymbol(),
Ted Kremeneka591bc02009-06-18 22:57:13 +0000110 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +0000111 else
Ted Kremeneka591bc02009-06-18 22:57:13 +0000112 return AssumeSymEQ(state, SymR->getSymbol(),
113 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +0000114 }
Ted Kremenek45021952009-02-14 17:08:39 +0000115 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
116 }
Mike Stump1eb44332009-09-09 15:08:12 +0000117
Ted Kremenek45021952009-02-14 17:08:39 +0000118 // FALL-THROUGH.
119 }
Mike Stump1eb44332009-09-09 15:08:12 +0000120
Ted Kremenek45021952009-02-14 17:08:39 +0000121 case loc::GotoLabelKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000122 return Assumption ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000123
124 case loc::ConcreteIntKind: {
Mike Stump1eb44332009-09-09 15:08:12 +0000125 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000126 bool isFeasible = b ? Assumption : !Assumption;
127 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000128 }
129 } // end switch
130}
131
Ted Kremeneka591bc02009-06-18 22:57:13 +0000132const GRState *SimpleConstraintManager::Assume(const GRState *state,
133 NonLoc Cond,
134 bool Assumption) {
135
136 state = AssumeAux(state, Cond, Assumption);
137
Ted Kremenek45021952009-02-14 17:08:39 +0000138 // EvalAssume is used to call into the GRTransferFunction object to perform
139 // any checker-specific update of the state based on this assumption being
Mike Stump1eb44332009-09-09 15:08:12 +0000140 // true or false.
Zhongxing Xub94b81a2009-12-31 06:13:07 +0000141
142 if (!state)
143 return 0;
144
145 std::vector<std::pair<void *, Checker*> >::iterator
146 I = state->checker_begin(), E = state->checker_end();
147
148 for (; I != E; ++I) {
149 state = I->second->EvalAssume(state, Cond, Assumption);
150 }
151
152 return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000153}
154
Ted Kremeneka591bc02009-06-18 22:57:13 +0000155const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
156 NonLoc Cond,
157 bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +0000158
Zhongxing Xua129eb92009-03-25 05:58:37 +0000159 // We cannot reason about SymIntExpr and SymSymExpr.
160 if (!canReasonAbout(Cond)) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000161 // Just return the current state indicating that the path is feasible.
162 // This may be an over-approximation of what is possible.
163 return state;
Mike Stump1eb44332009-09-09 15:08:12 +0000164 }
Zhongxing Xua129eb92009-03-25 05:58:37 +0000165
Ted Kremeneka591bc02009-06-18 22:57:13 +0000166 BasicValueFactory &BasicVals = state->getBasicVals();
167 SymbolManager &SymMgr = state->getSymbolManager();
Ted Kremenek45021952009-02-14 17:08:39 +0000168
169 switch (Cond.getSubKind()) {
170 default:
171 assert(false && "'Assume' not implemented for this NonLoc");
172
173 case nonloc::SymbolValKind: {
174 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
175 SymbolRef sym = SV.getSymbol();
Mike Stump1eb44332009-09-09 15:08:12 +0000176 QualType T = SymMgr.getType(sym);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000177 const llvm::APSInt &zero = BasicVals.getValue(0, T);
178
179 return Assumption ? AssumeSymNE(state, sym, zero)
180 : AssumeSymEQ(state, sym, zero);
Ted Kremenek45021952009-02-14 17:08:39 +0000181 }
182
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000183 case nonloc::SymExprValKind: {
184 nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
Ted Kremenek80417472009-09-25 00:18:15 +0000185 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())){
186 // FIXME: This is a hack. It silently converts the RHS integer to be
187 // of the same type as on the left side. This should be removed once
188 // we support truncation/extension of symbolic values.
189 GRStateManager &StateMgr = state->getStateManager();
190 ASTContext &Ctx = StateMgr.getContext();
191 QualType LHSType = SE->getLHS()->getType(Ctx);
192 BasicValueFactory &BasicVals = StateMgr.getBasicVals();
193 const llvm::APSInt &RHS = BasicVals.Convert(LHSType, SE->getRHS());
194 SymIntExpr SENew(SE->getLHS(), SE->getOpcode(), RHS, SE->getType(Ctx));
195
196 return AssumeSymInt(state, Assumption, &SENew);
197 }
Mike Stump1eb44332009-09-09 15:08:12 +0000198
Ted Kremeneka591bc02009-06-18 22:57:13 +0000199 // For all other symbolic expressions, over-approximate and consider
200 // the constraint feasible.
201 return state;
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000202 }
Ted Kremenek45021952009-02-14 17:08:39 +0000203
204 case nonloc::ConcreteIntKind: {
205 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000206 bool isFeasible = b ? Assumption : !Assumption;
207 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000208 }
209
210 case nonloc::LocAsIntegerKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000211 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
212 Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000213 } // end switch
214}
215
Ted Kremeneka591bc02009-06-18 22:57:13 +0000216const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
217 bool Assumption,
218 const SymIntExpr *SE) {
Ted Kremenek45021952009-02-14 17:08:39 +0000219
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000220
221 // Here we assume that LHS is a symbol. This is consistent with the
222 // rest of the constraint manager logic.
223 SymbolRef Sym = cast<SymbolData>(SE->getLHS());
224 const llvm::APSInt &Int = SE->getRHS();
Mike Stump1eb44332009-09-09 15:08:12 +0000225
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000226 switch (SE->getOpcode()) {
Ted Kremenek45021952009-02-14 17:08:39 +0000227 default:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000228 // No logic yet for other operators. Assume the constraint is feasible.
229 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000230
231 case BinaryOperator::EQ:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000232 return Assumption ? AssumeSymEQ(state, Sym, Int)
233 : AssumeSymNE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000234
235 case BinaryOperator::NE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000236 return Assumption ? AssumeSymNE(state, Sym, Int)
237 : AssumeSymEQ(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000238 case BinaryOperator::GT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000239 return Assumption ? AssumeSymGT(state, Sym, Int)
240 : AssumeSymLE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000241
242 case BinaryOperator::GE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000243 return Assumption ? AssumeSymGE(state, Sym, Int)
244 : AssumeSymLT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000245
246 case BinaryOperator::LT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000247 return Assumption ? AssumeSymLT(state, Sym, Int)
248 : AssumeSymGE(state, Sym, Int);
Mike Stump1eb44332009-09-09 15:08:12 +0000249
Ted Kremenek45021952009-02-14 17:08:39 +0000250 case BinaryOperator::LE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000251 return Assumption ? AssumeSymLE(state, Sym, Int)
252 : AssumeSymGT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000253 } // end switch
254}
255
Ted Kremeneka591bc02009-06-18 22:57:13 +0000256const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000257 DefinedSVal Idx,
258 DefinedSVal UpperBound,
Mike Stump1eb44332009-09-09 15:08:12 +0000259 bool Assumption) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000260
Ted Kremenek45021952009-02-14 17:08:39 +0000261 // Only support ConcreteInt for now.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000262 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
263 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000264
Ted Kremenekf1b82272009-06-18 23:20:05 +0000265 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
Ted Kremenek45021952009-02-14 17:08:39 +0000266 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
267 // IdxV might be too narrow.
268 if (IdxV.getBitWidth() < Zero.getBitWidth())
269 IdxV.extend(Zero.getBitWidth());
270 // UBV might be too narrow, too.
271 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
272 if (UBV.getBitWidth() < Zero.getBitWidth())
273 UBV.extend(Zero.getBitWidth());
274
275 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000276 bool isFeasible = Assumption ? InBound : !InBound;
277 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000278}
279
280} // end of namespace clang