From: Ted Kremenek Date: Thu, 14 Aug 2008 21:16:54 +0000 (+0000) Subject: Migrated retain/release checker to use the Generic Data Map in GRState (instead X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=72cd17f0a4722e1fa3eb47c08a7aa29aeba16754;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54788 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index d8609a8ddf..504383fd12 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -47,6 +47,8 @@ class GRTransferFuncs; // GRState- An ImmutableMap type Stmt*/Decl*/Symbols to RVals. //===----------------------------------------------------------------------===// +template 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 @@ public: GenericDataMap GDM; ConstNotEqTy ConstNotEq; ConstEqTy ConstEq; - void* CheckerState; public: @@ -85,8 +86,7 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 GRStateTrait::data_type get() const { + return GRStateTrait::MakeData(FindGDM(GRStateTrait::GDMIndex())); + } + + template + typename GRStateTrait::lookup_type + get(typename GRStateTrait::key_type key) const { + void* const* d = FindGDM(GRStateTrait::GDMIndex()); + return GRStateTrait::Lookup(GRStateTrait::MakeData(d), key); + } + + // State pretty-printing. class Printer { public: virtual ~Printer() {} @@ -183,7 +197,7 @@ public: void printStdErr(Printer **Beg = 0, Printer **End = 0) const; void printDOT(std::ostream& Out, Printer **Beg = 0, Printer **End = 0) const; -}; +}; template<> struct GRTrait { static inline void* toPtr(GRState* St) { return (void*) St; } @@ -195,6 +209,7 @@ template<> struct GRTrait { } }; + class GRStateSet { typedef llvm::SmallPtrSet ImplTy; ImplTy Impl; @@ -226,7 +241,11 @@ public: S.Add(St); } }; -}; +}; + +//===----------------------------------------------------------------------===// +// GRStateManager - Factory object for GRStates. +//===----------------------------------------------------------------------===// class GRStateManager { friend class GRExprEngine; @@ -349,18 +368,8 @@ public: } // 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 @@ public: 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 + const GRState* set(const GRState* st, typename GRStateTrait::data_type D) { + return addGDM(st, GRStateTrait::GDMIndex(), + GRStateTrait::MakeVoidPtr(D)); + } + + template + const GRState* set(const GRState* st, + typename GRStateTrait::key_type K, + typename GRStateTrait::value_type V, + typename GRStateTrait::context_type C) { + + return addGDM(st, GRStateTrait::GDMIndex(), + GRStateTrait::MakeVoidPtr(GRStateTrait::Set(st->get(), K, V, C))); + } + + template + const GRState* remove(const GRState* st, + typename GRStateTrait::key_type K, + typename GRStateTrait::context_type C) { + + return addGDM(st, GRStateTrait::GDMIndex(), + GRStateTrait::MakeVoidPtr(GRStateTrait::Remove(st->get(), K, C))); + } + // Assumption logic. const GRState* Assume(const GRState* St, RVal Cond, bool Assumption, bool& isFeasible) { @@ -440,6 +475,86 @@ private: 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 GRStateTrait::data_type get() const { + return St->get(); + } + + template + typename GRStateTrait::lookup_type + get(typename GRStateTrait::key_type key) const { + return St->get(key); + } + + template + GRStateRef set(typename GRStateTrait::data_type D) { + return GRStateRef(Mgr->set(St, D), *Mgr); + } + + template + GRStateRef set(typename GRStateTrait::key_type K, + typename GRStateTrait::value_type E, + typename GRStateTrait::context_type C) { + return GRStateRef(Mgr->set(St, K, E, C), *Mgr); + } + + template + GRStateRef remove(typename GRStateTrait::key_type K, + typename GRStateTrait::context_type C) { + return GRStateRef(Mgr->remove(St, K, C), *Mgr); + } +}; + + } // end clang namespace #endif diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 256072ab3a..9a769988a1 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1192,20 +1192,60 @@ void RefVal::print(std::ostream& Out) const { } } +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// RefBindings - State used to track object reference counts. +//===----------------------------------------------------------------------===// + +typedef llvm::ImmutableMap RefBindings; +typedef RefBindings::Factory RefBFactoryTy; + +static int RefBIndex = 0; + +namespace clang { +template<> struct GRStateTrait { + 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 RefBindings; - - typedef RefBindings::Factory RefBFactoryTy; - typedef llvm::DenseMap > ReleasesNotOwnedTy; - + typedef ReleasesNotOwnedTy UseAfterReleasesTy; typedef llvm::DenseMap*> @@ -1225,30 +1265,18 @@ private: 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(Update(state.get(), sym, V, + E, hasErr)); + return hasErr; + } + void ProcessNonLeakError(ExplodedNodeSet& Dst, GRStmtNodeBuilder& Builder, Expr* NodeExpr, Expr* ErrorExpr, @@ -1260,9 +1288,6 @@ private: 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 @@ public: void CFRefCount::BindingsPrinter::Print(std::ostream& Out, const GRState* state, const char* nl, const char* sep) { - RefBindings B = GetRefBindings(state); + RefBindings B = state->get(); if (!B.isEmpty()) Out << sep << nl; @@ -1464,34 +1489,25 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, ExplodedNode* 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(V)) { SymbolID Sym = cast(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(Sym)) + if (Update(state, Sym, *T, GetArgE(Summ, idx), hasErr)) { ErrorExpr = *I; ErrorSym = Sym; break; } - } } else if (isa(V)) { #if 0 @@ -1515,58 +1531,48 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, // 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(X)) { SymbolID Sym = cast(X).getSymbol(); - SetRefBindings(StVals,RefBFactory.Remove(GetRefBindings(StVals),Sym)); + state = state.remove(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(lval::SymbolVal(NewSym)) - : cast(nonlval::SymbolVal(NewSym))); + + state = state.SetRVal(*DV, + LVal::IsLValType(DV->getDecl()->getType()) + ? cast(lval::SymbolVal(NewSym)) + : cast(nonlval::SymbolVal(NewSym))); } else { // Nuke all other arguments passed by reference. - StateMgr.Unbind(StVals, cast(V)); + state = state.Unbind(cast(V)); } #endif } else if (isa(V)) - StateMgr.Unbind(StVals, cast(V).getLVal()); + state = state.Unbind(cast(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(V)) { SymbolID Sym = cast(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(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 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, ? cast(lval::SymbolVal(Sym)) : cast(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 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, 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 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count); QualType RetT = GetReturnType(Ex, Eng.getContext()); - GRState StImpl = *St; + state = state.set(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 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, 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(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 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst, if (isa(V)) { SymbolID Sym = cast(V).getSymbol(); - if (const RefVal* T = GetRefBindings(*St).lookup(Sym)) { + if (const RefVal* T = St->get(Sym)) { QualType Ty = T->getType(); if (const PointerType* PT = Ty->getAsPointerType()) { @@ -1743,24 +1745,16 @@ void CFRefCount::EvalStore(ExplodedNodeSet& Dst, SymbolID Sym = cast(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(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(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 @@ const GRState* CFRefCount::HandleSymbolDeath(GRStateManager& VMgr, 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(sid, RefBFactory); - return VMgr.getPersistentState(StImpl); + return state.set(sid, V ^ RefVal::ErrorLeak, RefBFactory); } void CFRefCount::EvalEndPath(GRExprEngine& Eng, GREndPathNodeBuilder& Builder) { const GRState* St = Builder.getState(); - RefBindings B = GetRefBindings(*St); + RefBindings B = St->get(); llvm::SmallVector Leaked; @@ -1828,7 +1820,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst, // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor. - RefBindings B = GetRefBindings(*St); + RefBindings B = St->get(); llvm::SmallVector Leaked; for (GRStateManager::DeadSymbolsTy::const_iterator @@ -1875,27 +1867,23 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, 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(V)) return; // Get the reference count binding (if any). SymbolID Sym = cast(V).getSymbol(); - RefBindings B = GetRefBindings(*St); - const RefVal* T = B.lookup(Sym); + const RefVal* T = state.get(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 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, } // 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(Sym, X, RefBFactory); + Builder.MakeNode(Dst, S, Pred, state); } // Assumptions. @@ -1934,7 +1920,7 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr, // 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(); if (B.isEmpty()) return St; @@ -1953,14 +1939,14 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr, if (!changed) return St; - GRState StImpl = *St; - StImpl.CheckerState = B.getRoot(); - return VMgr.getPersistentState(StImpl); + GRStateRef state(St, VMgr); + state = state.set(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 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode* N, 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 CurrB = CurrSt->get(); const RefVal* PrevT = PrevB.lookup(Sym); const RefVal* CurrT = CurrB.lookup(Sym); @@ -2273,6 +2259,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode* N, // The typestate has changed. std::ostringstream os; + std::string s; switch (CurrV.getKind()) { case RefVal::Owned: @@ -2296,7 +2283,8 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode* N, os << " retain count."; } - Msg = os.str().c_str(); + s = os.str(); + Msg = s.c_str(); break; @@ -2342,7 +2330,6 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode* N, static std::pair*,VarDecl*> GetAllocationSite(ExplodedNode* N, SymbolID Sym) { - typedef CFRefCount::RefBindings RefBindings; ExplodedNode* Last = N; // Find the first node that referred to the tracked symbol. We also @@ -2352,7 +2339,7 @@ GetAllocationSite(ExplodedNode* N, SymbolID Sym) { while (N) { const GRState* St = N->getState(); - RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState); + RefBindings B = St->get(); if (!B.lookup(Sym)) break; @@ -2392,17 +2379,12 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, 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(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* AllocNode = 0; VarDecl* FirstDecl = 0; llvm::tie(AllocNode, FirstDecl) = GetAllocationSite(EndN, Sym); @@ -2434,7 +2416,6 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& BR, // 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. diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index 1c7df79c02..b945803804 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -178,11 +178,9 @@ const GRState* GRStateManager::AddEQ(const GRState* St, SymbolID sym, 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 @@ void GRState::print(std::ostream& Out, Printer** Beg, Printer** End, 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.