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