 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
39.1% |
36 / 92 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
47.8% |
44 / 92 |
| |
|
Line Coverage: |
48.4% |
76 / 157 |
| |
 |
|
 |
1 : //= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- 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 SVal, Loc, and NonLoc, classes that represent
11 : // abstract r-values for use with path-sensitive value tracking.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "clang/Checker/PathSensitive/GRState.h"
16 : #include "clang/Basic/IdentifierTable.h"
17 :
18 : using namespace clang;
19 : using llvm::dyn_cast;
20 : using llvm::cast;
21 : using llvm::APSInt;
22 :
23 : //===----------------------------------------------------------------------===//
24 : // Symbol iteration within an SVal.
25 : //===----------------------------------------------------------------------===//
26 :
27 :
28 : //===----------------------------------------------------------------------===//
29 : // Utility methods.
30 : //===----------------------------------------------------------------------===//
31 :
32 0: bool SVal::hasConjuredSymbol() const {
0: branch 1 not taken
0: branch 2 not taken
33 0: if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
34 0: SymbolRef sym = SV->getSymbol();
0: branch 1 not taken
0: branch 2 not taken
35 0: if (isa<SymbolConjured>(sym))
36 0: return true;
37 : }
38 :
0: branch 1 not taken
0: branch 2 not taken
39 0: if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
40 0: const MemRegion *R = RV->getRegion();
0: branch 1 not taken
0: branch 2 not taken
41 0: if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
42 0: SymbolRef sym = SR->getSymbol();
0: branch 1 not taken
0: branch 2 not taken
43 0: if (isa<SymbolConjured>(sym))
44 0: return true;
45 : }
46 : }
47 :
48 0: return false;
49 : }
50 :
51 11578: const FunctionDecl *SVal::getAsFunctionDecl() const {
11444: branch 1 taken
134: branch 2 taken
52 11578: if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
53 11444: const MemRegion* R = X->getRegion();
11092: branch 1 taken
352: branch 2 taken
54 11444: if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
55 11092: return CTR->getDecl();
56 : }
57 :
58 486: return NULL;
59 : }
60 :
61 : /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
62 : /// wraps a symbol, return that SymbolRef. Otherwise return 0.
63 : // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
64 39871: SymbolRef SVal::getAsLocSymbol() const {
17692: branch 1 taken
22179: branch 2 taken
65 39871: if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
66 17692: const MemRegion *R = X->StripCasts();
15257: branch 1 taken
2435: branch 2 taken
67 17692: if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
68 15257: return SymR->getSymbol();
69 : }
70 24614: return NULL;
71 : }
72 :
73 : /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
74 : /// Otherwise return 0.
75 : // FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
76 41214: SymbolRef SVal::getAsSymbol() const {
7921: branch 1 taken
33293: branch 2 taken
77 41214: if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
78 7921: return X->getSymbol();
79 :
461: branch 1 taken
32832: branch 2 taken
80 33293: if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
0: branch 2 not taken
461: branch 3 taken
81 461: if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
82 0: return Y;
83 :
84 33293: return getAsLocSymbol();
85 : }
86 :
87 : /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
88 : /// return that expression. Otherwise return NULL.
89 34454: const SymExpr *SVal::getAsSymbolicExpression() const {
220: branch 1 taken
34234: branch 2 taken
90 34454: if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
91 220: return X->getSymbolicExpression();
92 :
93 34234: return getAsSymbol();
94 : }
95 :
96 33059: const MemRegion *SVal::getAsRegion() const {
25947: branch 1 taken
7112: branch 2 taken
97 33059: if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
98 25947: return X->getRegion();
99 :
17: branch 1 taken
7095: branch 2 taken
100 7112: if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this)) {
101 17: return X->getLoc().getAsRegion();
102 : }
103 :
104 7095: return 0;
105 : }
106 :
107 17934: const MemRegion *loc::MemRegionVal::StripCasts() const {
108 17934: const MemRegion *R = getRegion();
17934: branch 0 taken
0: branch 1 not taken
109 17934: return R ? R->StripCasts() : NULL;
110 : }
111 :
112 0: bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
113 0: return itr == X.itr;
114 : }
115 :
116 45483: bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
117 45483: return itr != X.itr;
118 : }
119 :
120 15244: SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
121 15244: itr.push_back(SE);
198: branch 3 taken
15244: branch 4 taken
0: branch 8 not taken
0: branch 9 not taken
122 15244: while (!isa<SymbolData>(itr.back())) expand();
123 15244: }
124 :
125 15244: SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
15244: branch 1 taken
0: branch 2 not taken
126 15244: assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
0: branch 2 not taken
15244: branch 3 taken
127 15244: assert(isa<SymbolData>(itr.back()));
128 15244: itr.pop_back();
0: branch 1 not taken
15244: branch 2 taken
129 15244: if (!itr.empty())
0: branch 3 not taken
0: branch 4 not taken
130 0: while (!isa<SymbolData>(itr.back())) expand();
131 15244: return *this;
132 : }
133 :
134 15244: SymbolRef SVal::symbol_iterator::operator*() {
15244: branch 1 taken
0: branch 2 not taken
135 15244: assert(!itr.empty() && "attempting to dereference an 'end' iterator");
136 15244: return cast<SymbolData>(itr.back());
137 : }
138 :
139 198: void SVal::symbol_iterator::expand() {
140 198: const SymExpr *SE = itr.back();
141 198: itr.pop_back();
142 :
198: branch 1 taken
0: branch 2 not taken
143 198: if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
144 198: itr.push_back(SIE->getLHS());
145 198: return;
146 : }
0: branch 1 not taken
0: branch 2 not taken
147 0: else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
148 0: itr.push_back(SSE->getLHS());
149 0: itr.push_back(SSE->getRHS());
150 0: return;
151 : }
152 :
153 0: assert(false && "unhandled expansion case");
154 : }
155 :
156 10: const void *nonloc::LazyCompoundVal::getStore() const {
157 10: return static_cast<const LazyCompoundValData*>(Data)->getStore();
158 : }
159 :
160 10: const TypedRegion *nonloc::LazyCompoundVal::getRegion() const {
161 10: return static_cast<const LazyCompoundValData*>(Data)->getRegion();
162 : }
163 :
164 : //===----------------------------------------------------------------------===//
165 : // Other Iterators.
166 : //===----------------------------------------------------------------------===//
167 :
168 181: nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
169 181: return getValue()->begin();
170 : }
171 :
172 181: nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
173 181: return getValue()->end();
174 : }
175 :
176 : //===----------------------------------------------------------------------===//
177 : // Useful predicates.
178 : //===----------------------------------------------------------------------===//
179 :
180 457: bool SVal::isConstant() const {
427: branch 1 taken
30: branch 2 taken
55: branch 4 taken
372: branch 5 taken
181 457: return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
182 : }
183 :
184 425: bool SVal::isZeroConstant() const {
55: branch 1 taken
370: branch 2 taken
185 425: if (isa<loc::ConcreteInt>(*this))
186 55: return cast<loc::ConcreteInt>(*this).getValue() == 0;
363: branch 1 taken
7: branch 2 taken
187 370: else if (isa<nonloc::ConcreteInt>(*this))
188 363: return cast<nonloc::ConcreteInt>(*this).getValue() == 0;
189 : else
190 7: return false;
191 : }
192 :
193 :
194 : //===----------------------------------------------------------------------===//
195 : // Transfer function dispatch for Non-Locs.
196 : //===----------------------------------------------------------------------===//
197 :
198 : SVal nonloc::ConcreteInt::evalBinOp(ValueManager &ValMgr,
199 : BinaryOperator::Opcode Op,
200 1359: const nonloc::ConcreteInt& R) const {
201 : const llvm::APSInt* X =
202 1359: ValMgr.getBasicValueFactory().EvaluateAPSInt(Op, getValue(), R.getValue());
203 :
1359: branch 0 taken
0: branch 1 not taken
204 1359: if (X)
205 1359: return nonloc::ConcreteInt(*X);
206 : else
207 0: return UndefinedVal();
208 : }
209 :
210 : nonloc::ConcreteInt
211 20: nonloc::ConcreteInt::evalComplement(ValueManager &ValMgr) const {
212 20: return ValMgr.makeIntVal(~getValue());
213 : }
214 :
215 18: nonloc::ConcreteInt nonloc::ConcreteInt::evalMinus(ValueManager &ValMgr) const {
216 18: return ValMgr.makeIntVal(-getValue());
217 : }
218 :
219 : //===----------------------------------------------------------------------===//
220 : // Transfer function dispatch for Locs.
221 : //===----------------------------------------------------------------------===//
222 :
223 : SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
224 : BinaryOperator::Opcode Op,
225 0: const loc::ConcreteInt& R) const {
226 :
227 : assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
228 0: (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
229 :
230 0: const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
231 :
0: branch 0 not taken
0: branch 1 not taken
232 0: if (X)
233 0: return loc::ConcreteInt(*X);
234 : else
235 0: return UndefinedVal();
236 : }
237 :
238 : //===----------------------------------------------------------------------===//
239 : // Pretty-Printing.
240 : //===----------------------------------------------------------------------===//
241 :
242 0: void SVal::dump() const { dumpToStream(llvm::errs()); }
243 :
244 0: void SVal::dumpToStream(llvm::raw_ostream& os) const {
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
245 0: switch (getBaseKind()) {
246 : case UnknownKind:
247 0: os << "Invalid";
248 0: break;
249 : case NonLocKind:
250 0: cast<NonLoc>(this)->dumpToStream(os);
251 0: break;
252 : case LocKind:
253 0: cast<Loc>(this)->dumpToStream(os);
254 0: break;
255 : case UndefinedKind:
256 0: os << "Undefined";
257 0: break;
258 : default:
259 0: assert (false && "Invalid SVal.");
260 : }
261 0: }
262 :
263 0: void NonLoc::dumpToStream(llvm::raw_ostream& os) const {
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
264 0: switch (getSubKind()) {
265 : case nonloc::ConcreteIntKind:
266 0: os << cast<nonloc::ConcreteInt>(this)->getValue().getZExtValue();
0: branch 3 not taken
0: branch 4 not taken
267 0: if (cast<nonloc::ConcreteInt>(this)->getValue().isUnsigned())
268 0: os << 'U';
269 0: break;
270 : case nonloc::SymbolValKind:
271 0: os << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
272 0: break;
273 : case nonloc::SymExprValKind: {
274 0: const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
275 0: const SymExpr *SE = C.getSymbolicExpression();
276 0: os << SE;
277 0: break;
278 : }
279 : case nonloc::LocAsIntegerKind: {
280 0: const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
281 0: os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
282 0: break;
283 : }
284 : case nonloc::CompoundValKind: {
285 0: const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
286 0: os << "compoundVal{";
287 0: bool first = true;
0: branch 4 not taken
0: branch 5 not taken
288 0: for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
0: branch 0 not taken
0: branch 1 not taken
289 0: if (first) {
290 0: os << ' '; first = false;
291 : }
292 : else
293 0: os << ", ";
294 :
295 0: (*I).dumpToStream(os);
296 : }
297 0: os << "}";
298 0: break;
299 : }
300 : case nonloc::LazyCompoundValKind: {
301 0: const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
302 : os << "lazyCompoundVal{" << (void*) C.getStore() << ',' << C.getRegion()
303 0: << '}';
304 0: break;
305 : }
306 : default:
307 0: assert (false && "Pretty-printed not implemented for this NonLoc.");
308 : break;
309 : }
310 0: }
311 :
312 0: void Loc::dumpToStream(llvm::raw_ostream& os) const {
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
313 0: switch (getSubKind()) {
314 : case loc::ConcreteIntKind:
315 0: os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
316 0: break;
317 : case loc::GotoLabelKind:
318 0: os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getID()->getName();
319 0: break;
320 : case loc::MemRegionKind:
321 0: os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
322 0: break;
323 : default:
324 0: assert(false && "Pretty-printing not implemented for this Loc.");
325 : break;
326 : }
327 0: }
Generated: 2010-02-10 01:31 by zcov