[cfe-commits] r54788 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRState.h lib/Analysis/CFRefCount.cpp lib/Analysis/GRState.cpp
Ted Kremenek
kremenek at apple.com
Thu Aug 14 14:16:54 PDT 2008
Author: kremenek
Date: Thu Aug 14 16:16:54 2008
New Revision: 54788
URL: http://llvm.org/viewvc/llvm-project?rev=54788&view=rev
Log:
Migrated retain/release checker to use the Generic Data Map in GRState (instead
of using CheckerState).
Removed CheckerState from GRState.
Added class GRStateRef which wraps GRState* and GRStateManager*. This is handy
for generating new states with a single handle.
Added member template set/get functions to GRStateRef/GRState/GRStateManager for
accessing the Generic Data Map.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/lib/Analysis/GRState.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=54788&r1=54787&r2=54788&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Thu Aug 14 16:16:54 2008
@@ -47,6 +47,8 @@
// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
//===----------------------------------------------------------------------===//
+template<typename T> struct GRStateTrait;
+
/// GRState - This class encapsulates the actual data values for
/// for a "state" in our symbolic value tracking. It is intended to be
/// used as a functional object; that is once it is created and made
@@ -74,7 +76,6 @@
GenericDataMap GDM;
ConstNotEqTy ConstNotEq;
ConstEqTy ConstEq;
- void* CheckerState;
public:
@@ -85,8 +86,7 @@
St(st),
GDM(gdm),
ConstNotEq(CNE),
- ConstEq(CE),
- CheckerState(NULL) {}
+ ConstEq(CE) {}
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
@@ -96,8 +96,7 @@
St(RHS.St),
GDM(RHS.GDM),
ConstNotEq(RHS.ConstNotEq),
- ConstEq(RHS.ConstEq),
- CheckerState(RHS.CheckerState) {}
+ ConstEq(RHS.ConstEq) {}
/// getEnvironment - Return the environment associated with this state.
/// The environment is the mapping from expressions to values.
@@ -118,7 +117,6 @@
V->GDM.Profile(ID);
V->ConstNotEq.Profile(ID);
V->ConstEq.Profile(ID);
- ID.AddPointer(V->CheckerState);
}
/// Profile - Used to profile the contents of this object for inclusion
@@ -171,6 +169,22 @@
ce_iterator ce_begin() const { return ConstEq.begin(); }
ce_iterator ce_end() const { return ConstEq.end(); }
+ // Trait based GDM dispatch.
+ void* const* FindGDM(void* K) const;
+
+ template <typename T>
+ typename GRStateTrait<T>::data_type get() const {
+ return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex()));
+ }
+
+ template<typename T>
+ typename GRStateTrait<T>::lookup_type
+ get(typename GRStateTrait<T>::key_type key) const {
+ void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
+ return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
+ }
+
+ // State pretty-printing.
class Printer {
public:
virtual ~Printer() {}
@@ -183,7 +197,7 @@
void printStdErr(Printer **Beg = 0, Printer **End = 0) const;
void printDOT(std::ostream& Out, Printer **Beg = 0, Printer **End = 0) const;
-};
+};
template<> struct GRTrait<GRState*> {
static inline void* toPtr(GRState* St) { return (void*) St; }
@@ -195,6 +209,7 @@
}
};
+
class GRStateSet {
typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
ImplTy Impl;
@@ -226,7 +241,11 @@
S.Add(St);
}
};
-};
+};
+
+//===----------------------------------------------------------------------===//
+// GRStateManager - Factory object for GRStates.
+//===----------------------------------------------------------------------===//
class GRStateManager {
friend class GRExprEngine;
@@ -349,18 +368,8 @@
}
// Methods that manipulate the GDM.
- const GRState* addGDM(const GRState* St, void* Key, void* Data) {
- GRState::GenericDataMap M1 = St->getGDM();
- GRState::GenericDataMap M2 = GDMFactory.Add(M2, Key, Data);
-
- if (M1 == M2)
- return St;
-
- GRState NewSt = *St;
- NewSt.GDM = M2;
- return getPersistentState(NewSt);
- }
-
+ const GRState* addGDM(const GRState* St, void* Key, void* Data);
+
// Methods that query & manipulate the Store.
RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
return StMgr->GetRVal(St->getStore(), LV, T);
@@ -389,6 +398,32 @@
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
+ // Trait based GDM dispatch.
+ template <typename T>
+ const GRState* set(const GRState* st, typename GRStateTrait<T>::data_type D) {
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(D));
+ }
+
+ template<typename T>
+ const GRState* set(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type V,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
+ }
+
+ template <typename T>
+ const GRState* remove(const GRState* st,
+ typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+
+ return addGDM(st, GRStateTrait<T>::GDMIndex(),
+ GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
+ }
+
// Assumption logic.
const GRState* Assume(const GRState* St, RVal Cond, bool Assumption,
bool& isFeasible) {
@@ -440,6 +475,86 @@
const llvm::APSInt& V, bool& isFeasible);
};
+//===----------------------------------------------------------------------===//
+// GRStateRef - A "fat" reference to GRState that also bundles GRStateManager.
+//===----------------------------------------------------------------------===//
+
+class GRStateRef {
+ const GRState* St;
+ GRStateManager* Mgr;
+public:
+ GRStateRef(const GRState* st, GRStateManager& mgr) : St(st), Mgr(&mgr) {}
+
+ const GRState* getState() const { return St; }
+ operator const GRState*() const { return St; }
+ GRStateManager& getManager() const { return *Mgr; }
+
+ RVal GetRVal(Expr* Ex) {
+ return Mgr->GetRVal(St, Ex);
+ }
+
+ RVal GetBlkExprRVal(Expr* Ex) {
+ return Mgr->GetBlkExprRVal(St, Ex);
+ }
+
+ RVal GetRVal(LVal LV, QualType T = QualType()) {
+ return Mgr->GetRVal(St, LV, T);
+ }
+
+ GRStateRef SetRVal(Expr* Ex, RVal V, bool isBlkExpr, bool Invalidate) {
+ return GRStateRef(Mgr->SetRVal(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
+ }
+
+ GRStateRef SetRVal(Expr* Ex, RVal V) {
+ return GRStateRef(Mgr->SetRVal(St, Ex, V), *Mgr);
+ }
+
+ GRStateRef SetRVal(LVal LV, RVal V) {
+ GRState StImpl = *St;
+ Mgr->SetRVal(StImpl, LV, V);
+ return GRStateRef(Mgr->getPersistentState(StImpl), *Mgr);
+ }
+
+ GRStateRef Unbind(LVal LV) {
+ return GRStateRef(Mgr->Unbind(St, LV), *Mgr);
+ }
+
+ GRStateRef AddNE(SymbolID sym, const llvm::APSInt& V) {
+ return GRStateRef(Mgr->AddNE(St, sym, V), *Mgr);
+ }
+
+ // Trait based GDM dispatch.
+ template<typename T>
+ typename GRStateTrait<T>::data_type get() const {
+ return St->get<T>();
+ }
+
+ template<typename T>
+ typename GRStateTrait<T>::lookup_type
+ get(typename GRStateTrait<T>::key_type key) const {
+ return St->get<T>(key);
+ }
+
+ template<typename T>
+ GRStateRef set(typename GRStateTrait<T>::data_type D) {
+ return GRStateRef(Mgr->set<T>(St, D), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef set(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::value_type E,
+ typename GRStateTrait<T>::context_type C) {
+ return GRStateRef(Mgr->set<T>(St, K, E, C), *Mgr);
+ }
+
+ template<typename T>
+ GRStateRef remove(typename GRStateTrait<T>::key_type K,
+ typename GRStateTrait<T>::context_type C) {
+ return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
+ }
+};
+
+
} // end clang namespace
#endif
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=54788&r1=54787&r2=54788&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu Aug 14 16:16:54 2008
@@ -1192,20 +1192,60 @@
}
}
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// RefBindings - State used to track object reference counts.
+//===----------------------------------------------------------------------===//
+
+typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
+typedef RefBindings::Factory RefBFactoryTy;
+
+static int RefBIndex = 0;
+
+namespace clang {
+template<> struct GRStateTrait<RefBindings> {
+ typedef RefBindings data_type;
+ typedef RefBFactoryTy& context_type;
+ typedef SymbolID key_type;
+ typedef RefVal value_type;
+ typedef const RefVal* lookup_type;
+
+ static RefBindings MakeData(void* const* p) {
+ return p ? RefBindings((RefBindings::TreeTy*) *p) : RefBindings(0);
+ }
+ static void* MakeVoidPtr(RefBindings B) {
+ return B.getRoot();
+ }
+ static void* GDMIndex() {
+ return &RefBIndex;
+ }
+ static lookup_type Lookup(RefBindings B, SymbolID K) {
+ return B.lookup(K);
+ }
+ static data_type Set(RefBindings B, key_type K, value_type E,
+ RefBFactoryTy& F) {
+ return F.Add(B, K, E);
+ }
+
+ static data_type Remove(RefBindings B, SymbolID K, RefBFactoryTy& F) {
+ return F.Remove(B, K);
+ }
+};
+}
+
//===----------------------------------------------------------------------===//
// Transfer functions.
//===----------------------------------------------------------------------===//
+namespace {
+
class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
public:
// Type definitions.
- typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
-
- typedef RefBindings::Factory RefBFactoryTy;
-
typedef llvm::DenseMap<GRExprEngine::NodeTy*,std::pair<Expr*, SymbolID> >
ReleasesNotOwnedTy;
-
+
typedef ReleasesNotOwnedTy UseAfterReleasesTy;
typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
@@ -1225,30 +1265,18 @@
ReleasesNotOwnedTy ReleasesNotOwned;
LeaksTy Leaks;
BindingsPrinter Printer;
-
-public:
-
- static RefBindings GetRefBindings(const GRState& StImpl) {
- return RefBindings((const RefBindings::TreeTy*) StImpl.CheckerState);
- }
-
- static RefBindings GetRefBindings(const GRState* state) {
- return RefBindings((const RefBindings::TreeTy*) state->CheckerState);
- }
-
-private:
-
- static void SetRefBindings(GRState& StImpl, RefBindings B) {
- StImpl.CheckerState = B.getRoot();
- }
-
- RefBindings Remove(RefBindings B, SymbolID sym) {
- return RefBFactory.Remove(B, sym);
- }
RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
RefVal::Kind& hasErr);
+ RefVal::Kind& Update(GRStateRef& state, SymbolID sym, RefVal V,
+ ArgEffect E, RefVal::Kind& hasErr) {
+
+ state = state.set<RefBindings>(Update(state.get<RefBindings>(), sym, V,
+ E, hasErr));
+ return hasErr;
+ }
+
void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
GRStmtNodeBuilder<GRState>& Builder,
Expr* NodeExpr, Expr* ErrorExpr,
@@ -1260,9 +1288,6 @@
const GRState* St,
SymbolID sid, RefVal V, bool& hasLeak);
- const GRState* NukeBinding(GRStateManager& VMgr, const GRState* St,
- SymbolID sid);
-
public:
CFRefCount(ASTContext& Ctx, bool gcenabled, const LangOptions& lopts)
@@ -1370,7 +1395,7 @@
void CFRefCount::BindingsPrinter::Print(std::ostream& Out, const GRState* state,
const char* nl, const char* sep) {
- RefBindings B = GetRefBindings(state);
+ RefBindings B = state->get<RefBindings>();
if (!B.isEmpty())
Out << sep << nl;
@@ -1464,34 +1489,25 @@
ExplodedNode<GRState>* Pred) {
// Get the state.
- GRStateManager& StateMgr = Eng.getStateManager();
- const GRState* St = Builder.GetState(Pred);
+ GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
// Evaluate the effect of the arguments.
- GRState StVals = *St;
RefVal::Kind hasErr = (RefVal::Kind) 0;
unsigned idx = 0;
Expr* ErrorExpr = NULL;
SymbolID ErrorSym = 0;
- for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
-
- RVal V = StateMgr.GetRVal(St, *I);
+ for (ExprIterator I = arg_beg; I != arg_end; ++I, ++idx) {
+ RVal V = state.GetRVal(*I);
if (isa<lval::SymbolVal>(V)) {
SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
- RefBindings B = GetRefBindings(StVals);
-
- if (RefBindings::data_type* T = B.lookup(Sym)) {
- B = Update(B, Sym, *T, GetArgE(Summ, idx), hasErr);
- SetRefBindings(StVals, B);
-
- if (hasErr) {
+ if (RefBindings::data_type* T = state.get<RefBindings>(Sym))
+ if (Update(state, Sym, *T, GetArgE(Summ, idx), hasErr)) {
ErrorExpr = *I;
ErrorSym = Sym;
break;
}
- }
}
else if (isa<LVal>(V)) {
#if 0
@@ -1515,58 +1531,48 @@
// disambiguate conjured symbols.
// Is the invalidated variable something that we were tracking?
- RVal X = StateMgr.GetRVal(&StVals, *DV);
+ RVal X = state.GetRVal(*DV);
if (isa<lval::SymbolVal>(X)) {
SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
- SetRefBindings(StVals,RefBFactory.Remove(GetRefBindings(StVals),Sym));
+ state = state.remove<RefBindings>(Sym, RefBFactory);
}
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
SymbolID NewSym = Eng.getSymbolManager().getConjuredSymbol(*I, Count);
-
- StateMgr.SetRVal(StVals, *DV,
- LVal::IsLValType(DV->getDecl()->getType())
- ? cast<RVal>(lval::SymbolVal(NewSym))
- : cast<RVal>(nonlval::SymbolVal(NewSym)));
+
+ state = state.SetRVal(*DV,
+ LVal::IsLValType(DV->getDecl()->getType())
+ ? cast<RVal>(lval::SymbolVal(NewSym))
+ : cast<RVal>(nonlval::SymbolVal(NewSym)));
}
else {
// Nuke all other arguments passed by reference.
- StateMgr.Unbind(StVals, cast<LVal>(V));
+ state = state.Unbind(cast<LVal>(V));
}
#endif
}
else if (isa<nonlval::LValAsInteger>(V))
- StateMgr.Unbind(StVals, cast<nonlval::LValAsInteger>(V).getLVal());
+ state = state.Unbind(cast<nonlval::LValAsInteger>(V).getLVal());
}
// Evaluate the effect on the message receiver.
if (!ErrorExpr && Receiver) {
- RVal V = StateMgr.GetRVal(St, Receiver);
-
+ RVal V = state.GetRVal(Receiver);
if (isa<lval::SymbolVal>(V)) {
SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
- RefBindings B = GetRefBindings(StVals);
-
- if (const RefVal* T = B.lookup(Sym)) {
- B = Update(B, Sym, *T, GetReceiverE(Summ), hasErr);
- SetRefBindings(StVals, B);
-
- if (hasErr) {
+ if (const RefVal* T = state.get<RefBindings>(Sym))
+ if (Update(state, Sym, *T, GetReceiverE(Summ), hasErr)) {
ErrorExpr = Receiver;
ErrorSym = Sym;
}
- }
}
}
-
- // Get the persistent state.
- St = StateMgr.getPersistentState(StVals);
// Process any errors.
if (hasErr) {
- ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, St,
+ ProcessNonLeakError(Dst, Builder, Ex, ErrorExpr, Pred, state,
hasErr, ErrorSym);
return;
}
@@ -1592,7 +1598,7 @@
? cast<RVal>(lval::SymbolVal(Sym))
: cast<RVal>(nonlval::SymbolVal(Sym));
- St = StateMgr.SetRVal(St, Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
+ state = state.SetRVal(Ex, X, Eng.getCFG().isBlkExpr(Ex), false);
}
break;
@@ -1601,15 +1607,15 @@
unsigned idx = RE.getIndex();
assert (arg_end >= arg_beg);
assert (idx < (unsigned) (arg_end - arg_beg));
- RVal V = StateMgr.GetRVal(St, *(arg_beg+idx));
- St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
+ RVal V = state.GetRVal(*(arg_beg+idx));
+ state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
break;
}
case RetEffect::ReceiverAlias: {
assert (Receiver);
- RVal V = StateMgr.GetRVal(St, Receiver);
- St = StateMgr.SetRVal(St, Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
+ RVal V = state.GetRVal(Receiver);
+ state = state.SetRVal(Ex, V, Eng.getCFG().isBlkExpr(Ex), false);
break;
}
@@ -1619,17 +1625,19 @@
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, Eng.getContext());
- GRState StImpl = *St;
+ state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT), RefBFactory);
+ state = state.SetRVal(Ex, lval::SymbolVal(Sym),
+ Eng.getCFG().isBlkExpr(Ex), false);
+
+#if 0
RefBindings B = GetRefBindings(StImpl);
SetRefBindings(StImpl, RefBFactory.Add(B, Sym, RefVal::makeOwned(RetT)));
-
- St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
- Ex, lval::SymbolVal(Sym),
- Eng.getCFG().isBlkExpr(Ex), false);
+#endif
+
// FIXME: Add a flag to the checker where allocations are allowed to fail.
if (RE.getKind() == RetEffect::OwnedAllocatedSymbol)
- St = StateMgr.AddNE(St, Sym, Eng.getBasicVals().getZeroWithPtrWidth());
+ state = state.AddNE(Sym, Eng.getBasicVals().getZeroWithPtrWidth());
break;
}
@@ -1639,24 +1647,18 @@
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
QualType RetT = GetReturnType(Ex, Eng.getContext());
- GRState StImpl = *St;
- RefBindings B = GetRefBindings(StImpl);
- SetRefBindings(StImpl, RefBFactory.Add(B, Sym,
- RefVal::makeNotOwned(RetT)));
-
- St = StateMgr.SetRVal(StateMgr.getPersistentState(StImpl),
- Ex, lval::SymbolVal(Sym),
+ state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT), RefBFactory);
+ state = state.SetRVal(Ex, lval::SymbolVal(Sym),
Eng.getCFG().isBlkExpr(Ex), false);
-
break;
}
}
// Is this a sink?
if (IsEndPath(Summ))
- Builder.MakeSinkNode(Dst, Ex, Pred, St);
+ Builder.MakeSinkNode(Dst, Ex, Pred, state);
else
- Builder.MakeNode(Dst, Ex, Pred, St);
+ Builder.MakeNode(Dst, Ex, Pred, state);
}
@@ -1693,7 +1695,7 @@
if (isa<lval::SymbolVal>(V)) {
SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
- if (const RefVal* T = GetRefBindings(*St).lookup(Sym)) {
+ if (const RefVal* T = St->get<RefBindings>(Sym)) {
QualType Ty = T->getType();
if (const PointerType* PT = Ty->getAsPointerType()) {
@@ -1743,24 +1745,16 @@
SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol();
- if (!GetRefBindings(*St).lookup(Sym))
- return;
+ GRStateRef state(St, Eng.getStateManager());
- // Nuke the binding.
- St = NukeBinding(Eng.getStateManager(), St, Sym);
+ if (!state.get<RefBindings>(Sym))
+ return;
- // Hand of the remaining logic to the parent implementation.
- GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val);
-}
+ // Nuke the binding.
+ state = state.remove<RefBindings>(Sym, RefBFactory);
-
-const GRState* CFRefCount::NukeBinding(GRStateManager& VMgr,
- const GRState* St,
- SymbolID sid) {
- GRState StImpl = *St;
- RefBindings B = GetRefBindings(StImpl);
- StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot();
- return VMgr.getPersistentState(StImpl);
+ // Hand of the remaining logic to the parent implementation.
+ GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, state, TargetLV, Val);
}
// End-of-path.
@@ -1772,21 +1766,19 @@
hasLeak = V.isOwned() ||
((V.isNotOwned() || V.isReturnedOwned()) && V.getCount() > 0);
+ GRStateRef state(St, VMgr);
+
if (!hasLeak)
- return NukeBinding(VMgr, St, sid);
-
- RefBindings B = GetRefBindings(*St);
- GRState StImpl = *St;
- StImpl.CheckerState = RefBFactory.Add(B, sid, V^RefVal::ErrorLeak).getRoot();
+ return state.remove<RefBindings>(sid, RefBFactory);
- return VMgr.getPersistentState(StImpl);
+ return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak, RefBFactory);
}
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
GREndPathNodeBuilder<GRState>& Builder) {
const GRState* St = Builder.getState();
- RefBindings B = GetRefBindings(*St);
+ RefBindings B = St->get<RefBindings>();
llvm::SmallVector<SymbolID, 10> Leaked;
@@ -1828,7 +1820,7 @@
// FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
- RefBindings B = GetRefBindings(*St);
+ RefBindings B = St->get<RefBindings>();
llvm::SmallVector<SymbolID, 10> Leaked;
for (GRStateManager::DeadSymbolsTy::const_iterator
@@ -1875,27 +1867,23 @@
Expr* RetE = S->getRetValue();
if (!RetE) return;
- GRStateManager& StateMgr = Eng.getStateManager();
- const GRState* St = Builder.GetState(Pred);
- RVal V = StateMgr.GetRVal(St, RetE);
+ GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
+ RVal V = state.GetRVal(RetE);
if (!isa<lval::SymbolVal>(V))
return;
// Get the reference count binding (if any).
SymbolID Sym = cast<lval::SymbolVal>(V).getSymbol();
- RefBindings B = GetRefBindings(*St);
- const RefVal* T = B.lookup(Sym);
+ const RefVal* T = state.get<RefBindings>(Sym);
if (!T)
return;
- // Change the reference count.
-
+ // Change the reference count.
RefVal X = *T;
- switch (X.getKind()) {
-
+ switch (X.getKind()) {
case RefVal::Owned: {
unsigned cnt = X.getCount();
assert (cnt > 0);
@@ -1915,10 +1903,8 @@
}
// Update the binding.
-
- GRState StImpl = *St;
- StImpl.CheckerState = RefBFactory.Add(B, Sym, X).getRoot();
- Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
+ state = state.set<RefBindings>(Sym, X, RefBFactory);
+ Builder.MakeNode(Dst, S, Pred, state);
}
// Assumptions.
@@ -1934,7 +1920,7 @@
// too bad since the number of symbols we will track in practice are
// probably small and EvalAssume is only called at branches and a few
// other places.
- RefBindings B = GetRefBindings(*St);
+ RefBindings B = St->get<RefBindings>();
if (B.isEmpty())
return St;
@@ -1953,14 +1939,14 @@
if (!changed)
return St;
- GRState StImpl = *St;
- StImpl.CheckerState = B.getRoot();
- return VMgr.getPersistentState(StImpl);
+ GRStateRef state(St, VMgr);
+ state = state.set<RefBindings>(B);
+ return state;
}
-CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
- RefVal V, ArgEffect E,
- RefVal::Kind& hasErr) {
+RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
+ RefVal V, ArgEffect E,
+ RefVal::Kind& hasErr) {
// FIXME: This dispatch can potentially be sped up by unifiying it into
// a single switch statement. Opt for simplicity for now.
@@ -2215,8 +2201,8 @@
const GRState* PrevSt = PrevN->getState();
const GRState* CurrSt = N->getState();
- CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt);
- CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt);
+ RefBindings PrevB = PrevSt->get<RefBindings>();
+ RefBindings CurrB = CurrSt->get<RefBindings>();
const RefVal* PrevT = PrevB.lookup(Sym);
const RefVal* CurrT = CurrB.lookup(Sym);
@@ -2273,6 +2259,7 @@
// The typestate has changed.
std::ostringstream os;
+ std::string s;
switch (CurrV.getKind()) {
case RefVal::Owned:
@@ -2296,7 +2283,8 @@
os << " retain count.";
}
- Msg = os.str().c_str();
+ s = os.str();
+ Msg = s.c_str();
break;
@@ -2342,7 +2330,6 @@
static std::pair<ExplodedNode<GRState>*,VarDecl*>
GetAllocationSite(ExplodedNode<GRState>* N, SymbolID Sym) {
- typedef CFRefCount::RefBindings RefBindings;
ExplodedNode<GRState>* Last = N;
// Find the first node that referred to the tracked symbol. We also
@@ -2352,7 +2339,7 @@
while (N) {
const GRState* St = N->getState();
- RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState);
+ RefBindings B = St->get<RefBindings>();
if (!B.lookup(Sym))
break;
@@ -2392,17 +2379,12 @@
if (!getBugType().isLeak())
return RangedBugReport::getEndPath(BR, EndN);
- typedef CFRefCount::RefBindings RefBindings;
-
// Get the retain count.
-
- unsigned long RetCount =
- CFRefCount::GetRefBindings(*EndN->getState()).lookup(Sym)->getCount();
+ unsigned long RetCount = EndN->getState()->get<RefBindings>(Sym)->getCount();
// We are a leak. Walk up the graph to get to the first node where the
// symbol appeared, and also get the first VarDecl that tracked object
// is stored to.
-
ExplodedNode<GRState>* AllocNode = 0;
VarDecl* FirstDecl = 0;
llvm::tie(AllocNode, FirstDecl) = GetAllocationSite(EndN, Sym);
@@ -2434,7 +2416,6 @@
// Look in the *trimmed* graph at the immediate predecessor of EndN. Does
// it occur on the same line?
-
PathDiagnosticPiece::DisplayHint Hint = PathDiagnosticPiece::Above;
assert (!EndN->pred_empty()); // Not possible to have 0 predecessors.
Modified: cfe/trunk/lib/Analysis/GRState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRState.cpp?rev=54788&r1=54787&r2=54788&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRState.cpp (original)
+++ cfe/trunk/lib/Analysis/GRState.cpp Thu Aug 14 16:16:54 2008
@@ -178,11 +178,9 @@
const GRState* GRStateManager::getInitialState() {
- GRState StateImpl(EnvMgr.getInitialEnvironment(),
- StMgr->getInitialStore(),
- GDMFactory.GetEmptyMap(),
- CNEFactory.GetEmptyMap(),
- CEFactory.GetEmptyMap());
+ GRState StateImpl(EnvMgr.getInitialEnvironment(), StMgr->getInitialStore(),
+ GDMFactory.GetEmptyMap(), CNEFactory.GetEmptyMap(),
+ CEFactory.GetEmptyMap());
return getPersistentState(StateImpl);
}
@@ -307,6 +305,25 @@
for ( ; Beg != End ; ++Beg) (*Beg)->Print(Out, this, nl, sep);
}
+//===----------------------------------------------------------------------===//
+// Generic Data Map.
+//===----------------------------------------------------------------------===//
+
+void* const* GRState::FindGDM(void* K) const {
+ return GDM.lookup(K);
+}
+
+const GRState* GRStateManager::addGDM(const GRState* St, void* Key, void* Data){
+ GRState::GenericDataMap M1 = St->getGDM();
+ GRState::GenericDataMap M2 = GDMFactory.Add(M1, Key, Data);
+
+ if (M1 == M2)
+ return St;
+
+ GRState NewSt = *St;
+ NewSt.GDM = M2;
+ return getPersistentState(NewSt);
+}
//===----------------------------------------------------------------------===//
// Queries.
More information about the cfe-commits
mailing list