blob: 8c423a99777d57a2de43ae4c330ff46336d4f74e [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;
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 Kremenek32a58082010-01-05 00:15:18 +000068const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc cond,
69 bool assumption) {
70 state = AssumeAux(state, cond, assumption);
71 return SU.ProcessAssume(state, cond, assumption);
Ted Kremenek45021952009-02-14 17:08:39 +000072}
73
Ted Kremeneka591bc02009-06-18 22:57:13 +000074const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
75 Loc Cond, bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +000076
Ted Kremeneka591bc02009-06-18 22:57:13 +000077 BasicValueFactory &BasicVals = state->getBasicVals();
Ted Kremenek45021952009-02-14 17:08:39 +000078
79 switch (Cond.getSubKind()) {
80 default:
81 assert (false && "'Assume' not implemented for this Loc.");
Ted Kremeneka591bc02009-06-18 22:57:13 +000082 return state;
Ted Kremenek45021952009-02-14 17:08:39 +000083
Ted Kremenek45021952009-02-14 17:08:39 +000084 case loc::MemRegionKind: {
85 // FIXME: Should this go into the storemanager?
Mike Stump1eb44332009-09-09 15:08:12 +000086
Ted Kremeneka591bc02009-06-18 22:57:13 +000087 const MemRegion *R = cast<loc::MemRegionVal>(Cond).getRegion();
88 const SubRegion *SubR = dyn_cast<SubRegion>(R);
Ted Kremenek45021952009-02-14 17:08:39 +000089
90 while (SubR) {
91 // FIXME: now we only find the first symbolic region.
Ted Kremeneka591bc02009-06-18 22:57:13 +000092 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SubR)) {
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000093 if (Assumption)
Mike Stump1eb44332009-09-09 15:08:12 +000094 return AssumeSymNE(state, SymR->getSymbol(),
Ted Kremeneka591bc02009-06-18 22:57:13 +000095 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000096 else
Ted Kremeneka591bc02009-06-18 22:57:13 +000097 return AssumeSymEQ(state, SymR->getSymbol(),
98 BasicVals.getZeroWithPtrWidth());
Zhongxing Xu3330dcb2009-04-10 06:06:13 +000099 }
Ted Kremenek45021952009-02-14 17:08:39 +0000100 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
101 }
Mike Stump1eb44332009-09-09 15:08:12 +0000102
Ted Kremenek45021952009-02-14 17:08:39 +0000103 // FALL-THROUGH.
104 }
Mike Stump1eb44332009-09-09 15:08:12 +0000105
Ted Kremenek45021952009-02-14 17:08:39 +0000106 case loc::GotoLabelKind:
Ted Kremeneka591bc02009-06-18 22:57:13 +0000107 return Assumption ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000108
109 case loc::ConcreteIntKind: {
Mike Stump1eb44332009-09-09 15:08:12 +0000110 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
Ted Kremeneka591bc02009-06-18 22:57:13 +0000111 bool isFeasible = b ? Assumption : !Assumption;
112 return isFeasible ? state : NULL;
Ted Kremenek45021952009-02-14 17:08:39 +0000113 }
114 } // end switch
115}
116
Ted Kremeneka591bc02009-06-18 22:57:13 +0000117const GRState *SimpleConstraintManager::Assume(const GRState *state,
Ted Kremenek32a58082010-01-05 00:15:18 +0000118 NonLoc cond,
119 bool assumption) {
120 state = AssumeAux(state, cond, assumption);
121 return SU.ProcessAssume(state, cond, assumption);
Ted Kremenek45021952009-02-14 17:08:39 +0000122}
123
Ted Kremeneka591bc02009-06-18 22:57:13 +0000124const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
125 NonLoc Cond,
126 bool Assumption) {
Mike Stump1eb44332009-09-09 15:08:12 +0000127
Zhongxing Xua129eb92009-03-25 05:58:37 +0000128 // We cannot reason about SymIntExpr and SymSymExpr.
129 if (!canReasonAbout(Cond)) {
Ted Kremeneka591bc02009-06-18 22:57:13 +0000130 // Just return the current state indicating that the path is feasible.
131 // This may be an over-approximation of what is possible.
132 return state;
Mike Stump1eb44332009-09-09 15:08:12 +0000133 }
Zhongxing Xua129eb92009-03-25 05:58:37 +0000134
Ted Kremeneka591bc02009-06-18 22:57:13 +0000135 BasicValueFactory &BasicVals = state->getBasicVals();
136 SymbolManager &SymMgr = state->getSymbolManager();
Ted Kremenek45021952009-02-14 17:08:39 +0000137
138 switch (Cond.getSubKind()) {
139 default:
140 assert(false && "'Assume' not implemented for this NonLoc");
141
142 case nonloc::SymbolValKind: {
143 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
144 SymbolRef sym = SV.getSymbol();
Mike Stump1eb44332009-09-09 15:08:12 +0000145 QualType T = SymMgr.getType(sym);
Ted Kremeneka591bc02009-06-18 22:57:13 +0000146 const llvm::APSInt &zero = BasicVals.getValue(0, T);
147
148 return Assumption ? AssumeSymNE(state, sym, zero)
149 : AssumeSymEQ(state, sym, zero);
Ted Kremenek45021952009-02-14 17:08:39 +0000150 }
151
Ted Kremeneke0e4ebf2009-03-26 03:35:11 +0000152 case nonloc::SymExprValKind: {
153 nonloc::SymExprVal V = cast<nonloc::SymExprVal>(Cond);
Ted Kremenek80417472009-09-25 00:18:15 +0000154 if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(V.getSymbolicExpression())){
155 // FIXME: This is a hack. It silently converts the RHS integer to be
156 // of the same type as on the left side. This should be removed once
157 // we support truncation/extension of symbolic values.
158 GRStateManager &StateMgr = state->getStateManager();
159 ASTContext &Ctx = StateMgr.getContext();
160 QualType LHSType = SE->getLHS()->getType(Ctx);
161 BasicValueFactory &BasicVals = StateMgr.getBasicVals();
162 const llvm::APSInt &RHS = BasicVals.Convert(LHSType, SE->getRHS());
163 SymIntExpr SENew(SE->getLHS(), SE->getOpcode(), RHS, SE->getType(Ctx));
164
165 return AssumeSymInt(state, Assumption, &SENew);
166 }
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