Remove references to 'Checker' and 'GRTransferFuncs' from

GRStateManager.  Having these references was an abstraction violation,
as they really should only be known about GRExprEngine.

This change required adding a new 'ProcessAssume' callback in
GRSubEngine.  GRExprEngine implements this callback by calling
'EvalAssume' on all registered Checker objects as well as the
registered GRTransferFunc object.

llvm-svn: 92549
This commit is contained in:
Ted Kremenek 2010-01-05 00:15:18 +00:00
parent 646aacb097
commit de8e7447b6
10 changed files with 81 additions and 115 deletions

View File

@ -25,6 +25,7 @@ namespace clang {
class GRState;
class GRStateManager;
class GRSubEngine;
class SVal;
class ConstraintManager {
@ -64,8 +65,10 @@ public:
virtual bool canReasonAbout(SVal X) const = 0;
};
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr);
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr);
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
GRSubEngine &subengine);
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
GRSubEngine &subengine);
} // end clang namespace

View File

@ -87,9 +87,11 @@ class GRExprEngine : public GRSubEngine {
// this object be placed at the very end of member variables so that its
// destructor is called before the rest of the GRExprEngine is destroyed.
GRBugReporter BR;
llvm::OwningPtr<GRTransferFuncs> TF;
public:
GRExprEngine(AnalysisManager &mgr);
GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf);
~GRExprEngine();
@ -104,18 +106,14 @@ public:
SValuator &getSValuator() { return SVator; }
GRTransferFuncs& getTF() { return *StateMgr.TF; }
GRTransferFuncs& getTF() { return *TF; }
BugReporter& getBugReporter() { return BR; }
GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
/// setTransferFunctions
void setTransferFunctionsAndCheckers(GRTransferFuncs* tf);
void setTransferFunctions(GRTransferFuncs& tf) {
setTransferFunctionsAndCheckers(&tf);
}
// FIXME: Remove once GRTransferFuncs is no longer referenced.
void setTransferFunction(GRTransferFuncs* tf);
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
@ -173,6 +171,10 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ProcessEndPath(GREndPathNodeBuilder& builder);
/// EvalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManager() const { return StateMgr; }

View File

