blob: e4ad85aa8369be91c75b58e0fd705e4a35be893b [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"
18
19namespace clang {
20
21SimpleConstraintManager::~SimpleConstraintManager() {}
22
Ted Kremenek66b52712009-03-11 02:22:59 +000023bool SimpleConstraintManager::canReasonAbout(SVal X) const {
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000024 if (nonloc::SymExprVal *SymVal = dyn_cast<nonloc::SymExprVal>(&X)) {
25 const SymExpr *SE = SymVal->getSymbolicExpression();
Mike Stump1eb44332009-09-09 15:08:12 +000026
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000027 if (isa<SymbolData>(SE))
28 return true;
Mike Stump1eb44332009-09-09 15:08:12 +000029
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +000030 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
31 switch (SIE->getOpcode()) {
32 // We don't reason yet about bitwise-constraints on symbolic values.
33 case BinaryOperator::And:
34 case BinaryOperator::Or:
35 case BinaryOperator::Xor:
36 return false;
37 // We don't reason yet about arithmetic constraints on symbolic values.
38 case BinaryOperator::Mul:
39 case BinaryOperator::Div:
40 case BinaryOperator::Rem:
41 case BinaryOperator::Add:
42 case BinaryOperator::Sub:
43 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 Kremeneka591bc02009-06-18 22:57:13 +000067const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
68 bool Assumption) {
69
70 state = AssumeAux(state, Cond, Assumption);
71
Ted Kremenek45021952009-02-14 17:08:39 +000072 // EvalAssume is used to call into the GRTransferFunction object to perform
73 // any checker-specific update of the state based on this assumption being
Mike Stump1eb44332009-09-09 15:08:12 +000074 // true or false.
Ted Kremeneka591bc02009-06-18 22:57:13 +000075 return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
76 : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +000077}
78
Ted Kremeneka591bc02009-06-18 22:57:13 +000079const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
80 Loc Cond, bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +000081
Ted Kremeneka591bc02009-06-18 22:57:13 +000082 BasicValueFactory &BasicVals = state->getBasicVals();
Ted Kremenek45021952009-02-14 17:08:39 +000083
84 switch (Cond.getSubKind()) {
85 default:
86 assert (false && "'Assume' not implemented for this Loc.");
Ted Kremeneka591bc02009-06-18 22:57:13 +000087 return state;
Ted Kremenek45021952009-02-14 17:08:39 +000088
Ted Kremenek45021952009-02-14 17:08:39 +000089 case loc::MemRegionKind: {
90 // FIXME: Should this go into the storemanager?
Mike Stump1eb44332009-09-09 15:08:12 +000091
Ted Kremeneka591bc02009-06-18 22:57:13 +000092 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
93 const SubRegion *SubR = dyn_cast<SubRegion>(R);
Ted Kremenek45021952009-02-14 17:08:39 +000094
95 while (SubR) {
96 // FIXME: now we only find the first symbolic region.
Ted Kremeneka591bc02009-06-18 22:57:13 +000097 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000098 if (Assumption)
Mike Stump1eb44332009-09-09 15:08:12 +000099 return AssumeSymNE(state, SymR->getSymbol(),
Ted Kremeneka591bc02009-06-18 22:57:13 +0000100 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +0000101 else
Ted Kremeneka591bc02009-06-18 22:57:13 +0000102 return AssumeSymEQ(state, SymR->getSymbol(),
103 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +0000104 }
Ted Kremenek45021952009-02-14 17:08:39 +0000105 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
106 }
Mike Stump1eb44332009-09-09 15:08:12 +0000107
Ted Kremenek45021952009-02-14 17:08:39 +0000108 // FALL-THROUGH.
109 }
Mike Stump1eb44332009-09-09 15:08:12 +0000110
Ted Kremenek45021952009-02-14 17:08:39 +0000111 case loc::GotoLabelKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000112 return Assumption ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000113
114 case loc::ConcreteIntKind: {
Mike Stump1eb44332009-09-09 15:08:12 +0000115 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000116 bool isFeasible = b ? Assumption : !Assumption;
117 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000118 }
119 } // end switch
120}
121
Ted Kremeneka591bc02009-06-18 22:57:13 +0000122const GRState *SimpleConstraintManager::Assume(const GRState *state,
123 NonLoc Cond,
124 bool Assumption) {
125
126 state = AssumeAux(state, Cond, Assumption);
127
Ted Kremenek45021952009-02-14 17:08:39 +0000128 // EvalAssume is used to call into the GRTransferFunction object to perform
129 // any checker-specific update of the state based on this assumption being
Mike Stump1eb44332009-09-09 15:08:12 +0000130 // true or false.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000131 return state ? state->getTransferFuncs().EvalAssume(state, Cond, Assumption)
132 : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000133}
134
Ted Kremeneka591bc02009-06-18 22:57:13 +0000135const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
136 NonLoc Cond,
137 bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +0000138
Zhongxing Xua129eb92009-03-25 05:58:37 +0000139 // We cannot reason about SymIntExpr and SymSymExpr.
140 if (!canReasonAbout(Cond)) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000141 // Just return the current state indicating that the path is feasible.
142 // This may be an over-approximation of what is possible.
143 return state;
Mike Stump1eb44332009-09-09 15:08:12 +0000144 }
Zhongxing Xua129eb92009-03-25 05:58:37 +0000145
Ted Kremeneka591bc02009-06-18 22:57:13 +0000146 BasicValueFactory &BasicVals = state->getBasicVals();
147 SymbolManager &SymMgr = state->getSymbolManager();
Ted Kremenek45021952009-02-14 17:08:39 +0000148
149 switch (Cond.getSubKind()) {
150 default:
151 assert(false && "'Assume' not implemented for this NonLoc");
152
153 case nonloc::SymbolValKind: {
154 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
155 SymbolRef sym = SV.getSymbol();
Mike Stump1eb44332009-09-09 15:08:12 +0000156 QualType T = SymMgr.getType(sym);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000157 const llvm::APSInt &zero = BasicVals.getValue(0, T);
158
159 return Assumption ? AssumeSymNE(state, sym, zero)
160 : AssumeSymEQ(state, sym, zero);
Ted Kremenek45021952009-02-14 17:08:39 +0000161 }
162
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000163 case nonloc::SymExprValKind: {
164 nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
165 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression()))
Ted Kremeneka591bc02009-06-18 22:57:13 +0000166 return AssumeSymInt(state, Assumption, SE);
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Ted Kremeneka591bc02009-06-18 22:57:13 +0000168 // For all other symbolic expressions, over-approximate and consider
169 // the constraint feasible.
170 return state;
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000171 }
Ted Kremenek45021952009-02-14 17:08:39 +0000172
173 case nonloc::ConcreteIntKind: {
174 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000175 bool isFeasible = b ? Assumption : !Assumption;
176 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000177 }
178
179 case nonloc::LocAsIntegerKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000180 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
181 Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000182 } // end switch
183}
184
Ted Kremeneka591bc02009-06-18 22:57:13 +0000185const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
186 bool Assumption,
187 const SymIntExpr *SE) {
Ted Kremenek45021952009-02-14 17:08:39 +0000188
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000189
190 // Here we assume that LHS is a symbol. This is consistent with the
191 // rest of the constraint manager logic.
192 SymbolRef Sym = cast<SymbolData>(SE->getLHS());
193 const llvm::APSInt &Int = SE->getRHS();
Mike Stump1eb44332009-09-09 15:08:12 +0000194
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000195 switch (SE->getOpcode()) {
Ted Kremenek45021952009-02-14 17:08:39 +0000196 default:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000197 // No logic yet for other operators. Assume the constraint is feasible.
198 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000199
200 case BinaryOperator::EQ:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000201 return Assumption ? AssumeSymEQ(state, Sym, Int)
202 : AssumeSymNE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000203
204 case BinaryOperator::NE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000205 return Assumption ? AssumeSymNE(state, Sym, Int)
206 : AssumeSymEQ(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000207 case BinaryOperator::GT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000208 return Assumption ? AssumeSymGT(state, Sym, Int)
209 : AssumeSymLE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000210
211 case BinaryOperator::GE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000212 return Assumption ? AssumeSymGE(state, Sym, Int)
213 : AssumeSymLT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000214
215 case BinaryOperator::LT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000216 return Assumption ? AssumeSymLT(state, Sym, Int)
217 : AssumeSymGE(state, Sym, Int);
Mike Stump1eb44332009-09-09 15:08:12 +0000218
Ted Kremenek45021952009-02-14 17:08:39 +0000219 case BinaryOperator::LE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000220 return Assumption ? AssumeSymLE(state, Sym, Int)
221 : AssumeSymGT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000222 } // end switch
223}
224
Ted Kremeneka591bc02009-06-18 22:57:13 +0000225const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000226 DefinedSVal Idx,
227 DefinedSVal UpperBound,
Mike Stump1eb44332009-09-09 15:08:12 +0000228 bool Assumption) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000229
Ted Kremenek45021952009-02-14 17:08:39 +0000230 // Only support ConcreteInt for now.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000231 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
232 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000233
Ted Kremenekf1b82272009-06-18 23:20:05 +0000234 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
Ted Kremenek45021952009-02-14 17:08:39 +0000235 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
236 // IdxV might be too narrow.
237 if (IdxV.getBitWidth() < Zero.getBitWidth())
238 IdxV.extend(Zero.getBitWidth());
239 // UBV might be too narrow, too.
240 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
241 if (UBV.getBitWidth() < Zero.getBitWidth())
242 UBV.extend(Zero.getBitWidth());
243
244 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000245 bool isFeasible = Assumption ? InBound : !InBound;
246 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000247}
248
249} // end of namespace clang