blob: 64a230975f0981010ce35db6a9b0344ea02b4c3e [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"
16#include "llvm/ADT/ImmutableMap.h"
17#include "llvm/Support/Compiler.h"
18
19using namespace clang;
20
21namespace {
22
23class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
24 typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
25 VarBindingsTy::Factory VBFactory;
26
27public:
28 BasicStoreManager(llvm::BumpPtrAllocator& A) : VBFactory(A) {}
29 virtual ~BasicStoreManager() {}
30
31 virtual RVal GetRVal(Store St, LVal LV, QualType T);
32 virtual Store SetRVal(Store St, LVal LV, RVal V);
33 virtual Store Remove(Store St, LVal LV);
34
35 virtual Store getInitialStore() {
36 return VBFactory.GetEmptyMap().getRoot();
37 }
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));
46 }
Ted Kremenek4323a572008-07-10 22:03:41 +000047};
48
49} // end anonymous namespace
50
51
52StoreManager* clang::CreateBasicStoreManager(llvm::BumpPtrAllocator& A) {
53 return new BasicStoreManager(A);
54}
55
56RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
57
58 if (isa<UnknownVal>(LV))
59 return UnknownVal();
60
61 assert (!isa<UndefinedVal>(LV));
62
63 switch (LV.getSubKind()) {
64
65 case lval::DeclValKind: {
66 VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
67 VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());
68 return T ? *T : UnknownVal();
69 }
70
71 case lval::SymbolValKind: {
72
73 // FIXME: This is a broken representation of memory, and is prone
74 // to crashing the analyzer when addresses to symbolic values are
75 // passed through casts. We need a better representation of symbolic
76 // memory (or just memory in general); probably we should do this
77 // as a plugin class (similar to GRTransferFuncs).
78
79#if 0
80 const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
81 assert (T.getTypePtr());
82
83 // Punt on "symbolic" function pointers.
84 if (T->isFunctionType())
85 return UnknownVal();
86
87 if (T->isPointerType())
88 return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
89 else
90 return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
91#endif
92
93 return UnknownVal();
94 }
95
96 case lval::ConcreteIntKind:
97 // Some clients may call GetRVal with such an option simply because
98 // they are doing a quick scan through their LVals (potentially to
99 // invalidate their bindings). Just return Undefined.
100 return UndefinedVal();
101
102 case lval::ArrayOffsetKind:
103 case lval::FieldOffsetKind:
104 return UnknownVal();
105
106 case lval::FuncValKind:
107 return LV;
108
109 case lval::StringLiteralValKind:
110 // FIXME: Implement better support for fetching characters from strings.
111 return UnknownVal();
112
113 default:
114 assert (false && "Invalid LVal.");
115 break;
116 }
117
118 return UnknownVal();
119}
120
Ted Kremenekf59bf482008-07-17 18:38:48 +0000121Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
122 switch (LV.getSubKind()) {
123 case lval::DeclValKind: {
124 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000125 return V.isUnknown()
126 ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
127 : VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000128 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000129 default:
130 assert ("SetRVal for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000131 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000132 }
133}
134
Ted Kremenekf59bf482008-07-17 18:38:48 +0000135Store BasicStoreManager::Remove(Store store, LVal LV) {
Ted Kremenek4323a572008-07-10 22:03:41 +0000136 switch (LV.getSubKind()) {
Ted Kremenekf59bf482008-07-17 18:38:48 +0000137 case lval::DeclValKind: {
138 VarBindingsTy B = GetVarBindings(store);
Ted Kremenek4323a572008-07-10 22:03:41 +0000139 return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
Ted Kremenekf59bf482008-07-17 18:38:48 +0000140 }
Ted Kremenek4323a572008-07-10 22:03:41 +0000141 default:
142 assert ("Remove for given LVal type not yet implemented.");
Ted Kremenekf59bf482008-07-17 18:38:48 +0000143 return store;
Ted Kremenek4323a572008-07-10 22:03:41 +0000144 }
145}
Ted Kremenekf59bf482008-07-17 18:38:48 +0000146
147Store BasicStoreManager::RemoveDeadBindings(Store store,
148 Stmt* Loc,
149 const LiveVariables& Liveness,
150 DeclRootsTy& DRoots,
151 LiveSymbolsTy& LSymbols,
152 DeadSymbolsTy& DSymbols) {
153
154 VarBindingsTy B = GetVarBindings(store);
155 typedef RVal::symbol_iterator symbol_iterator;
156
157 // Iterate over the variable bindings.
158 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
159 if (Liveness.isLive(Loc, I.getKey())) {
160 DRoots.push_back(I.getKey());
161 RVal X = I.getData();
162
163 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
164 LSymbols.insert(*SI);
165 }
166
167 // Scan for live variables and live symbols.
168 llvm::SmallPtrSet<ValueDecl*, 10> Marked;
169
170 while (!DRoots.empty()) {
171 ValueDecl* V = DRoots.back();
172 DRoots.pop_back();
173
174 if (Marked.count(V))
175 continue;
176
177 Marked.insert(V);
178
179 RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
180
181 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
182 LSymbols.insert(*SI);
183
184 if (!isa<lval::DeclVal>(X))
185 continue;
186
187 const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
188 DRoots.push_back(LVD.getDecl());
189 }
190
191 // Remove dead variable bindings.
192 for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
193 if (!Marked.count(I.getKey())) {
194 store = Remove(store, lval::DeclVal(I.getKey()));
195 RVal X = I.getData();
196
197 for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
198 if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
199 }
200
201 return store;
202}