blob: 015db76080dfbe3091f14aa007406cf251e6885e [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);
Ted Kremenek80417472009-09-25 00:18:15 +0000165 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())){
166 // FIXME: This is a hack. It silently converts the RHS integer to be
167 // of the same type as on the left side. This should be removed once
168 // we support truncation/extension of symbolic values.
169 GRStateManager &StateMgr = state->getStateManager();
170 ASTContext &Ctx = StateMgr.getContext();
171 QualType LHSType = SE->getLHS()->getType(Ctx);
172 BasicValueFactory &BasicVals = StateMgr.getBasicVals();
173 const llvm::APSInt &RHS = BasicVals.Convert(LHSType, SE->getRHS());
174 SymIntExpr SENew(SE->getLHS(), SE->getOpcode(), RHS, SE->getType(Ctx));
175
176 return AssumeSymInt(state, Assumption, &SENew);
177 }
Mike Stump1eb44332009-09-09 15:08:12 +0000178
Ted Kremeneka591bc02009-06-18 22:57:13 +0000179 // For all other symbolic expressions, over-approximate and consider
180 // the constraint feasible.
181 return state;
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000182 }
Ted Kremenek45021952009-02-14 17:08:39 +0000183
184 case nonloc::ConcreteIntKind: {
185 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000186 bool isFeasible = b ? Assumption : !Assumption;
187 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000188 }
189
190 case nonloc::LocAsIntegerKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000191 return AssumeAux(state, cast<nonloc::LocAsInteger>(Cond).getLoc(),
192 Assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000193 } // end switch
194}
195
Ted Kremeneka591bc02009-06-18 22:57:13 +0000196const GRState *SimpleConstraintManager::AssumeSymInt(const GRState *state,
197 bool Assumption,
198 const SymIntExpr *SE) {
Ted Kremenek45021952009-02-14 17:08:39 +0000199
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000200
201 // Here we assume that LHS is a symbol. This is consistent with the
202 // rest of the constraint manager logic.
203 SymbolRef Sym = cast<SymbolData>(SE->getLHS());
204 const llvm::APSInt &Int = SE->getRHS();
Mike Stump1eb44332009-09-09 15:08:12 +0000205
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000206 switch (SE->getOpcode()) {
Ted Kremenek45021952009-02-14 17:08:39 +0000207 default:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000208 // No logic yet for other operators. Assume the constraint is feasible.
209 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000210
211 case BinaryOperator::EQ:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000212 return Assumption ? AssumeSymEQ(state, Sym, Int)
213 : AssumeSymNE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000214
215 case BinaryOperator::NE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000216 return Assumption ? AssumeSymNE(state, Sym, Int)
217 : AssumeSymEQ(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000218 case BinaryOperator::GT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000219 return Assumption ? AssumeSymGT(state, Sym, Int)
220 : AssumeSymLE(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000221
222 case BinaryOperator::GE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000223 return Assumption ? AssumeSymGE(state, Sym, Int)
224 : AssumeSymLT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000225
226 case BinaryOperator::LT:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000227 return Assumption ? AssumeSymLT(state, Sym, Int)
228 : AssumeSymGE(state, Sym, Int);
Mike Stump1eb44332009-09-09 15:08:12 +0000229
Ted Kremenek45021952009-02-14 17:08:39 +0000230 case BinaryOperator::LE:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000231 return Assumption ? AssumeSymLE(state, Sym, Int)
232 : AssumeSymGT(state, Sym, Int);
Ted Kremenek45021952009-02-14 17:08:39 +0000233 } // end switch
234}
235
Ted Kremeneka591bc02009-06-18 22:57:13 +0000236const GRState *SimpleConstraintManager::AssumeInBound(const GRState *state,
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000237 DefinedSVal Idx,
238 DefinedSVal UpperBound,
Mike Stump1eb44332009-09-09 15:08:12 +0000239 bool Assumption) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000240
Ted Kremenek45021952009-02-14 17:08:39 +0000241 // Only support ConcreteInt for now.
Ted Kremeneka591bc02009-06-18 22:57:13 +0000242 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound)))
243 return state;
Ted Kremenek45021952009-02-14 17:08:39 +0000244
Ted Kremenekf1b82272009-06-18 23:20:05 +0000245 const llvm::APSInt& Zero = state->getBasicVals().getZeroWithPtrWidth(false);
Ted Kremenek45021952009-02-14 17:08:39 +0000246 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
247 // IdxV might be too narrow.
248 if (IdxV.getBitWidth() < Zero.getBitWidth())
249 IdxV.extend(Zero.getBitWidth());
250 // UBV might be too narrow, too.
251 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
252 if (UBV.getBitWidth() < Zero.getBitWidth())
253 UBV.extend(Zero.getBitWidth());
254
255 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000256 bool isFeasible = Assumption ? InBound : !InBound;
257 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000258}
259
260} // end of namespace clang