blob: c72f39c2fc2a6cee151150870056e020d98787b1 [file] [log] [blame]
Ted Kremenekdd984832009-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
23const GRState*
24SimpleConstraintManager::Assume(const GRState* St, SVal Cond, bool Assumption,
25 bool& isFeasible) {
26 if (Cond.isUnknown()) {
27 isFeasible = true;
28 return St;
29 }
30
31 if (isa<NonLoc>(Cond))
32 return Assume(St, cast<NonLoc>(Cond), Assumption, isFeasible);
33 else
34 return Assume(St, cast<Loc>(Cond), Assumption, isFeasible);
35}
36
37const GRState*
38SimpleConstraintManager::Assume(const GRState* St, Loc Cond, bool Assumption,
39 bool& isFeasible) {
40 St = AssumeAux(St, Cond, Assumption, isFeasible);
41
42 if (!isFeasible)
43 return St;
44
45 // EvalAssume is used to call into the GRTransferFunction object to perform
46 // any checker-specific update of the state based on this assumption being
47 // true or false.
48 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
49 isFeasible);
50}
51
52const GRState*
53SimpleConstraintManager::AssumeAux(const GRState* St, Loc Cond, bool Assumption,
54 bool& isFeasible) {
55 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
56
57 switch (Cond.getSubKind()) {
58 default:
59 assert (false && "'Assume' not implemented for this Loc.");
60 return St;
61
62 case loc::SymbolValKind:
63 if (Assumption)
64 return AssumeSymNE(St, cast<loc::SymbolVal>(Cond).getSymbol(),
65 BasicVals.getZeroWithPtrWidth(), isFeasible);
66 else
67 return AssumeSymEQ(St, cast<loc::SymbolVal>(Cond).getSymbol(),
68 BasicVals.getZeroWithPtrWidth(), isFeasible);
69
70 case loc::MemRegionKind: {
71 // FIXME: Should this go into the storemanager?
72
73 const MemRegion* R = cast<loc::MemRegionVal>(Cond).getRegion();
74 const SubRegion* SubR = dyn_cast<SubRegion>(R);
75
76 while (SubR) {
77 // FIXME: now we only find the first symbolic region.
78 if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(SubR))
79 return AssumeAux(St, loc::SymbolVal(SymR->getSymbol()), Assumption,
80 isFeasible);
81 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
82 }
83
84 // FALL-THROUGH.
85 }
86
87 case loc::FuncValKind:
88 case loc::GotoLabelKind:
89 isFeasible = Assumption;
90 return St;
91
92 case loc::ConcreteIntKind: {
93 bool b = cast<loc::ConcreteInt>(Cond).getValue() != 0;
94 isFeasible = b ? Assumption : !Assumption;
95 return St;
96 }
97 } // end switch
98}
99
100const GRState*
101SimpleConstraintManager::Assume(const GRState* St, NonLoc Cond, bool Assumption,
102 bool& isFeasible) {
103 St = AssumeAux(St, Cond, Assumption, isFeasible);
104
105 if (!isFeasible)
106 return St;
107
108 // EvalAssume is used to call into the GRTransferFunction object to perform
109 // any checker-specific update of the state based on this assumption being
110 // true or false.
111 return StateMgr.getTransferFuncs().EvalAssume(StateMgr, St, Cond, Assumption,
112 isFeasible);
113}
114
115const GRState*
116SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond,
117 bool Assumption, bool& isFeasible) {
118 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
119 SymbolManager& SymMgr = StateMgr.getSymbolManager();
120
121 switch (Cond.getSubKind()) {
122 default:
123 assert(false && "'Assume' not implemented for this NonLoc");
124
125 case nonloc::SymbolValKind: {
126 nonloc::SymbolVal& SV = cast<nonloc::SymbolVal>(Cond);
127 SymbolRef sym = SV.getSymbol();
128 QualType T = SymMgr.getType(sym);
129
130 if (Assumption)
131 return AssumeSymNE(St, sym, BasicVals.getValue(0, T), isFeasible);
132 else
133 return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible);
134 }
135
136 case nonloc::SymIntConstraintValKind:
137 return
138 AssumeSymInt(St, Assumption,
139 cast<nonloc::SymIntConstraintVal>(Cond).getConstraint(),
140 isFeasible);
141
142 case nonloc::ConcreteIntKind: {
143 bool b = cast<nonloc::ConcreteInt>(Cond).getValue() != 0;
144 isFeasible = b ? Assumption : !Assumption;
145 return St;
146 }
147
148 case nonloc::LocAsIntegerKind:
149 return AssumeAux(St, cast<nonloc::LocAsInteger>(Cond).getLoc(),
150 Assumption, isFeasible);
151 } // end switch
152}
153
154const GRState*
155SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption,
156 const SymIntConstraint& C,
157 bool& isFeasible) {
158
159 switch (C.getOpcode()) {
160 default:
161 // No logic yet for other operators.
162 isFeasible = true;
163 return St;
164
165 case BinaryOperator::EQ:
166 if (Assumption)
167 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
168 else
169 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
170
171 case BinaryOperator::NE:
172 if (Assumption)
173 return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible);
174 else
175 return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible);
176
177 case BinaryOperator::GT:
178 if (Assumption)
179 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
180 else
181 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
182
183 case BinaryOperator::GE:
184 if (Assumption)
185 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
186 else
187 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
188
189 case BinaryOperator::LT:
190 if (Assumption)
191 return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible);
192 else
193 return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible);
194
195 case BinaryOperator::LE:
196 if (Assumption)
197 return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible);
198 else
199 return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible);
200 } // end switch
201}
202
203const GRState*
204SimpleConstraintManager::AssumeInBound(const GRState* St, SVal Idx,
205 SVal UpperBound, bool Assumption,
206 bool& isFeasible) {
207 // Only support ConcreteInt for now.
208 if (!(isa<nonloc::ConcreteInt>(Idx) && isa<nonloc::ConcreteInt>(UpperBound))){
209 isFeasible = true;
210 return St;
211 }
212
213 const llvm::APSInt& Zero = getBasicVals().getZeroWithPtrWidth(false);
214 llvm::APSInt IdxV = cast<nonloc::ConcreteInt>(Idx).getValue();
215 // IdxV might be too narrow.
216 if (IdxV.getBitWidth() < Zero.getBitWidth())
217 IdxV.extend(Zero.getBitWidth());
218 // UBV might be too narrow, too.
219 llvm::APSInt UBV = cast<nonloc::ConcreteInt>(UpperBound).getValue();
220 if (UBV.getBitWidth() < Zero.getBitWidth())
221 UBV.extend(Zero.getBitWidth());
222
223 bool InBound = (Zero <= IdxV) && (IdxV < UBV);
224
225 isFeasible = Assumption ? InBound : !InBound;
226
227 return St;
228}
229
230} // end of namespace clang