blob: f05a041179e78c87a045acc05d34c9757f89d543 [file] [log] [blame]
Ted Kremenek4323a572008-07-10 22:03:41 +00001//== BasicStore.cpp - Basic map from Locations to Values --------*- 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 defined the BasicStore and BasicStoreManager classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/PathSensitive/BasicStore.h"
Ted Kremenek5f81c442008-08-28 23:31:31 +000015#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenekcaa37242008-08-19 16:51:45 +000016#include "clang/Analysis/PathSensitive/GRState.h"
Ted Kremenek4323a572008-07-10 22:03:41 +000017#include "llvm/ADT/ImmutableMap.h"
18#include "llvm/Support/Compiler.h"
Ted Kremeneka622d8c2008-08-19 22:24:03 +000019#include "llvm/Support/Streams.h"
Ted Kremenek4323a572008-07-10 22:03:41 +000020
21using namespace clang;
Ted Kremenek5f81c442008-08-28 23:31:31 +000022using store::Region;
23using store::RegionExtent;
Ted Kremenek4323a572008-07-10 22:03:41 +000024
25namespace {
26
27class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
28 typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
29 VarBindingsTy::Factory VBFactory;
Ted Kremenek5f81c442008-08-28 23:31:31 +000030 GRStateManager& StMgr;
Ted Kremenek4323a572008-07-10 22:03:41 +000031
32public:
Ted Kremenek5f81c442008-08-28 23:31:31 +000033 BasicStoreManager(GRStateManager& mgr) : StMgr(mgr) {}
Ted Kremenekd0c4b282008-08-25 19:33:03 +000034
Ted Kremenek4323a572008-07-10 22:03:41 +000035 virtual ~BasicStoreManager() {}
36
37 virtual RVal GetRVal(Store St, LVal LV, QualType T);
38 virtual Store SetRVal(Store St, LVal LV, RVal V);
39 virtual Store Remove(Store St, LVal LV);
40
Ted Kremenekcaa37242008-08-19 16:51:45 +000041 virtual Store getInitialStore(GRStateManager& StateMgr);
Ted Kremenekf59bf482008-07-17 18:38:48 +000042
43 virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
44 const LiveVariables& Live,
45 DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
46 DeadSymbolsTy& DSymbols);
Zhongxing Xubbe8ff42008-08-21 22:34:01 +000047
Ted Kremeneke53c0692008-08-23 00:50:55 +000048 virtual Store AddDecl(Store store, GRStateManager& StateMgr,
49 const VarDecl* VD, Expr* Ex,
Zhongxing Xubbe8ff42008-08-21 22:34:01 +000050 RVal InitVal = UndefinedVal(), unsigned Count = 0);
51
Ted Kremenekf59bf482008-07-17 18:38:48 +000052 static inline VarBindingsTy GetVarBindings(Store store) {
53 return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
Ted Kremeneka622d8c2008-08-19 22:24:03 +000054 }
55
56 virtual void print(Store store, std::ostream& Out,
57 const char* nl, const char *sep);
Ted Kremenekd0c4b282008-08-25 19:33:03 +000058
Ted Kremenek5f81c442008-08-28 23:31:31 +000059 virtual RegionExtent getExtent(Region R);
Ted Kremenek4323a572008-07-10 22:03:41 +000060};
61
62} // end anonymous namespace
63
64
Ted Kremenek5f81c442008-08-28 23:31:31 +000065StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
66 return new BasicStoreManager(StMgr);
Ted Kremenekd0c4b282008-08-25 19:33:03 +000067}
68
Ted Kremenek5f81c442008-08-28 23:31:31 +000069RegionExtent BasicStoreManager::getExtent(Region R) {
70 VarDecl* VD = (VarDecl*) R;
71 QualType T = VD->getType();
Ted Kremenekd0c4b282008-08-25 19:33:03 +000072
Ted Kremenek5f81c442008-08-28 23:31:31 +000073 // FIXME: Add support for VLAs. This may require passing in additional
74 // information, or tracking a different region type.
75 if (!T.getTypePtr()->isConstantSizeType())
76 return store::UnknownExtent();
77
78 ASTContext& C = StMgr.getContext();
79 assert (!T->isObjCInterfaceType()); // @interface not a possible VarDecl type.
80 assert (T != C.VoidTy); // void not a possible VarDecl type.
81 return store::IntExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
82 C.VoidPtrTy));
Ted Kremenek4323a572008-07-10 22:03:41 +000083}
84
Ted Kremenek5f81c442008-08-28 23:31:31 +000085
Ted Kremenek4323a572008-07-10 22:03:41 +000086RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
87
88 if (isa<UnknownVal>(LV))
89 return UnknownVal();
90
91 assert (!isa<UndefinedVal>(LV));
92
93 switch (LV.getSubKind()) {
94
95 case lval::DeclValKind: {
96 VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
97 VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());
98 return T ? *T : UnknownVal();
99 }
100
Ted Kremenekd0c4b282008-08-25 19:33:03 +0000101 case lval::SymbolValKind:
Ted Kremenek4323a572008-07-10 22:03:41 +0000102 return UnknownVal();
Ted Kremenek4323a572008-07-10 22:03:41 +0000103
104 case lval::ConcreteIntKind:
105 // Some clients may call GetRVal with such an option simply because
106 // they are doing a quick scan through their LVals (potentially to
107 // invalidate their bindings). Just return Undefined.
108 return UndefinedVal();
109
110 case lval::ArrayOffsetKind:
111 case lval::FieldOffsetKind:
112 return UnknownVal();
113
114 case lval::FuncValKind:
115 return LV;
116
117 case lval::StringLiteralValKind:
118 // FIXME: Implement better support for fetching characters from strings.
119 return UnknownVal();
120
121 default:
122 assert (false && "Invalid LVal.");
123 break;
124 }
125
126 return UnknownVal();
127}
128
Ted Kremenekf59bf482008-07-17 18:38:48 +0000129Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
130 switch (LV.getSubKind()) {
131 case lval::DeclValKind: {
132 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000133 return V.isUnknown()
134 ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
135 : VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000136 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000137 default:
138 assert ("SetRVal for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000139 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000140 }
141}
142
Ted Kremenekf59bf482008-07-17 18:38:48 +0000143Store BasicStoreManager::Remove(Store store, LVal LV) {
Ted Kremenek4323a572008-07-10 22:03:41 +0000144 switch (LV.getSubKind()) {
Ted Kremenekf59bf482008-07-17 18:38:48 +0000145 case lval::DeclValKind: {
146 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000147 return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000148 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000149 default:
150 assert ("Remove for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000151 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000152 }
153}
Ted Kremenekf59bf482008-07-17 18:38:48 +0000154
155Store BasicStoreManager::RemoveDeadBindings(Store store,
156 Stmt* Loc,
157 const LiveVariables& Liveness,
158 DeclRootsTy& DRoots,
159 LiveSymbolsTy& LSymbols,
160 DeadSymbolsTy& DSymbols) {
161
162 VarBindingsTy B = GetVarBindings(store);
163 typedef RVal::symbol_iterator symbol_iterator;
164
165 // Iterate over the variable bindings.
166 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
167 if (Liveness.isLive(Loc, I.getKey())) {
168 DRoots.push_back(I.getKey());
169 RVal X = I.getData();
170
171 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
172 LSymbols.insert(*SI);
173 }
174
175 // Scan for live variables and live symbols.
176 llvm::SmallPtrSet<ValueDecl*, 10> Marked;
177
178 while (!DRoots.empty()) {
179 ValueDecl* V = DRoots.back();
180 DRoots.pop_back();
181
182 if (Marked.count(V))
183 continue;
184
185 Marked.insert(V);
186
187 RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
188
189 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
190 LSymbols.insert(*SI);
191
192 if (!isa<lval::DeclVal>(X))
193 continue;
194
195 const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
196 DRoots.push_back(LVD.getDecl());
197 }
198
199 // Remove dead variable bindings.
200 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
201 if (!Marked.count(I.getKey())) {
202 store = Remove(store, lval::DeclVal(I.getKey()));
203 RVal X = I.getData();
204
205 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
206 if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
207 }
208
209 return store;
210}
Ted Kremenekcaa37242008-08-19 16:51:45 +0000211
212Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) {
213 // The LiveVariables information already has a compilation of all VarDecls
214 // used in the function. Iterate through this set, and "symbolicate"
215 // any VarDecl whose value originally comes from outside the function.
216
217 typedef LiveVariables::AnalysisDataTy LVDataTy;
218 LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
219
220 Store St = VBFactory.GetEmptyMap().getRoot();
221
222 for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
223 ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
224
225 if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
226 // Punt on static variables for now.
227 if (VD->getStorageClass() == VarDecl::Static)
228 continue;
229
230 // Only handle pointers and integers for now.
231 QualType T = VD->getType();
232 if (LVal::IsLValType(T) || T->isIntegerType()) {
233 // Initialize globals and parameters to symbolic values.
234 // Initialize local variables to undefined.
235 RVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
236 isa<ImplicitParamDecl>(VD))
237 ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
238 : UndefinedVal();
239
240 St = SetRVal(St, lval::DeclVal(VD), X);
241 }
242 }
243 }
244 return St;
245}
Ted Kremeneka622d8c2008-08-19 22:24:03 +0000246
Ted Kremeneke53c0692008-08-23 00:50:55 +0000247Store BasicStoreManager::AddDecl(Store store, GRStateManager& StateMgr,
248 const VarDecl* VD, Expr* Ex,
249 RVal InitVal, unsigned Count) {
250
251 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
252 SymbolManager& SymMgr = StateMgr.getSymbolManager();
253
Zhongxing Xubbe8ff42008-08-21 22:34:01 +0000254 // BasicStore does not model arrays and structs.
255 if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
256 return store;
257
258 if (VD->hasGlobalStorage()) {
259 // Handle variables with global storage: extern, static, PrivateExtern.
260
261 // FIXME:: static variables may have an initializer, but the second time a
262 // function is called those values may not be current. Currently, a function
263 // will not be called more than once.
264
265 // Static global variables should not be visited here.
266 assert(!(VD->getStorageClass() == VarDecl::Static &&
267 VD->isFileVarDecl()));
268
269 // Process static variables.
270 if (VD->getStorageClass() == VarDecl::Static) {
271 // C99: 6.7.8 Initialization
272 // If an object that has static storage duration is not initialized
273 // explicitly, then:
274 // —if it has pointer type, it is initialized to a null pointer;
275 // —if it has arithmetic type, it is initialized to (positive or
276 // unsigned) zero;
277 if (!Ex) {
278 QualType T = VD->getType();
279 if (LVal::IsLValType(T))
280 store = SetRVal(store, lval::DeclVal(VD),
281 lval::ConcreteInt(BasicVals.getValue(0, T)));
282 else if (T->isIntegerType())
283 store = SetRVal(store, lval::DeclVal(VD),
284 nonlval::ConcreteInt(BasicVals.getValue(0, T)));
285 else {
286 // assert(0 && "ignore other types of variables");
287 }
288 } else {
289 store = SetRVal(store, lval::DeclVal(VD), InitVal);
290 }
291 }
292 } else {
293 // Process local scalar variables.
294 QualType T = VD->getType();
295 if (LVal::IsLValType(T) || T->isIntegerType()) {
296 RVal V = Ex ? InitVal : UndefinedVal();
297
298 if (Ex && InitVal.isUnknown()) {
299 // EXPERIMENTAL: "Conjured" symbols.
300 SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count);
301
302 V = LVal::IsLValType(Ex->getType())
303 ? cast<RVal>(lval::SymbolVal(Sym))
304 : cast<RVal>(nonlval::SymbolVal(Sym));
305 }
306
307 store = SetRVal(store, lval::DeclVal(VD), V);
308 }
309 }
310
311 return store;
312}
313
Ted Kremeneka622d8c2008-08-19 22:24:03 +0000314void BasicStoreManager::print(Store store, std::ostream& Out,
315 const char* nl, const char *sep) {
316
317 VarBindingsTy B = GetVarBindings(store);
318 Out << "Variables:" << nl;
319
320 bool isFirst = true;
321
322 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
323 if (isFirst) isFirst = false;
324 else Out << nl;
325
326 Out << ' ' << I.getKey()->getName() << " : ";
327 I.getData().print(Out);
328 }
329}