@ -40,10 +40,10 @@
namespace clang {
class GRStateManager;
class GRTransferFuncs;
class Checker;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
GRSubEngine&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===//
@ -159,10 +159,6 @@ public:
BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const;
GRTransferFuncs &getTransferFuncs() const;
std::vector<std::pair<void *, Checker *> >::iterator checker_begin() const;
std::vector<std::pair<void *, Checker *> >::iterator checker_end() const;
//==---------------------------------------------------------------------==//
// Constraints on values.
@ -391,9 +387,8 @@ public:
//===----------------------------------------------------------------------===//
class GRStateManager {
friend class GRExprEngine;
friend class GRState;
friend class GRExprEngine; // FIXME: Remove.
private:
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr;
@ -416,27 +411,20 @@ private:
ValueManager ValueMgr;
/// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc;
/// TF - Object that represents a bundle of transfer functions
/// for manipulating and creating SVals.
GRTransferFuncs* TF;
/// Reference to all checkers in GRExprEngine.
std::vector<std::pair<void *, Checker*> > *Checkers;
llvm::BumpPtrAllocator &Alloc;
public:
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc)
llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng)
: EnvMgr(alloc),
GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this),
Alloc(alloc) {
StoreMgr.reset((*CreateStoreManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
}
~GRStateManager();
@ -446,10 +434,6 @@ public:
ASTContext &getContext() { return ValueMgr.getContext(); }
const ASTContext &getContext() const { return ValueMgr.getContext(); }
GRTransferFuncs& getTransferFuncs() { return *TF; }
std::vector<std::pair<void *, Checker *> > &getCheckers() { return *Checkers;}
BasicValueFactory &getBasicVals() {
return ValueMgr.getBasicValueFactory();
}
@ -702,20 +686,6 @@ inline SymbolManager &GRState::getSymbolManager() const {
return getStateManager().getSymbolManager();
}
inline GRTransferFuncs &GRState::getTransferFuncs() const {
return getStateManager().getTransferFuncs();
}
inline std::vector<std::pair<void *, Checker *> >::iterator
GRState::checker_begin() const {
return getStateManager().getCheckers().begin();
}
inline std::vector<std::pair<void *, Checker *> >::iterator
GRState::checker_end() const {
return getStateManager().getCheckers().end();
}
template<typename T>
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
return getStateManager().add<T>(this, K, get_context<T>());

View File

@ -13,6 +13,8 @@
#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
#include "clang/Analysis/PathSensitive/SVals.h"
namespace clang {
class Stmt;
@ -62,8 +64,12 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0;
/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
virtual const GRState* ProcessAssume(const GRState *state,
SVal cond, bool assumption) = 0;
};
}
#endif

View File

@ -49,8 +49,9 @@ class BasicConstraintManager
: public SimpleConstraintManager {
GRState::IntSetTy::Factory ISetFactory;
public:
BasicConstraintManager(GRStateManager& statemgr)
: ISetFactory(statemgr.getAllocator()) {}
BasicConstraintManager(GRStateManager &statemgr, GRSubEngine &subengine)
: SimpleConstraintManager(subengine),
ISetFactory(statemgr.getAllocator()) {}
const GRState* AssumeSymNE(const GRState* state, SymbolRef sym,
const llvm::APSInt& V);
@ -88,9 +89,9 @@ public:
} // end anonymous namespace
ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& StateMgr)
{
return new BasicConstraintManager(StateMgr);
ConstraintManager* clang::CreateBasicConstraintManager(GRStateManager& statemgr,
GRSubEngine &subengine) {
return new BasicConstraintManager(statemgr, subengine);
}
const GRState*

View File

@ -300,23 +300,27 @@ static void RegisterInternalChecks(GRExprEngine &Eng) {
RegisterOSAtomicChecker(Eng);
}
GRExprEngine::GRExprEngine(AnalysisManager &mgr)
GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf)
: AMgr(mgr),
CoreEngine(mgr.getASTContext(), *this),
G(CoreEngine.getGraph()),
Builder(NULL),
StateMgr(G.getContext(), mgr.getStoreManagerCreator(),
mgr.getConstraintManagerCreator(), G.getAllocator()),
mgr.getConstraintManagerCreator(), G.getAllocator(),
*this),
SymMgr(StateMgr.getSymbolManager()),
ValMgr(StateMgr.getValueManager()),
SVator(ValMgr.getSValuator()),
CurrentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", G.getContext())),
BR(mgr, *this)
{
BR(mgr, *this), TF(tf) {
// Register internal checks.
RegisterInternalChecks(*this);
// FIXME: Eventually remove the TF object entirely.
TF->RegisterChecks(*this);
TF->RegisterPrinters(getStateManager().Printers);
}
GRExprEngine::~GRExprEngine() {
@ -330,13 +334,6 @@ GRExprEngine::~GRExprEngine() {
// Utility methods.
//===----------------------------------------------------------------------===//
void GRExprEngine::setTransferFunctionsAndCheckers(GRTransferFuncs* tf) {
StateMgr.TF = tf;
StateMgr.Checkers = &Checkers;
tf->RegisterChecks(*this);
tf->RegisterPrinters(getStateManager().Printers);
}
void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
if (!BatchAuditor)
BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
@ -415,6 +412,25 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
// Top-level transfer function logic (Dispatcher).
//===----------------------------------------------------------------------===//
/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
bool assumption) {
for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
I != E; ++I) {
if (!state)
return NULL;
state = I->second->EvalAssume(state, cond, assumption);
}
if (!state)
return NULL;
return TF->EvalAssume(state, cond, assumption);
}
void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
CurrentStmt = CE.getStmt();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),

