Add support for pluggable components of static analyzer.

- Creator function pointers are saved in ManagerRegistry.
 - The Register* class is used to notify ManagerRegistry new module is 
   available.
 - AnalysisManager queries ManagerRegistry for configurable module. Then it
   passes them to GRExprEngine, in turn to GRStateManager.

llvm-svn: 60143
This commit is contained in:
Zhongxing Xu 2008-11-27 01:55:08 +00:00
parent a29dc05eaf
commit 16e3f0e03f
6 changed files with 101 additions and 20 deletions

View File

@ -13,6 +13,7 @@
#include "ASTConsumers.h"
#include "clang/Driver/PathDiagnosticClients.h"
#include "clang/Driver/ManagerRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@ -129,12 +130,20 @@ namespace {
llvm::OwningPtr<LiveVariables> liveness;
llvm::OwningPtr<ParentMap> PM;
// Configurable components creators.
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
public:
AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
: D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false) {}
: D(d), Body(b), TU(0), AScope(ScopeDecl), C(c), DisplayedFunction(false) {
setManagerCreators();
}
AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu)
: D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {}
: D(0), Body(0), TU(tu), AScope(ScopeTU), C(c), DisplayedFunction(false) {
setManagerCreators();
}
Decl* getCodeDecl() const {
assert (AScope == ScopeDecl);
@ -151,14 +160,13 @@ namespace {
return TU;
}
GRStateManager::StoreManagerCreator getStoreManagerCreator() {
switch (C.SM) {
default:
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC)\
case NAME##Model: return Create##NAME##Manager;
#include "Analyses.def"
}
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
};
ConstraintManagerCreator getConstraintManagerCreator() {
return CreateConstraintMgr;
}
virtual CFG* getCFG() {
if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
@ -215,7 +223,7 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
bool shouldVisualizeGraphviz() const {
return C.VisGraphviz;
}
bool shouldVisualizeUbigraph() const {
return C.VisUbigraph;
}
@ -249,8 +257,33 @@ case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
<< MD->getSelector().getAsString() << "'\n";
}
}
private:
/// Set configurable analyzer components creators. First check if there are
/// components registered at runtime. Otherwise fall back to builtin
/// components.
void setManagerCreators() {
if (ManagerRegistry::StoreMgrCreator != 0) {
CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
}
else {
switch (C.SM) {
default:
assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
#include "Analyses.def"
}
}
if (ManagerRegistry::ConstraintMgrCreator != 0)
CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
else
CreateConstraintMgr = CreateBasicConstraintManager;
}
};
} // end anonymous namespace
namespace llvm {
@ -370,7 +403,8 @@ static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
if (!L) return;
GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
mgr.getStoreManagerCreator());
mgr.getStoreManagerCreator(),
mgr.getConstraintManagerCreator());
Eng.setTransferFunctions(tf);

View File

@ -182,8 +182,8 @@ protected:
public:
GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, LiveVariables& L,
GRStateManager::StoreManagerCreator SMC =
CreateBasicStoreManager);
StoreManagerCreator SMC = CreateBasicStoreManager,
ConstraintManagerCreator CMC = CreateBasicConstraintManager);
~GRExprEngine();

View File

@ -46,6 +46,9 @@ namespace clang {
class GRStateManager;
class GRTransferFuncs;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===//
// GRStateTrait - Traits used by the Generic Data Map of a GRState.
//===----------------------------------------------------------------------===//
@ -292,9 +295,6 @@ private:
public:
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,

View File

@ -0,0 +1,40 @@
#ifndef LLVM_CLANG_MANAGER_REGISTRY_H
#define LLVM_CLANG_MANAGER_REGISTRY_H
#include "clang/Analysis/PathSensitive/GRState.h"
namespace clang {
/// ManagerRegistry - This class records manager creators registered at
/// runtime. The information is communicated to AnalysisManager through static
/// members. Better design is expected.
class ManagerRegistry {
public:
static StoreManagerCreator StoreMgrCreator;
static ConstraintManagerCreator ConstraintMgrCreator;
};
/// RegisterConstraintManager - This class is used to setup the constraint
/// manager of the static analyzer. The constructor takes a creator function
/// pointer for creating the constraint manager.
///
/// It is used like this:
///
/// class MyConstraintManager {};
/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) {
/// return new MyConstraintManager(statemgr);
/// }
/// RegisterConstraintManager X(CreateMyConstraintManager);
class RegisterConstraintManager {
public:
RegisterConstraintManager(ConstraintManagerCreator CMC) {
assert(ManagerRegistry::ConstraintMgrCreator == 0
&& "ConstraintMgrCreator already set!");
ManagerRegistry::ConstraintMgrCreator = CMC;
}
};
}
#endif

View File

@ -116,13 +116,13 @@ static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx,
LiveVariables& L,
GRStateManager::StoreManagerCreator SMC)
StoreManagerCreator SMC,
ConstraintManagerCreator CMC)
: CoreEngine(cfg, CD, Ctx, *this),
G(CoreEngine.getGraph()),
Liveness(L),
Builder(NULL),
StateMgr(G.getContext(), SMC,
CreateBasicConstraintManager, G.getAllocator(), cfg, CD, L),
StateMgr(G.getContext(), SMC, CMC, G.getAllocator(), cfg, CD, L),
SymMgr(StateMgr.getSymbolManager()),
CurrentStmt(NULL),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),

View File

@ -0,0 +1,7 @@
#include "clang/Driver/ManagerRegistry.h"
using namespace clang;
StoreManagerCreator ManagerRegistry::StoreMgrCreator = 0;
ConstraintManagerCreator ManagerRegistry::ConstraintMgrCreator = 0;