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 GRState;
class GRStateManager; class GRStateManager;
class GRSubEngine;
class SVal; class SVal;
class ConstraintManager { class ConstraintManager {
@ -64,8 +65,10 @@ public:
virtual bool canReasonAbout(SVal X) const = 0; virtual bool canReasonAbout(SVal X) const = 0;
}; };
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr); ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr,
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr); GRSubEngine &subengine);
ConstraintManager* CreateRangeConstraintManager(GRStateManager& statemgr,
GRSubEngine &subengine);
} // end clang namespace } // 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 // 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. // destructor is called before the rest of the GRExprEngine is destroyed.
GRBugReporter BR; GRBugReporter BR;
llvm::OwningPtr<GRTransferFuncs> TF;
public: public:
GRExprEngine(AnalysisManager &mgr); GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf);
~GRExprEngine(); ~GRExprEngine();
@ -104,18 +106,14 @@ public:
SValuator &getSValuator() { return SVator; } SValuator &getSValuator() { return SVator; }
GRTransferFuncs& getTF() { return *StateMgr.TF; } GRTransferFuncs& getTF() { return *TF; }
BugReporter& getBugReporter() { return BR; } BugReporter& getBugReporter() { return BR; }
GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; } GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
/// setTransferFunctions // FIXME: Remove once GRTransferFuncs is no longer referenced.
void setTransferFunctionsAndCheckers(GRTransferFuncs* tf); void setTransferFunction(GRTransferFuncs* tf);
void setTransferFunctions(GRTransferFuncs& tf) {
setTransferFunctionsAndCheckers(&tf);
}
/// ViewGraph - Visualize the ExplodedGraph created by executing the /// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation. /// simulation.
@ -173,6 +171,10 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function. /// nodes when the control reaches the end of a function.
void ProcessEndPath(GREndPathNodeBuilder& builder); 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; } GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManager() const { return StateMgr; } const GRStateManager& getStateManager() const { return StateMgr; }

View File

