blob: 24ec7f0e387e6e59755033674d68c8c638373767 [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;
28
29public:
30 BasicStoreManager(llvm::BumpPtrAllocator& A) : VBFactory(A) {}
31 virtual ~BasicStoreManager() {}
32
33 virtual RVal GetRVal(Store St, LVal LV, QualType T);
34 virtual Store SetRVal(Store St, LVal LV, RVal V);
35 virtual Store Remove(Store St, LVal LV);
36
Ted Kremenekcaa37242008-08-19 16:51:45 +000037 virtual Store getInitialStore(GRStateManager& StateMgr);
Ted Kremenekf59bf482008-07-17 18:38:48 +000038
39 virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
40 const LiveVariables& Live,
41 DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
42 DeadSymbolsTy& DSymbols);
43
44 static inline VarBindingsTy GetVarBindings(Store store) {
45 return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
Ted Kremeneka622d8c2008-08-19 22:24:03 +000046 }
47
48 virtual void print(Store store, std::ostream& Out,
49 const char* nl, const char *sep);
Ted Kremenek4323a572008-07-10 22:03:41 +000050};
51
52} // end anonymous namespace
53
54
55StoreManager* clang::CreateBasicStoreManager(llvm::BumpPtrAllocator& A) {
56 return new BasicStoreManager(A);
57}
58
59RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
60
61 if (isa<UnknownVal>(LV))
62 return UnknownVal();
63
64 assert (!isa<UndefinedVal>(LV));
65
66 switch (LV.getSubKind()) {
67
68 case lval::DeclValKind: {
69 VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
70 VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());
71 return T ? *T : UnknownVal();
72 }
73
74 case lval::SymbolValKind: {
75
76 // FIXME: This is a broken representation of memory, and is prone
77 // to crashing the analyzer when addresses to symbolic values are
78 // passed through casts. We need a better representation of symbolic
79 // memory (or just memory in general); probably we should do this
80 // as a plugin class (similar to GRTransferFuncs).
81
82#if 0
83 const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
84 assert (T.getTypePtr());
85
86 // Punt on "symbolic" function pointers.
87 if (T->isFunctionType())
88 return UnknownVal();
89
90 if (T->isPointerType())
91 return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
92 else
93 return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
94#endif
95
96 return UnknownVal();
97 }
98
99 case lval::ConcreteIntKind:
100 // Some clients may call GetRVal with such an option simply because
101 // they are doing a quick scan through their LVals (potentially to
102 // invalidate their bindings). Just return Undefined.
103 return UndefinedVal();
104
105 case lval::ArrayOffsetKind:
106 case lval::FieldOffsetKind:
107 return UnknownVal();
108
109 case lval::FuncValKind:
110 return LV;
111
112 case lval::StringLiteralValKind:
113 // FIXME: Implement better support for fetching characters from strings.
114 return UnknownVal();
115
116 default:
117 assert (false && "Invalid LVal.");
118 break;
119 }
120
121 return UnknownVal();
122}
123
Ted Kremenekf59bf482008-07-17 18:38:48 +0000124Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
125 switch (LV.getSubKind()) {
126 case lval::DeclValKind: {
127 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000128 return V.isUnknown()
129 ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
130 : VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000131 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000132 default:
133 assert ("SetRVal for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000134 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000135 }
136}
137
Ted Kremenekf59bf482008-07-17 18:38:48 +0000138Store BasicStoreManager::Remove(Store store, LVal LV) {
Ted Kremenek4323a572008-07-10 22:03:41 +0000139 switch (LV.getSubKind()) {
Ted Kremenekf59bf482008-07-17 18:38:48 +0000140 case lval::DeclValKind: {
141 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000142 return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000143 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000144 default:
145 assert ("Remove for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000146 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000147 }
148}
Ted Kremenekf59bf482008-07-17 18:38:48 +0000149
150Store BasicStoreManager::RemoveDeadBindings(Store store,
151 Stmt* Loc,
152 const LiveVariables& Liveness,
153 DeclRootsTy& DRoots,
154 LiveSymbolsTy& LSymbols,
155 DeadSymbolsTy& DSymbols) {
156
157 VarBindingsTy B = GetVarBindings(store);
158 typedef RVal::symbol_iterator symbol_iterator;
159
160 // Iterate over the variable bindings.
161 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
162 if (Liveness.isLive(Loc, I.getKey())) {
163 DRoots.push_back(I.getKey());
164 RVal X = I.getData();
165
166 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
167 LSymbols.insert(*SI);
168 }
169
170 // Scan for live variables and live symbols.
171 llvm::SmallPtrSet<ValueDecl*, 10> Marked;
172
173 while (!DRoots.empty()) {
174 ValueDecl* V = DRoots.back();
175 DRoots.pop_back();
176
177 if (Marked.count(V))
178 continue;
179
180 Marked.insert(V);
181
182 RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
183
184 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
185 LSymbols.insert(*SI);
186
187 if (!isa<lval::DeclVal>(X))
188 continue;
189
190 const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
191 DRoots.push_back(LVD.getDecl());
192 }
193
194 // Remove dead variable bindings.
195 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
196 if (!Marked.count(I.getKey())) {
197 store = Remove(store, lval::DeclVal(I.getKey()));
198 RVal X = I.getData();
199
200 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
201 if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
202 }
203
204 return store;
205}
Ted Kremenekcaa37242008-08-19 16:51:45 +0000206
207Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) {
208 // The LiveVariables information already has a compilation of all VarDecls
209 // used in the function. Iterate through this set, and "symbolicate"
210 // any VarDecl whose value originally comes from outside the function.
211
212 typedef LiveVariables::AnalysisDataTy LVDataTy;
213 LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
214
215 Store St = VBFactory.GetEmptyMap().getRoot();
216
217 for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
218 ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
219
220 if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
221 // Punt on static variables for now.
222 if (VD->getStorageClass() == VarDecl::Static)
223 continue;
224
225 // Only handle pointers and integers for now.
226 QualType T = VD->getType();
227 if (LVal::IsLValType(T) || T->isIntegerType()) {
228 // Initialize globals and parameters to symbolic values.
229 // Initialize local variables to undefined.
230 RVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
231 isa<ImplicitParamDecl>(VD))
232 ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
233 : UndefinedVal();
234
235 St = SetRVal(St, lval::DeclVal(VD), X);
236 }
237 }
238 }
239 return St;
240}
Ted Kremeneka622d8c2008-08-19 22:24:03 +0000241
242void BasicStoreManager::print(Store store, std::ostream& Out,
243 const char* nl, const char *sep) {
244
245 VarBindingsTy B = GetVarBindings(store);
246 Out << "Variables:" << nl;
247
248 bool isFirst = true;
249
250 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
251 if (isFirst) isFirst = false;
252 else Out << nl;
253
254 Out << ' ' << I.getKey()->getName() << " : ";
255 I.getData().print(Out);
256 }
257}