Newer
Older
//== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defined the BasicStore and BasicStoreManager classes.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/PathSensitive/BasicStore.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
namespace {
class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
VarBindingsTy::Factory VBFactory;
public:
BasicStoreManager(llvm::BumpPtrAllocator& A) : VBFactory(A) {}
virtual ~BasicStoreManager() {}
virtual RVal GetRVal(Store St, LVal LV, QualType T);
virtual Store SetRVal(Store St, LVal LV, RVal V);
virtual Store Remove(Store St, LVal LV);
virtual Store getInitialStore() {
return VBFactory.GetEmptyMap().getRoot();
}
virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
const LiveVariables& Live,
DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
DeadSymbolsTy& DSymbols);
static inline VarBindingsTy GetVarBindings(Store store) {
return VarBindingsTy(static_cast<const VarBindingsTy::TreeTy*>(store));
}
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
};
} // end anonymous namespace
StoreManager* clang::CreateBasicStoreManager(llvm::BumpPtrAllocator& A) {
return new BasicStoreManager(A);
}
RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
if (isa<UnknownVal>(LV))
return UnknownVal();
assert (!isa<UndefinedVal>(LV));
switch (LV.getSubKind()) {
case lval::DeclValKind: {
VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());
return T ? *T : UnknownVal();
}
case lval::SymbolValKind: {
// FIXME: This is a broken representation of memory, and is prone
// to crashing the analyzer when addresses to symbolic values are
// passed through casts. We need a better representation of symbolic
// memory (or just memory in general); probably we should do this
// as a plugin class (similar to GRTransferFuncs).
#if 0
const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
assert (T.getTypePtr());
// Punt on "symbolic" function pointers.
if (T->isFunctionType())
return UnknownVal();
if (T->isPointerType())
return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
else
return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
#endif
return UnknownVal();
}
case lval::ConcreteIntKind:
// Some clients may call GetRVal with such an option simply because
// they are doing a quick scan through their LVals (potentially to
// invalidate their bindings). Just return Undefined.
return UndefinedVal();
case lval::ArrayOffsetKind:
case lval::FieldOffsetKind:
return UnknownVal();
case lval::FuncValKind:
return LV;
case lval::StringLiteralValKind:
// FIXME: Implement better support for fetching characters from strings.
return UnknownVal();
default:
assert (false && "Invalid LVal.");
break;
}
return UnknownVal();
}
Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {
switch (LV.getSubKind()) {
case lval::DeclValKind: {
VarBindingsTy B = GetVarBindings(store);
return V.isUnknown()
? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
: VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
}
default:
assert ("SetRVal for given LVal type not yet implemented.");
return store;
}
}
Store BasicStoreManager::Remove(Store store, LVal LV) {
switch (LV.getSubKind()) {
case lval::DeclValKind: {
VarBindingsTy B = GetVarBindings(store);
return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
}
default:
assert ("Remove for given LVal type not yet implemented.");
return store;
}
}
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
Store BasicStoreManager::RemoveDeadBindings(Store store,
Stmt* Loc,
const LiveVariables& Liveness,
DeclRootsTy& DRoots,
LiveSymbolsTy& LSymbols,
DeadSymbolsTy& DSymbols) {
VarBindingsTy B = GetVarBindings(store);
typedef RVal::symbol_iterator symbol_iterator;
// Iterate over the variable bindings.
for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
if (Liveness.isLive(Loc, I.getKey())) {
DRoots.push_back(I.getKey());
RVal X = I.getData();
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
LSymbols.insert(*SI);
}
// Scan for live variables and live symbols.
llvm::SmallPtrSet<ValueDecl*, 10> Marked;
while (!DRoots.empty()) {
ValueDecl* V = DRoots.back();
DRoots.pop_back();
if (Marked.count(V))
continue;
Marked.insert(V);
RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
LSymbols.insert(*SI);
if (!isa<lval::DeclVal>(X))
continue;
const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
DRoots.push_back(LVD.getDecl());
}
// Remove dead variable bindings.
for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
if (!Marked.count(I.getKey())) {
store = Remove(store, lval::DeclVal(I.getKey()));
RVal X = I.getData();
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
}
return store;
}