@ -40,10 +40,10 @@
namespace clang { namespace clang {
class GRStateManager; class GRStateManager;
class GRTransferFuncs;
class Checker; class Checker;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&); typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&,
GRSubEngine&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&); typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -159,10 +159,6 @@ public:
BasicValueFactory &getBasicVals() const; BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() 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. // Constraints on values.
@ -391,9 +387,8 @@ public:
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
class GRStateManager { class GRStateManager {
friend class GRExprEngine;
friend class GRState; friend class GRState;
friend class GRExprEngine; // FIXME: Remove.
private: private:
EnvironmentManager EnvMgr; EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr; llvm::OwningPtr<StoreManager> StoreMgr;
@ -416,27 +411,20 @@ private:
ValueManager ValueMgr; ValueManager ValueMgr;
/// Alloc - A BumpPtrAllocator to allocate states. /// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc; 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;
public: public:
GRStateManager(ASTContext& Ctx, GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager, StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager, ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc) llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng)
: EnvMgr(alloc), : EnvMgr(alloc),
GDMFactory(alloc), GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this), ValueMgr(alloc, Ctx, *this),
Alloc(alloc) { Alloc(alloc) {
StoreMgr.reset((*CreateStoreManager)(*this)); StoreMgr.reset((*CreateStoreManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this)); ConstraintMgr.reset((*CreateConstraintManager)(*this, subeng));
} }
~GRStateManager(); ~GRStateManager();
@ -446,10 +434,6 @@ public:
ASTContext &getContext() { return ValueMgr.getContext(); } ASTContext &getContext() { return ValueMgr.getContext(); }
const ASTContext &getContext() const { 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() { BasicValueFactory &getBasicVals() {
return ValueMgr.getBasicValueFactory(); return ValueMgr.getBasicValueFactory();
} }
@ -702,20 +686,6 @@ inline SymbolManager &GRState::getSymbolManager() const {
return getStateManager().getSymbolManager(); 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> template<typename T>
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const { const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
return getStateManager().add<T>(this, K, get_context<T>()); return getStateManager().add<T>(this, K, get_context<T>());

View File

@ -13,6 +13,8 @@
#ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H #ifndef LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
#define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H #define LLVM_CLANG_ANALYSIS_GRSUBENGINE_H
#include "clang/Analysis/PathSensitive/SVals.h"
namespace clang { namespace clang {
class Stmt; class Stmt;
@ -62,8 +64,12 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function. /// nodes when the control reaches the end of a function.
virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0; 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 #endif

View File

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

View File

@ -300,23 +300,27 @@ static void RegisterInternalChecks(GRExprEngine &Eng) {
RegisterOSAtomicChecker(Eng); RegisterOSAtomicChecker(Eng);
} }
GRExprEngine::GRExprEngine(AnalysisManager &mgr) GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf)
: AMgr(mgr), : AMgr(mgr),
CoreEngine(mgr.getASTContext(), *this), CoreEngine(mgr.getASTContext(), *this),
G(CoreEngine.getGraph()), G(CoreEngine.getGraph()),
Builder(NULL), Builder(NULL),
StateMgr(G.getContext(), mgr.getStoreManagerCreator(), StateMgr(G.getContext(), mgr.getStoreManagerCreator(),
mgr.getConstraintManagerCreator(), G.getAllocator()), mgr.getConstraintManagerCreator(), G.getAllocator(),
*this),
SymMgr(StateMgr.getSymbolManager()), SymMgr(StateMgr.getSymbolManager()),
ValMgr(StateMgr.getValueManager()), ValMgr(StateMgr.getValueManager()),
SVator(ValMgr.getSValuator()), SVator(ValMgr.getSValuator()),
CurrentStmt(NULL), CurrentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", G.getContext())), RaiseSel(GetNullarySelector("raise", G.getContext())),
BR(mgr, *this) BR(mgr, *this), TF(tf) {
{
// Register internal checks. // Register internal checks.
RegisterInternalChecks(*this); RegisterInternalChecks(*this);
// FIXME: Eventually remove the TF object entirely.
TF->RegisterChecks(*this);
TF->RegisterPrinters(getStateManager().Printers);
} }
GRExprEngine::~GRExprEngine() { GRExprEngine::~GRExprEngine() {
@ -330,13 +334,6 @@ GRExprEngine::~GRExprEngine() {
// Utility methods. // 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) { void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
if (!BatchAuditor) if (!BatchAuditor)
BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator())); BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
@ -415,6 +412,25 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
// Top-level transfer function logic (Dispatcher). // 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) { void GRExprEngine::ProcessStmt(CFGElement CE, GRStmtNodeBuilder& builder) {
CurrentStmt = CE.getStmt(); CurrentStmt = CE.getStmt();
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),

View File

@ -234,7 +234,8 @@ namespace {
class RangeConstraintManager : public SimpleConstraintManager{ class RangeConstraintManager : public SimpleConstraintManager{
RangeSet GetRange(const GRState *state, SymbolRef sym); RangeSet GetRange(const GRState *state, SymbolRef sym);
public: public:
RangeConstraintManager() {} RangeConstraintManager(GRSubEngine &subengine)
: SimpleConstraintManager(subengine) {}
const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, const GRState* AssumeSymNE(const GRState* St, SymbolRef sym,
const llvm::APSInt& V); const llvm::APSInt& V);
@ -273,8 +274,9 @@ private:
} // end anonymous namespace } // end anonymous namespace
ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&) { ConstraintManager* clang::CreateRangeConstraintManager(GRStateManager&,
return new RangeConstraintManager(); GRSubEngine &subeng) {
return new RangeConstraintManager(subeng);
} }
const llvm::APSInt* RangeConstraintManager::getSymVal(const GRState* St, 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); return Assume(state, cast<Loc>(Cond), Assumption);
} }
const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc Cond, const GRState *SimpleConstraintManager::Assume(const GRState *state, Loc cond,
bool Assumption) { bool assumption) {
state = AssumeAux(state, cond, assumption);
state = AssumeAux(state, Cond, Assumption); return SU.ProcessAssume(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::AssumeAux(const GRState *state, 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, const GRState *SimpleConstraintManager::Assume(const GRState *state,
NonLoc Cond, NonLoc cond,
bool Assumption) { bool assumption) {
state = AssumeAux(state, cond, assumption);
state = AssumeAux(state, Cond, Assumption); return SU.ProcessAssume(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::AssumeAux(const GRState *state, const GRState *SimpleConstraintManager::AssumeAux(const GRState *state,

View File

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

View File

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