View File

@ -234,7 +234,8 @@ namespace {
class RangeConstraintManager : public SimpleConstraintManager{
RangeSet GetRange(const GRState *state, SymbolRef sym);
public:
RangeConstraintManager() {}
RangeConstraintManager(GRSubEngine &subengine)
: SimpleConstraintManager(subengine) {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V);
@ -273,8 +274,9 @@ private:
} // end anonymous namespace
ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) {
return new RangeConstraintManager();
ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&,
GRSubEngine &subeng) {
return new RangeConstraintManager(subeng);
}
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St,

View File

@ -65,25 +65,10 @@ const GRState *SimpleConstraintManager::Assume(const GRState *state,
return Assume(state, cast<Loc>(Cond), Assumption);
}
const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond,
bool Assumption) {
state = AssumeAux(state, Cond, Assumption);
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
// true or false.
if (!state)
return 0;
std::vector<std::pair<void *, Checker*> >::iterator
I = state->checker_begin(), E = state->checker_end();
for (; I != E; ++I) {
state = I->second->EvalAssume(state, Cond, Assumption);
}
return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc cond,
bool assumption) {
state = AssumeAux(state, cond, assumption);
return SU.ProcessAssume(state, cond, assumption);
}
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
@ -130,26 +115,10 @@ const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,
}
const GRState *SimpleConstraintManager::Assume(const GRState *state,
NonLoc Cond,
bool Assumption) {
state = AssumeAux(state, Cond, Assumption);
// EvalAssume is used to call into the GRTransferFunction object to perform
// any checker-specific update of the state based on this assumption being
// true or false.
if (!state)
return 0;
std::vector<std::pair<void *, Checker*> >::iterator
I = state->checker_begin(), E = state->checker_end();
for (; I != E; ++I) {
state = I->second->EvalAssume(state, Cond, Assumption);
}
return state->getTransferFuncs().EvalAssume(state, Cond, Assumption);
NonLoc cond,
bool assumption) {
state = AssumeAux(state, cond, assumption);
return SU.ProcessAssume(state, cond, assumption);
}
const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,

View File

@ -20,8 +20,9 @@
namespace clang {
class SimpleConstraintManager : public ConstraintManager {
GRSubEngine &SU;
public:
SimpleConstraintManager() {}
SimpleConstraintManager(GRSubEngine &subengine) : SU(subengine) {}
virtual ~SimpleConstraintManager();
//===------------------------------------------------------------------===//

View File

@ -363,7 +363,7 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
if (!mgr.getLiveVariables(D))
return;
GRExprEngine Eng(mgr);
GRExprEngine Eng(mgr, TF.take());
if (C.Opts.EnableExperimentalInternalChecks)
RegisterExperimentalInternalChecks(Eng);
@ -373,8 +373,6 @@ static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
if (C.Opts.EnableExperimentalChecks)
RegisterExperimentalChecks(Eng);
Eng.setTransferFunctionsAndCheckers(tf);
// Set the graph auditor.
llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
if (mgr.shouldVisualizeUbigraph()) {
@ -494,7 +492,9 @@ static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
// Display progress.
C.DisplayFunction(D);
GRExprEngine Eng(mgr);
// FIXME: Make a fake transfer function. The GRTransferFunc interface
// eventually will be removed.
GRExprEngine Eng(mgr, new GRTransferFuncs());
if (C.Opts.EnableExperimentalInternalChecks)
RegisterExperimentalInternalChecks(Eng);
@ -503,10 +503,6 @@ static void ActionInlineCall(AnalysisConsumer &C, AnalysisManager &mgr,
if (C.Opts.EnableExperimentalChecks)
RegisterExperimentalChecks(Eng);
// Make a fake transfer function. The GRTransferFunc interface will be
// removed.
Eng.setTransferFunctionsAndCheckers(new GRTransferFuncs());
// Register call inliner as the last checker.
RegisterCallInliner(Eng);