forked from OSchip/llvm-project
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:
parent
a29dc05eaf
commit
16e3f0e03f
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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),
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#include "clang/Driver/ManagerRegistry.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
StoreManagerCreator ManagerRegistry::StoreMgrCreator = 0;
|
||||
|
||||
ConstraintManagerCreator ManagerRegistry::ConstraintMgrCreator = 0;
|
Loading…
Reference in New Issue