зеркало из https://github.com/microsoft/clang-1.git
Migrate the retain/release checker to not manage the RefBindings::Factory object
directly, but instead have GRStateManager manage it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54862 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
e96de3e913
Коммит
b9d17f9384
|
@ -566,6 +566,11 @@ public:
|
||||||
return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
|
return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
GRStateRef remove(typename GRStateTrait<T>::key_type K) {
|
||||||
|
return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
|
||||||
|
}
|
||||||
|
|
||||||
// Pretty-printing.
|
// Pretty-printing.
|
||||||
void print(std::ostream& Out, const char* nl = "\n",
|
void print(std::ostream& Out, const char* nl = "\n",
|
||||||
const char *sep = "") const;
|
const char *sep = "") const;
|
||||||
|
|
|
@ -54,11 +54,11 @@ namespace clang {
|
||||||
return *((typename data_type::Factory*) p);
|
return *((typename data_type::Factory*) p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
|
static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
|
||||||
return new typename data_type::Factory(Alloc);
|
return new typename data_type::Factory(Alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void DeleteContext(void* Ctx) {
|
static void DeleteContext(void* Ctx) {
|
||||||
delete (typename data_type::Factory*) Ctx;
|
delete (typename data_type::Factory*) Ctx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||||
|
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
|
||||||
#include "clang/Analysis/PathDiagnostic.h"
|
#include "clang/Analysis/PathDiagnostic.h"
|
||||||
#include "clang/Analysis/LocalCheckers.h"
|
#include "clang/Analysis/LocalCheckers.h"
|
||||||
#include "clang/Analysis/PathDiagnostic.h"
|
#include "clang/Analysis/PathDiagnostic.h"
|
||||||
|
@ -1199,40 +1200,14 @@ void RefVal::print(std::ostream& Out) const {
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
|
typedef llvm::ImmutableMap<SymbolID, RefVal> RefBindings;
|
||||||
typedef RefBindings::Factory RefBFactoryTy;
|
|
||||||
|
|
||||||
static int RefBIndex = 0;
|
static int RefBIndex = 0;
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
template<> struct GRStateTrait<RefBindings> {
|
template<>
|
||||||
typedef RefBindings data_type;
|
struct GRStateTrait<RefBindings> : public GRStatePartialTrait<RefBindings> {
|
||||||
typedef RefBFactoryTy& context_type;
|
static inline void* GDMIndex() { return &RefBIndex; }
|
||||||
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.
|
// Transfer functions.
|
||||||
|
@ -1260,19 +1235,20 @@ public:
|
||||||
private:
|
private:
|
||||||
RetainSummaryManager Summaries;
|
RetainSummaryManager Summaries;
|
||||||
const LangOptions& LOpts;
|
const LangOptions& LOpts;
|
||||||
RefBFactoryTy RefBFactory;
|
|
||||||
UseAfterReleasesTy UseAfterReleases;
|
UseAfterReleasesTy UseAfterReleases;
|
||||||
ReleasesNotOwnedTy ReleasesNotOwned;
|
ReleasesNotOwnedTy ReleasesNotOwned;
|
||||||
LeaksTy Leaks;
|
LeaksTy Leaks;
|
||||||
|
|
||||||
RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
|
RefBindings Update(RefBindings B, SymbolID sym, RefVal V, ArgEffect E,
|
||||||
RefVal::Kind& hasErr);
|
RefVal::Kind& hasErr, RefBindings::Factory& RefBFactory);
|
||||||
|
|
||||||
RefVal::Kind& Update(GRStateRef& state, SymbolID sym, RefVal V,
|
RefVal::Kind& Update(GRStateRef& state, SymbolID sym, RefVal V,
|
||||||
ArgEffect E, RefVal::Kind& hasErr) {
|
ArgEffect E, RefVal::Kind& hasErr) {
|
||||||
|
|
||||||
state = state.set<RefBindings>(Update(state.get<RefBindings>(), sym, V,
|
state = state.set<RefBindings>(Update(state.get<RefBindings>(), sym, V,
|
||||||
E, hasErr));
|
E, hasErr,
|
||||||
|
state.get_context<RefBindings>()));
|
||||||
return hasErr;
|
return hasErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1534,7 +1510,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||||
|
|
||||||
if (isa<lval::SymbolVal>(X)) {
|
if (isa<lval::SymbolVal>(X)) {
|
||||||
SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
|
SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
|
||||||
state = state.remove<RefBindings>(Sym, RefBFactory);
|
state = state.remove<RefBindings>(Sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the value of the variable to be a conjured symbol.
|
// Set the value of the variable to be a conjured symbol.
|
||||||
|
@ -1624,7 +1600,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||||
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
|
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
|
||||||
QualType RetT = GetReturnType(Ex, Eng.getContext());
|
QualType RetT = GetReturnType(Ex, Eng.getContext());
|
||||||
|
|
||||||
state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT), RefBFactory);
|
state = state.set<RefBindings>(Sym, RefVal::makeOwned(RetT));
|
||||||
state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
|
state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1644,7 +1620,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
|
||||||
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
|
SymbolID Sym = Eng.getSymbolManager().getConjuredSymbol(Ex, Count);
|
||||||
QualType RetT = GetReturnType(Ex, Eng.getContext());
|
QualType RetT = GetReturnType(Ex, Eng.getContext());
|
||||||
|
|
||||||
state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT), RefBFactory);
|
state = state.set<RefBindings>(Sym, RefVal::makeNotOwned(RetT));
|
||||||
state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
|
state = state.SetRVal(Ex, lval::SymbolVal(Sym), false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1747,7 +1723,7 @@ void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Nuke the binding.
|
// Nuke the binding.
|
||||||
state = state.remove<RefBindings>(Sym, RefBFactory);
|
state = state.remove<RefBindings>(Sym);
|
||||||
|
|
||||||
// Hand of the remaining logic to the parent implementation.
|
// Hand of the remaining logic to the parent implementation.
|
||||||
GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, state, TargetLV, Val);
|
GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, state, TargetLV, Val);
|
||||||
|
@ -1765,9 +1741,9 @@ const GRState* CFRefCount::HandleSymbolDeath(GRStateManager& VMgr,
|
||||||
GRStateRef state(St, VMgr);
|
GRStateRef state(St, VMgr);
|
||||||
|
|
||||||
if (!hasLeak)
|
if (!hasLeak)
|
||||||
return state.remove<RefBindings>(sid, RefBFactory);
|
return state.remove<RefBindings>(sid);
|
||||||
|
|
||||||
return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak, RefBFactory);
|
return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeak);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
|
void CFRefCount::EvalEndPath(GRExprEngine& Eng,
|
||||||
|
@ -1899,7 +1875,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<GRState>& Dst,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the binding.
|
// Update the binding.
|
||||||
state = state.set<RefBindings>(Sym, X, RefBFactory);
|
state = state.set<RefBindings>(Sym, X);
|
||||||
Builder.MakeNode(Dst, S, Pred, state);
|
Builder.MakeNode(Dst, S, Pred, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1922,6 +1898,9 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
|
||||||
return St;
|
return St;
|
||||||
|
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
|
GRStateRef state(St, VMgr);
|
||||||
|
RefBindings::Factory& RefBFactory = state.get_context<RefBindings>();
|
||||||
|
|
||||||
for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
|
for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
|
||||||
// Check if the symbol is null (or equal to any constant).
|
// Check if the symbol is null (or equal to any constant).
|
||||||
|
@ -1932,17 +1911,16 @@ const GRState* CFRefCount::EvalAssume(GRStateManager& VMgr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!changed)
|
if (changed)
|
||||||
return St;
|
state = state.set<RefBindings>(B);
|
||||||
|
|
||||||
GRStateRef state(St, VMgr);
|
|
||||||
state = state.set<RefBindings>(B);
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
|
RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
|
||||||
RefVal V, ArgEffect E,
|
RefVal V, ArgEffect E,
|
||||||
RefVal::Kind& hasErr) {
|
RefVal::Kind& hasErr,
|
||||||
|
RefBindings::Factory& RefBFactory) {
|
||||||
|
|
||||||
// FIXME: This dispatch can potentially be sped up by unifiying it into
|
// FIXME: This dispatch can potentially be sped up by unifiying it into
|
||||||
// a single switch statement. Opt for simplicity for now.
|
// a single switch statement. Opt for simplicity for now.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче