blob: dd8508a50b227562e8457f757dda4bd91591b95d [file] [log] [blame]
Ted Kremenek28387992008-01-31 19:34:24 +00001//= 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//
Zhongxing Xu27f17422008-10-17 05:57:07 +000010// This file defines SVal, Loc, and NonLoc, classes that represent
Ted Kremenek28387992008-01-31 19:34:24 +000011// abstract r-values for use with path-sensitive value tracking.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenekd99bd552010-12-23 19:38:26 +000015#include "clang/StaticAnalyzer/PathSensitive/GRState.h"
Daniel Dunbar6e8aa532008-08-11 05:35:13 +000016#include "clang/Basic/IdentifierTable.h"
Ted Kremenek28387992008-01-31 19:34:24 +000017
18using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000019using namespace ento;
Ted Kremenek28387992008-01-31 19:34:24 +000020using llvm::dyn_cast;
21using llvm::cast;
22using llvm::APSInt;
23
24//===----------------------------------------------------------------------===//
Ted Kremenek3e31c262009-03-26 03:35:11 +000025// Symbol iteration within an SVal.
Ted Kremenek8e6f6e02008-02-14 23:25:54 +000026//===----------------------------------------------------------------------===//
Ted Kremenekeffdafa2008-02-01 06:36:40 +000027
Ted Kremenek0d2ccff2008-04-29 22:17:41 +000028
Ted Kremenek3e31c262009-03-26 03:35:11 +000029//===----------------------------------------------------------------------===//
30// Utility methods.
31//===----------------------------------------------------------------------===//
Ted Kremenekeffdafa2008-02-01 06:36:40 +000032
Zhongxing Xu08a2ede2009-05-12 10:10:00 +000033bool SVal::hasConjuredSymbol() const {
34 if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
35 SymbolRef sym = SV->getSymbol();
36 if (isa<SymbolConjured>(sym))
37 return true;
38 }
39
40 if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
41 const MemRegion *R = RV->getRegion();
42 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
43 SymbolRef sym = SR->getSymbol();
44 if (isa<SymbolConjured>(sym))
45 return true;
Zhongxing Xu08a2ede2009-05-12 10:10:00 +000046 }
47 }
48
49 return false;
50}
51
Ted Kremenek198a8c52009-08-28 04:49:15 +000052const FunctionDecl *SVal::getAsFunctionDecl() const {
Zhongxing Xuac129432009-04-20 05:24:46 +000053 if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
54 const MemRegion* R = X->getRegion();
Ted Kremenek10a50e72009-11-25 01:32:22 +000055 if (const FunctionTextRegion *CTR = R->getAs<FunctionTextRegion>())
Ted Kremenek198a8c52009-08-28 04:49:15 +000056 return CTR->getDecl();
Zhongxing Xuac129432009-04-20 05:24:46 +000057 }
58
Ted Kremenek198a8c52009-08-28 04:49:15 +000059 return NULL;
Zhongxing Xuac129432009-04-20 05:24:46 +000060}
61
Mike Stump11289f42009-09-09 15:08:12 +000062/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
Zhongxing Xuac129432009-04-20 05:24:46 +000063/// wraps a symbol, return that SymbolRef. Otherwise return 0.
64// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
Ted Kremenekc9747dd2009-03-03 22:06:47 +000065SymbolRef SVal::getAsLocSymbol() const {
Zhongxing Xu5cba6c82010-08-21 11:00:26 +000066 if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this))
67 return X->getLoc().getAsLocSymbol();
68
Ted Kremenekc9747dd2009-03-03 22:06:47 +000069 if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
Zhongxing Xuf8f3f9d2009-11-10 02:17:20 +000070 const MemRegion *R = X->StripCasts();
Ted Kremenek43015262009-07-29 21:43:22 +000071 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
72 return SymR->getSymbol();
Ted Kremenekc9747dd2009-03-03 22:06:47 +000073 }
Ted Kremenek43015262009-07-29 21:43:22 +000074 return NULL;
Ted Kremenekc9747dd2009-03-03 22:06:47 +000075}
76
Zhongxing Xu1bb6a1a2010-03-10 04:58:55 +000077/// Get the symbol in the SVal or its base region.
78SymbolRef SVal::getLocSymbolInBase() const {
79 const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this);
80
81 if (!X)
82 return 0;
83
84 const MemRegion *R = X->getRegion();
85
86 while (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
87 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(SR))
88 return SymR->getSymbol();
89 else
90 R = SR->getSuperRegion();
91 }
92
93 return 0;
94}
95
Ted Kremenekc9747dd2009-03-03 22:06:47 +000096/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
Zhongxing Xuac129432009-04-20 05:24:46 +000097/// Otherwise return 0.
98// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
Ted Kremenekc9747dd2009-03-03 22:06:47 +000099SymbolRef SVal::getAsSymbol() const {
100 if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
101 return X->getSymbol();
Mike Stump11289f42009-09-09 15:08:12 +0000102
Ted Kremenek3e31c262009-03-26 03:35:11 +0000103 if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
104 if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
105 return Y;
Mike Stump11289f42009-09-09 15:08:12 +0000106
Ted Kremenekc9747dd2009-03-03 22:06:47 +0000107 return getAsLocSymbol();
108}
109
Ted Kremenek3e31c262009-03-26 03:35:11 +0000110/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
111/// return that expression. Otherwise return NULL.
112const SymExpr *SVal::getAsSymbolicExpression() const {
113 if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
114 return X->getSymbolicExpression();
Mike Stump11289f42009-09-09 15:08:12 +0000115
Ted Kremenek3e31c262009-03-26 03:35:11 +0000116 return getAsSymbol();
117}
118
Zhongxing Xud0a246f2009-06-30 11:52:40 +0000119const MemRegion *SVal::getAsRegion() const {
120 if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this))
121 return X->getRegion();
122
Zhongxing Xucbbf8552010-01-11 06:52:53 +0000123 if (const nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(this)) {
124 return X->getLoc().getAsRegion();
125 }
126
Zhongxing Xud0a246f2009-06-30 11:52:40 +0000127 return 0;
128}
129
Zhongxing Xuf8f3f9d2009-11-10 02:17:20 +0000130const MemRegion *loc::MemRegionVal::StripCasts() const {
Ted Kremenekccf33352009-07-29 18:14:27 +0000131 const MemRegion *R = getRegion();
Zhongxing Xuf8f3f9d2009-11-10 02:17:20 +0000132 return R ? R->StripCasts() : NULL;
Ted Kremenekccf33352009-07-29 18:14:27 +0000133}
134
Ted Kremenek3e31c262009-03-26 03:35:11 +0000135bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
136 return itr == X.itr;
137}
138
139bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
140 return itr != X.itr;
141}
142
143SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
144 itr.push_back(SE);
Mike Stump11289f42009-09-09 15:08:12 +0000145 while (!isa<SymbolData>(itr.back())) expand();
Ted Kremenek3e31c262009-03-26 03:35:11 +0000146}
147
148SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
149 assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
150 assert(isa<SymbolData>(itr.back()));
Mike Stump11289f42009-09-09 15:08:12 +0000151 itr.pop_back();
Ted Kremenek3e31c262009-03-26 03:35:11 +0000152 if (!itr.empty())
153 while (!isa<SymbolData>(itr.back())) expand();
154 return *this;
155}
156
157SymbolRef SVal::symbol_iterator::operator*() {
158 assert(!itr.empty() && "attempting to dereference an 'end' iterator");
159 return cast<SymbolData>(itr.back());
160}
161
162void SVal::symbol_iterator::expand() {
163 const SymExpr *SE = itr.back();
164 itr.pop_back();
Mike Stump11289f42009-09-09 15:08:12 +0000165
Ted Kremenek3e31c262009-03-26 03:35:11 +0000166 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
167 itr.push_back(SIE->getLHS());
168 return;
Mike Stump11289f42009-09-09 15:08:12 +0000169 }
Ted Kremenek3e31c262009-03-26 03:35:11 +0000170 else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
171 itr.push_back(SSE->getLHS());
172 itr.push_back(SSE->getRHS());
173 return;
174 }
Mike Stump11289f42009-09-09 15:08:12 +0000175
Ted Kremenek3e31c262009-03-26 03:35:11 +0000176 assert(false && "unhandled expansion case");
177}
178
Zhongxing Xubd96bf12010-02-05 02:26:30 +0000179const void *nonloc::LazyCompoundVal::getStore() const {
180 return static_cast<const LazyCompoundValData*>(Data)->getStore();
Ted Kremenekfa417142009-08-06 01:20:57 +0000181}
182
183const TypedRegion *nonloc::LazyCompoundVal::getRegion() const {
184 return static_cast<const LazyCompoundValData*>(Data)->getRegion();
185}
186
Ted Kremenekcdd0be12008-02-06 22:50:25 +0000187//===----------------------------------------------------------------------===//
Ted Kremenekcbdce2e2008-10-30 18:01:28 +0000188// Other Iterators.
189//===----------------------------------------------------------------------===//
190
191nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
192 return getValue()->begin();
193}
194
195nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
196 return getValue()->end();
197}
198
199//===----------------------------------------------------------------------===//
Ted Kremenekb1c91bf2008-07-18 15:54:51 +0000200// Useful predicates.
201//===----------------------------------------------------------------------===//
202
Zhongxing Xu6c306c82009-11-09 06:52:44 +0000203bool SVal::isConstant() const {
204 return isa<nonloc::ConcreteInt>(this) || isa<loc::ConcreteInt>(this);
205}
206
Tom Care3ff08a82010-07-06 21:43:29 +0000207bool SVal::isConstant(int I) const {
Zhongxing Xu27f17422008-10-17 05:57:07 +0000208 if (isa<loc::ConcreteInt>(*this))
Tom Care3ff08a82010-07-06 21:43:29 +0000209 return cast<loc::ConcreteInt>(*this).getValue() == I;
Zhongxing Xu27f17422008-10-17 05:57:07 +0000210 else if (isa<nonloc::ConcreteInt>(*this))
Tom Care3ff08a82010-07-06 21:43:29 +0000211 return cast<nonloc::ConcreteInt>(*this).getValue() == I;
Ted Kremenekb1c91bf2008-07-18 15:54:51 +0000212 else
213 return false;
214}
215
Tom Care3ff08a82010-07-06 21:43:29 +0000216bool SVal::isZeroConstant() const {
217 return isConstant(0);
218}
219
Ted Kremenekb1c91bf2008-07-18 15:54:51 +0000220
221//===----------------------------------------------------------------------===//
Zhongxing Xu27f17422008-10-17 05:57:07 +0000222// Transfer function dispatch for Non-Locs.
Ted Kremenekcdd0be12008-02-06 22:50:25 +0000223//===----------------------------------------------------------------------===//
Ted Kremenekeffdafa2008-02-01 06:36:40 +0000224
Ted Kremenek90af9092010-12-02 07:49:45 +0000225SVal nonloc::ConcreteInt::evalBinOp(SValBuilder &svalBuilder,
Ted Kremenek1642bda2009-06-26 00:05:51 +0000226 BinaryOperator::Opcode Op,
Mike Stump11289f42009-09-09 15:08:12 +0000227 const nonloc::ConcreteInt& R) const {
Ted Kremenek36f6b042008-07-18 15:59:33 +0000228 const llvm::APSInt* X =
Ted Kremenek90af9092010-12-02 07:49:45 +0000229 svalBuilder.getBasicValueFactory().evalAPSInt(Op, getValue(), R.getValue());
Mike Stump11289f42009-09-09 15:08:12 +0000230
Ted Kremeneke0c79382008-02-28 20:32:03 +0000231 if (X)
Zhongxing Xu27f17422008-10-17 05:57:07 +0000232 return nonloc::ConcreteInt(*X);
Ted Kremeneke0c79382008-02-28 20:32:03 +0000233 else
234 return UndefinedVal();
Ted Kremenekcdd0be12008-02-06 22:50:25 +0000235}
236
Zhongxing Xu27f17422008-10-17 05:57:07 +0000237nonloc::ConcreteInt
Ted Kremenek90af9092010-12-02 07:49:45 +0000238nonloc::ConcreteInt::evalComplement(SValBuilder &svalBuilder) const {
239 return svalBuilder.makeIntVal(~getValue());
Ted Kremenekcdd0be12008-02-06 22:50:25 +0000240}
241
Ted Kremenek90af9092010-12-02 07:49:45 +0000242nonloc::ConcreteInt
243nonloc::ConcreteInt::evalMinus(SValBuilder &svalBuilder) const {
244 return svalBuilder.makeIntVal(-getValue());
Ted Kremenek2cdfd662008-02-04 16:58:30 +0000245}
246
Ted Kremenek28387992008-01-31 19:34:24 +0000247//===----------------------------------------------------------------------===//
Zhongxing Xu27f17422008-10-17 05:57:07 +0000248// Transfer function dispatch for Locs.
Ted Kremenek28387992008-01-31 19:34:24 +0000249//===----------------------------------------------------------------------===//
250
Ted Kremenekdc891422010-12-01 21:57:22 +0000251SVal loc::ConcreteInt::evalBinOp(BasicValueFactory& BasicVals,
Ted Kremenek0e19c032008-10-30 17:53:23 +0000252 BinaryOperator::Opcode Op,
253 const loc::ConcreteInt& R) const {
Mike Stump11289f42009-09-09 15:08:12 +0000254
John McCalle3027922010-08-25 11:45:40 +0000255 assert (Op == BO_Add || Op == BO_Sub ||
256 (Op >= BO_LT && Op <= BO_NE));
Mike Stump11289f42009-09-09 15:08:12 +0000257
Ted Kremenekdc891422010-12-01 21:57:22 +0000258 const llvm::APSInt* X = BasicVals.evalAPSInt(Op, getValue(), R.getValue());
Mike Stump11289f42009-09-09 15:08:12 +0000259
Ted Kremeneke0c79382008-02-28 20:32:03 +0000260 if (X)
Zhongxing Xu27f17422008-10-17 05:57:07 +0000261 return loc::ConcreteInt(*X);
Ted Kremeneke0c79382008-02-28 20:32:03 +0000262 else
263 return UndefinedVal();
Ted Kremenekcdd0be12008-02-06 22:50:25 +0000264}
Ted Kremenek28387992008-01-31 19:34:24 +0000265
Ted Kremenek28387992008-01-31 19:34:24 +0000266//===----------------------------------------------------------------------===//
267// Pretty-Printing.
268//===----------------------------------------------------------------------===//
269
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000270void SVal::dump() const { dumpToStream(llvm::errs()); }
Ted Kremenek736e4412008-02-12 21:37:56 +0000271
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000272void SVal::dumpToStream(llvm::raw_ostream& os) const {
Mike Stump11289f42009-09-09 15:08:12 +0000273 switch (getBaseKind()) {
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000274 case UnknownKind:
Ted Kremenekc4deb922010-09-15 03:13:30 +0000275 os << "Unknown";
Mike Stump11289f42009-09-09 15:08:12 +0000276 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000277 case NonLocKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000278 cast<NonLoc>(this)->dumpToStream(os);
Mike Stump11289f42009-09-09 15:08:12 +0000279 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000280 case LocKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000281 cast<Loc>(this)->dumpToStream(os);
Mike Stump11289f42009-09-09 15:08:12 +0000282 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000283 case UndefinedKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000284 os << "Undefined";
Mike Stump11289f42009-09-09 15:08:12 +0000285 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000286 default:
287 assert (false && "Invalid SVal.");
288 }
289}
290
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000291void NonLoc::dumpToStream(llvm::raw_ostream& os) const {
Mike Stump11289f42009-09-09 15:08:12 +0000292 switch (getSubKind()) {
Ted Kremenek08cbe572010-12-23 02:42:31 +0000293 case nonloc::ConcreteIntKind: {
294 const nonloc::ConcreteInt& C = *cast<nonloc::ConcreteInt>(this);
Ted Kremenekfe22d932010-12-23 02:42:46 +0000295 if (C.getValue().isUnsigned())
296 os << C.getValue().getZExtValue();
297 else
298 os << C.getValue().getSExtValue();
299 os << ' ' << (C.getValue().isUnsigned() ? 'U' : 'S')
Ted Kremenek08cbe572010-12-23 02:42:31 +0000300 << C.getValue().getBitWidth() << 'b';
Mike Stump11289f42009-09-09 15:08:12 +0000301 break;
Ted Kremenek08cbe572010-12-23 02:42:31 +0000302 }
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000303 case nonloc::SymbolValKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000304 os << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
Mike Stump11289f42009-09-09 15:08:12 +0000305 break;
Ted Kremenek3e31c262009-03-26 03:35:11 +0000306 case nonloc::SymExprValKind: {
307 const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
308 const SymExpr *SE = C.getSymbolicExpression();
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000309 os << SE;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000310 break;
Mike Stump11289f42009-09-09 15:08:12 +0000311 }
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000312 case nonloc::LocAsIntegerKind: {
313 const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000314 os << C.getLoc() << " [as " << C.getNumBits() << " bit integer]";
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000315 break;
316 }
Ted Kremenekcbdce2e2008-10-30 18:01:28 +0000317 case nonloc::CompoundValKind: {
318 const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
Ted Kremeneke2fb3ce2009-07-14 20:21:36 +0000319 os << "compoundVal{";
Ted Kremeneke40b6982008-10-30 18:35:10 +0000320 bool first = true;
321 for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
Mike Stump11289f42009-09-09 15:08:12 +0000322 if (first) {
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000323 os << ' '; first = false;
324 }
325 else
326 os << ", ";
327
328 (*I).dumpToStream(os);
Ted Kremeneke40b6982008-10-30 18:35:10 +0000329 }
Ted Kremeneke2fb3ce2009-07-14 20:21:36 +0000330 os << "}";
Ted Kremenekcbdce2e2008-10-30 18:01:28 +0000331 break;
Ted Kremenekfa417142009-08-06 01:20:57 +0000332 }
333 case nonloc::LazyCompoundValKind: {
334 const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
Dan Gohman145f3f12010-04-19 16:39:44 +0000335 os << "lazyCompoundVal{" << const_cast<void *>(C.getStore())
336 << ',' << C.getRegion()
Ted Kremenekfa417142009-08-06 01:20:57 +0000337 << '}';
338 break;
Mike Stump11289f42009-09-09 15:08:12 +0000339 }
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000340 default:
341 assert (false && "Pretty-printed not implemented for this NonLoc.");
342 break;
343 }
344}
345
Mike Stump11289f42009-09-09 15:08:12 +0000346void Loc::dumpToStream(llvm::raw_ostream& os) const {
347 switch (getSubKind()) {
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000348 case loc::ConcreteIntKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000349 os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
Mike Stump11289f42009-09-09 15:08:12 +0000350 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000351 case loc::GotoLabelKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000352 os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getID()->getName();
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000353 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000354 case loc::MemRegionKind:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000355 os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
Mike Stump11289f42009-09-09 15:08:12 +0000356 break;
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000357 default:
Ted Kremeneka6904ff2009-07-13 23:53:06 +0000358 assert(false && "Pretty-printing not implemented for this Loc.");
Zhongxing Xu509bd9e2008-10-24 06:00:12 +0000359 break;
360 }
361}