1 //= GRState.cpp - Path-Sensitive "State" for tracking values -----*- C++ -*--=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements GRState and GRStateManager.
12 //===----------------------------------------------------------------------===//
14 #include "clang/Checker/PathSensitive/GRStateTrait.h"
15 #include "clang/Checker/PathSensitive/GRState.h"
16 #include "clang/Checker/PathSensitive/GRTransferFuncs.h"
17 #include "llvm/ADT/SmallSet.h"
18 #include "llvm/Support/raw_ostream.h"
20 using namespace clang;
22 // Give the vtable for ConstraintManager somewhere to live.
23 // FIXME: Move this elsewhere.
24 ConstraintManager::~ConstraintManager() {}
26 GRStateManager::~GRStateManager() {
27 for (std::vector<GRState::Printer*>::iterator I=Printers.begin(),
28 E=Printers.end(); I!=E; ++I)
31 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
33 I->second.second(I->second.first);
37 GRStateManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
38 SymbolReaper& SymReaper) {
40 // This code essentially performs a "mark-and-sweep" of the VariableBindings.
41 // The roots are any Block-level exprs and Decls that our liveness algorithm
42 // tells us are live. We then see what Decls they may reference, and keep
43 // those around. This code more than likely can be made faster, and the
44 // frequency of which this method is called should be experimented with
45 // for optimum performance.
46 llvm::SmallVector<const MemRegion*, 10> RegionRoots;
47 GRState NewState = *state;
49 NewState.Env = EnvMgr.RemoveDeadBindings(NewState.Env, Loc, SymReaper,
52 // Clean up the store.
53 NewState.St = StoreMgr->RemoveDeadBindings(NewState.St, Loc, SymReaper,
56 return ConstraintMgr->RemoveDeadBindings(getPersistentState(NewState),
60 const GRState *GRState::unbindLoc(Loc LV) const {
61 Store OldStore = getStore();
62 Store NewStore = getStateManager().StoreMgr->Remove(OldStore, LV);
64 if (NewStore == OldStore)
67 GRState NewSt = *this;
69 return getStateManager().getPersistentState(NewSt);
72 SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const {
73 // We only want to do fetches from regions that we can actually bind
74 // values. For example, SymbolicRegions of type 'id<...>' cannot
75 // have direct bindings (but their can be bindings on their subregions).
76 if (!R->isBoundable())
79 if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
80 QualType T = TR->getValueType(getStateManager().getContext());
81 if (Loc::IsLocType(T) || T->isIntegerType())
89 const GRState *GRState::BindExpr(const Stmt* Ex, SVal V, bool Invalidate) const{
90 Environment NewEnv = getStateManager().EnvMgr.BindExpr(Env, Ex, V,
95 GRState NewSt = *this;
97 return getStateManager().getPersistentState(NewSt);
100 const GRState* GRStateManager::getInitialState(const LocationContext *InitLoc) {
102 EnvMgr.getInitialEnvironment(InitLoc->getAnalysisContext()),
103 StoreMgr->getInitialStore(InitLoc),
104 GDMFactory.GetEmptyMap());
106 return getPersistentState(State);
109 const GRState* GRStateManager::getPersistentState(GRState& State) {
111 llvm::FoldingSetNodeID ID;
115 if (GRState* I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
118 GRState* I = (GRState*) Alloc.Allocate<GRState>();
119 new (I) GRState(State);
120 StateSet.InsertNode(I, InsertPos);
124 const GRState* GRState::makeWithStore(Store store) const {
125 GRState NewSt = *this;
127 return getStateManager().getPersistentState(NewSt);
130 //===----------------------------------------------------------------------===//
131 // State pretty-printing.
132 //===----------------------------------------------------------------------===//
134 void GRState::print(llvm::raw_ostream& Out, const char* nl,
135 const char* sep) const {
137 GRStateManager &Mgr = getStateManager();
138 Mgr.getStoreManager().print(getStore(), Out, nl, sep);
140 CFG &C = *getAnalysisContext().getCFG();
142 // Print Subexpression bindings.
145 for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
146 if (C.isBlkExpr(I.getKey()))
150 Out << nl << nl << "Sub-Expressions:" << nl;
155 Out << " (" << (void*) I.getKey() << ") ";
156 LangOptions LO; // FIXME.
157 I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
158 Out << " : " << I.getData();
161 // Print block-expression bindings.
164 for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) {
165 if (!C.isBlkExpr(I.getKey()))
169 Out << nl << nl << "Block-level Expressions:" << nl;
174 Out << " (" << (void*) I.getKey() << ") ";
175 LangOptions LO; // FIXME.
176 I.getKey()->printPretty(Out, 0, PrintingPolicy(LO));
177 Out << " : " << I.getData();
180 Mgr.getConstraintManager().print(this, Out, nl, sep);
182 // Print checker-specific data.
183 for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(),
184 E = Mgr.Printers.end(); I != E; ++I) {
185 (*I)->Print(Out, this, nl, sep);
189 void GRState::printDOT(llvm::raw_ostream& Out) const {
190 print(Out, "\\l", "\\|");
193 void GRState::printStdErr() const {
197 //===----------------------------------------------------------------------===//
199 //===----------------------------------------------------------------------===//
201 void* const* GRState::FindGDM(void* K) const {
202 return GDM.lookup(K);
206 GRStateManager::FindGDMContext(void* K,
207 void* (*CreateContext)(llvm::BumpPtrAllocator&),
208 void (*DeleteContext)(void*)) {
210 std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
212 p.first = CreateContext(Alloc);
213 p.second = DeleteContext;
219 const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
220 GRState::GenericDataMap M1 = St->getGDM();
221 GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data);
228 return getPersistentState(NewSt);
231 //===----------------------------------------------------------------------===//
233 //===----------------------------------------------------------------------===//
236 class ScanReachableSymbols : public SubRegionMap::Visitor {
237 typedef llvm::DenseSet<const MemRegion*> VisitedRegionsTy;
239 VisitedRegionsTy visited;
240 const GRState *state;
241 SymbolVisitor &visitor;
242 llvm::OwningPtr<SubRegionMap> SRM;
245 ScanReachableSymbols(const GRState *st, SymbolVisitor& v)
246 : state(st), visitor(v) {}
248 bool scan(nonloc::CompoundVal val);
250 bool scan(const MemRegion *R);
252 // From SubRegionMap::Visitor.
253 bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) {
254 return scan(SubRegion);
259 bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
260 for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
267 bool ScanReachableSymbols::scan(SVal val) {
268 if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val))
269 return scan(X->getRegion());
271 if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val))
272 return scan(X->getLoc());
274 if (SymbolRef Sym = val.getAsSymbol())
275 return visitor.VisitSymbol(Sym);
277 if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val))
283 bool ScanReachableSymbols::scan(const MemRegion *R) {
284 if (isa<MemSpaceRegion>(R) || visited.count(R))
289 // If this is a symbolic region, visit the symbol for the region.
290 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
291 if (!visitor.VisitSymbol(SR->getSymbol()))
294 // If this is a subregion, also visit the parent regions.
295 if (const SubRegion *SR = dyn_cast<SubRegion>(R))
296 if (!scan(SR->getSuperRegion()))
299 // Now look at the binding to this region (if any).
300 if (!scan(state->getSValAsScalarOrLoc(R)))
303 // Now look at the subregions.
305 SRM.reset(state->getStateManager().getStoreManager().
306 getSubRegionMap(state->getStore()));
308 return SRM->iterSubRegions(R, *this);
311 bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
312 ScanReachableSymbols S(this, visitor);
316 bool GRState::scanReachableSymbols(const SVal *I, const SVal *E,
317 SymbolVisitor &visitor) const {
318 ScanReachableSymbols S(this, visitor);
319 for ( ; I != E; ++I) {
326 bool GRState::scanReachableSymbols(const MemRegion * const *I,
327 const MemRegion * const *E,
328 SymbolVisitor &visitor) const {
329 ScanReachableSymbols S(this, visitor);
330 for ( ; I != E; ++I) {
337 //===----------------------------------------------------------------------===//
339 //===----------------------------------------------------------------------===//
341 bool GRStateManager::isEqual(const GRState* state, const Expr* Ex,
342 const llvm::APSInt& Y) {
344 SVal V = state->getSVal(Ex);
346 if (loc::ConcreteInt* X = dyn_cast<loc::ConcreteInt>(&V))
347 return X->getValue() == Y;
349 if (nonloc::ConcreteInt* X = dyn_cast<nonloc::ConcreteInt>(&V))
350 return X->getValue() == Y;
352 if (SymbolRef Sym = V.getAsSymbol())
353 return ConstraintMgr->isEqual(state, Sym, Y);
358 bool GRStateManager::isEqual(const GRState* state, const Expr* Ex, uint64_t x) {
359 return isEqual(state, Ex, getBasicVals().getValue(x, Ex->getType()));