From: Zhongxing Xu Date: Thu, 27 Nov 2008 01:55:08 +0000 (+0000) Subject: Add support for pluggable components of static analyzer. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=22438a8dfe9f2f273c0b1a47f3f80be782ea6f09;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60143 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Driver/AnalysisConsumer.cpp b/Driver/AnalysisConsumer.cpp index df46322b5e..14b4440695 100644 --- a/Driver/AnalysisConsumer.cpp +++ b/Driver/AnalysisConsumer.cpp @@ -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 liveness; llvm::OwningPtr 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); diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 765bc27df0..17be0370de 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -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(); diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 68f7921db3..c3ef35b460 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -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, diff --git a/include/clang/Driver/ManagerRegistry.h b/include/clang/Driver/ManagerRegistry.h new file mode 100644 index 0000000000..cfbbc30411 --- /dev/null +++ b/include/clang/Driver/ManagerRegistry.h @@ -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 diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 448c2aa6b6..7c34fb91d2 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -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), diff --git a/lib/Driver/ManagerRegistry.cpp b/lib/Driver/ManagerRegistry.cpp new file mode 100644 index 0000000000..7604d2895f --- /dev/null +++ b/lib/Driver/ManagerRegistry.cpp @@ -0,0 +1,7 @@ +#include "clang/Driver/ManagerRegistry.h" + +using namespace clang; + +StoreManagerCreator ManagerRegistry::StoreMgrCreator = 0; + +ConstraintManagerCreator ManagerRegistry::ConstraintMgrCreator = 0;