blob: c2482bcd3b67d2e4bd9f8153dd4c277d2476c453 [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
Ted Kremenekf59bf482008-07-17 18:38:48 +000014#include "clang/Analysis/Analyses/LiveVariables.h"
Ted Kremenek4323a572008-07-10 22:03:41 +000015#include "clang/Analysis/PathSensitive/BasicStore.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;
22
23namespace {
24
25class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
26 typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
27 VarBindingsTy::Factory VBFactory;
Ted Kremenekd0c4b282008-08-25 19:33:03 +000028 ASTContext& C;
Ted Kremenek4323a572008-07-10 22:03:41 +000029
30public:
Ted Kremenekd0c4b282008-08-25 19:33:03 +000031 BasicStoreManager(llvm::BumpPtrAllocator& A, ASTContext& c)
32 : VBFactory(A), C(c) {}
33
Ted Kremenek4323a572008-07-10 22:03:41 +000034 virtual ~BasicStoreManager() {}
35
36 virtual RVal GetRVal(Store St, LVal LV, QualType T);
37 virtual Store SetRVal(Store St, LVal LV, RVal V);
38 virtual Store Remove(Store St, LVal LV);
39
Ted Kremenekcaa37242008-08-19 16:51:45 +000040 virtual Store getInitialStore(GRStateManager& StateMgr);
Ted Kremenekf59bf482008-07-17 18:38:48 +000041
42 virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
43 const LiveVariables& Live,
44 DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
45 DeadSymbolsTy& DSymbols);
Zhongxing Xubbe8ff42008-08-21 22:34:01 +000046
Ted Kremeneke53c0692008-08-23 00:50:55 +000047 virtual Store AddDecl(Store store, GRStateManager& StateMgr,
48 const VarDecl* VD, Expr* Ex,
Zhongxing Xubbe8ff42008-08-21 22:34:01 +000049 RVal InitVal = UndefinedVal(), unsigned Count = 0);
50
Ted Kremenekf59bf482008-07-17 18:38:48 +000051 static inline VarBindingsTy GetVarBindings(Store store) {
52 return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
Ted Kremeneka622d8c2008-08-19 22:24:03 +000053 }
54
55 virtual void print(Store store, std::ostream& Out,
56 const char* nl, const char *sep);
Ted Kremenekd0c4b282008-08-25 19:33:03 +000057
58 virtual RegionExtent getExtent(GRStateManager& SM, Region R);
Ted Kremenek4323a572008-07-10 22:03:41 +000059};
60
61} // end anonymous namespace
62
63
Ted Kremenekd0c4b282008-08-25 19:33:03 +000064StoreManager* clang::CreateBasicStoreManager(llvm::BumpPtrAllocator& A,
65 ASTContext& C) {
66 return new BasicStoreManager(A, C);
67}
68
69RegionExtent BasicStoreManager::getExtent(GRStateManager& SM, Region R) {
70 if (VarRegion *VR = dyn_cast<VarRegion>(&R))
71 return VR->getExtent(SM.getBasicVals());
72
73 return UnknownExtent();
Ted Kremenek4323a572008-07-10 22:03:41 +000074}
75
76RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
77
78 if (isa<UnknownVal>(LV))
79 return UnknownVal();
80
81 assert (!isa<UndefinedVal>(LV));
82
83 switch (LV.getSubKind()) {
84
85 case lval::DeclValKind: {
86 VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
87 VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());
88 return T ? *T : UnknownVal();
89 }
90
Ted Kremenekd0c4b282008-08-25 19:33:03 +000091 case lval::SymbolValKind:
Ted Kremenek4323a572008-07-10 22:03:41 +000092 return UnknownVal();
Ted Kremenek4323a572008-07-10 22:03:41 +000093
94 case lval::ConcreteIntKind:
95 // Some clients may call GetRVal with such an option simply because
96 // they are doing a quick scan through their LVals (potentially to
97 // invalidate their bindings). Just return Undefined.
98 return UndefinedVal();
99
100 case lval::ArrayOffsetKind:
101 case lval::FieldOffsetKind:
102 return UnknownVal();
103
104 case lval::FuncValKind:
105 return LV;
106
107 case lval::StringLiteralValKind:
108 // FIXME: Implement better support for fetching characters from strings.
109 return UnknownVal();
110
111 default:
112 assert (false && "Invalid LVal.");
113 break;
114 }
115
116 return UnknownVal();
117}
118
Ted Kremenekf59bf482008-07-17 18:38:48 +0000119Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
120 switch (LV.getSubKind()) {
121 case lval::DeclValKind: {
122 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000123 return V.isUnknown()
124 ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
125 : VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000126 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000127 default:
128 assert ("SetRVal for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000129 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000130 }
131}
132
Ted Kremenekf59bf482008-07-17 18:38:48 +0000133Store BasicStoreManager::Remove(Store store, LVal LV) {
Ted Kremenek4323a572008-07-10 22:03:41 +0000134 switch (LV.getSubKind()) {
Ted Kremenekf59bf482008-07-17 18:38:48 +0000135 case lval::DeclValKind: {
136 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000137 return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000138 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000139 default:
140 assert ("Remove for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000141 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000142 }
143}
Ted Kremenekf59bf482008-07-17 18:38:48 +0000144
145Store BasicStoreManager::RemoveDeadBindings(Store store,
146 Stmt* Loc,
147 const LiveVariables& Liveness,
148 DeclRootsTy& DRoots,
149 LiveSymbolsTy& LSymbols,
150 DeadSymbolsTy& DSymbols) {
151
152 VarBindingsTy B = GetVarBindings(store);
153 typedef RVal::symbol_iterator symbol_iterator;
154
155 // Iterate over the variable bindings.
156 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
157 if (Liveness.isLive(Loc, I.getKey())) {
158 DRoots.push_back(I.getKey());
159 RVal X = I.getData();
160
161 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
162 LSymbols.insert(*SI);
163 }
164
165 // Scan for live variables and live symbols.
166 llvm::SmallPtrSet<ValueDecl*, 10> Marked;
167
168 while (!DRoots.empty()) {
169 ValueDecl* V = DRoots.back();
170 DRoots.pop_back();
171
172 if (Marked.count(V))
173 continue;
174
175 Marked.insert(V);
176
177 RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
178
179 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
180 LSymbols.insert(*SI);
181
182 if (!isa<lval::DeclVal>(X))
183 continue;
184
185 const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
186 DRoots.push_back(LVD.getDecl());
187 }
188
189 // Remove dead variable bindings.
190 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
191 if (!Marked.count(I.getKey())) {
192 store = Remove(store, lval::DeclVal(I.getKey()));
193 RVal X = I.getData();
194
195 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
196 if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
197 }
198
199 return store;
200}
Ted Kremenekcaa37242008-08-19 16:51:45 +0000201
202Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) {
203 // The LiveVariables information already has a compilation of all VarDecls
204 // used in the function. Iterate through this set, and "symbolicate"
205 // any VarDecl whose value originally comes from outside the function.
206
207 typedef LiveVariables::AnalysisDataTy LVDataTy;
208 LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
209
210 Store St = VBFactory.GetEmptyMap().getRoot();
211
212 for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
213 ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
214
215 if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
216 // Punt on static variables for now.
217 if (VD->getStorageClass() == VarDecl::Static)
218 continue;
219
220 // Only handle pointers and integers for now.
221 QualType T = VD->getType();
222 if (LVal::IsLValType(T) || T->isIntegerType()) {
223 // Initialize globals and parameters to symbolic values.
224 // Initialize local variables to undefined.
225 RVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
226 isa<ImplicitParamDecl>(VD))
227 ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
228 : UndefinedVal();
229
230 St = SetRVal(St, lval::DeclVal(VD), X);
231 }
232 }
233 }
234 return St;
235}
Ted Kremeneka622d8c2008-08-19 22:24:03 +0000236
Ted Kremeneke53c0692008-08-23 00:50:55 +0000237Store BasicStoreManager::AddDecl(Store store, GRStateManager& StateMgr,
238 const VarDecl* VD, Expr* Ex,
239 RVal InitVal, unsigned Count) {
240
241 BasicValueFactory& BasicVals = StateMgr.getBasicVals();
242 SymbolManager& SymMgr = StateMgr.getSymbolManager();
243
Zhongxing Xubbe8ff42008-08-21 22:34:01 +0000244 // BasicStore does not model arrays and structs.
245 if (VD->getType()->isArrayType() || VD->getType()->isStructureType())
246 return store;
247
248 if (VD->hasGlobalStorage()) {
249 // Handle variables with global storage: extern, static, PrivateExtern.
250
251 // FIXME:: static variables may have an initializer, but the second time a
252 // function is called those values may not be current. Currently, a function
253 // will not be called more than once.
254
255 // Static global variables should not be visited here.
256 assert(!(VD->getStorageClass() == VarDecl::Static &&
257 VD->isFileVarDecl()));
258
259 // Process static variables.
260 if (VD->getStorageClass() == VarDecl::Static) {
261 // C99: 6.7.8 Initialization
262 // If an object that has static storage duration is not initialized
263 // explicitly, then:
264 // —if it has pointer type, it is initialized to a null pointer;
265 // —if it has arithmetic type, it is initialized to (positive or
266 // unsigned) zero;
267 if (!Ex) {
268 QualType T = VD->getType();
269 if (LVal::IsLValType(T))
270 store = SetRVal(store, lval::DeclVal(VD),
271 lval::ConcreteInt(BasicVals.getValue(0, T)));
272 else if (T->isIntegerType())
273 store = SetRVal(store, lval::DeclVal(VD),
274 nonlval::ConcreteInt(BasicVals.getValue(0, T)));
275 else {
276 // assert(0 && "ignore other types of variables");
277 }
278 } else {
279 store = SetRVal(store, lval::DeclVal(VD), InitVal);
280 }
281 }
282 } else {
283 // Process local scalar variables.
284 QualType T = VD->getType();
285 if (LVal::IsLValType(T) || T->isIntegerType()) {
286 RVal V = Ex ? InitVal : UndefinedVal();
287
288 if (Ex && InitVal.isUnknown()) {
289 // EXPERIMENTAL: "Conjured" symbols.
290 SymbolID Sym = SymMgr.getConjuredSymbol(Ex, Count);
291
292 V = LVal::IsLValType(Ex->getType())
293 ? cast<RVal>(lval::SymbolVal(Sym))
294 : cast<RVal>(nonlval::SymbolVal(Sym));
295 }
296
297 store = SetRVal(store, lval::DeclVal(VD), V);
298 }
299 }
300
301 return store;
302}
303
Ted Kremeneka622d8c2008-08-19 22:24:03 +0000304void BasicStoreManager::print(Store store, std::ostream& Out,
305 const char* nl, const char *sep) {
306
307 VarBindingsTy B = GetVarBindings(store);
308 Out << "Variables:" << nl;
309
310 bool isFirst = true;
311
312 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
313 if (isFirst) isFirst = false;
314 else Out << nl;
315
316 Out << ' ' << I.getKey()->getName() << " : ";
317 I.getData().print(Out);
318 }
319}