From b8ad5ee345fa1fdd1fa9253f2d01f69becc88a04 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 10 Mar 2011 01:14:05 +0000 Subject: [PATCH] Rework interaction between AnalysisContext and CFG::BuildOptions to keep a BuildOptions object around instead of keeping a copy of the flags. Moreover, change AnalysisContext to use an OwningPtr for created analysis objects instead of directly managing them. Finally, add a 'forcedBlkExprs' entry to CFG::BuildOptions that will be used by the CFGBuilder to force specific expressions to be block-level expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127385 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/AnalysisContext.h | 53 +++++++------ include/clang/Analysis/CFG.h | 9 ++- lib/Analysis/AnalysisContext.cpp | 96 ++++++++++++------------ lib/Analysis/CFG.cpp | 30 ++++---- 4 files changed, 94 insertions(+), 94 deletions(-) diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 8514514578..e449fe3c01 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/Analysis/CFG.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -27,8 +28,6 @@ namespace clang { class Decl; class Stmt; -class CFG; -class CFGBlock; class CFGReachabilityAnalysis; class CFGStmtMap; class LiveVariables; @@ -48,33 +47,32 @@ class AnalysisContext { // TranslationUnit is NULL if we don't have multiple translation units. idx::TranslationUnit *TU; - // AnalysisContext owns the following data. - CFG *cfg, *completeCFG; - CFGStmtMap *cfgStmtMap; + llvm::OwningPtr cfg, completeCFG; + llvm::OwningPtr cfgStmtMap; + + CFG::BuildOptions cfgBuildOptions; + CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; + bool builtCFG, builtCompleteCFG; - LiveVariables *liveness; - LiveVariables *relaxedLiveness; - ParentMap *PM; - PseudoConstantAnalysis *PCA; - CFGReachabilityAnalysis *CFA; - llvm::DenseMap *ReferencedBlockVars; + const bool useUnoptimizedCFG; + + llvm::OwningPtr liveness; + llvm::OwningPtr relaxedLiveness; + llvm::OwningPtr PM; + llvm::OwningPtr PCA; + llvm::OwningPtr CFA; + llvm::BumpPtrAllocator A; - bool UseUnoptimizedCFG; - bool AddEHEdges; - bool AddImplicitDtors; - bool AddInitializers; + + // FIXME: remove. + llvm::DenseMap *ReferencedBlockVars; + public: AnalysisContext(const Decl *d, idx::TranslationUnit *tu, bool useUnoptimizedCFG = false, bool addehedges = false, bool addImplicitDtors = false, - bool addInitializers = false) - : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0), - builtCFG(false), builtCompleteCFG(false), - liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0), - ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), - AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors), - AddInitializers(addInitializers) {} + bool addInitializers = false); ~AnalysisContext(); @@ -87,11 +85,12 @@ public: /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. - bool getAddEHEdges() const { return AddEHEdges; } - - bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } - bool getAddImplicitDtors() const { return AddImplicitDtors; } - bool getAddInitializers() const { return AddInitializers; } + bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } + bool getUseUnoptimizedCFG() const { + return cfgBuildOptions.PruneTriviallyFalseEdges; + } + bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } + bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } Stmt *getBody(); CFG *getCFG(); diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 03beba59da..18d31001b6 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -19,6 +19,8 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/DenseMap.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" #include @@ -532,13 +534,16 @@ public: class BuildOptions { public: + typedef llvm::DenseMap ForcedBlkExprs; + ForcedBlkExprs **forcedBlkExprs; + bool PruneTriviallyFalseEdges:1; bool AddEHEdges:1; bool AddInitializers:1; bool AddImplicitDtors:1; BuildOptions() - : PruneTriviallyFalseEdges(true) + : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) , AddEHEdges(false) , AddInitializers(false) , AddImplicitDtors(false) {} @@ -547,7 +552,7 @@ public: /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, - BuildOptions BO = BuildOptions()); + const BuildOptions &BO); /// createBlock - Create a new block in the CFG. The CFG owns the block; /// the caller should not directly free it. diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 62097ef20d..0085f3af15 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -29,6 +29,24 @@ using namespace clang; +AnalysisContext::AnalysisContext(const Decl *d, + idx::TranslationUnit *tu, + bool useUnoptimizedCFG, + bool addehedges, + bool addImplicitDtors, + bool addInitializers) + : D(d), TU(tu), + forcedBlkExprs(0), + builtCFG(false), builtCompleteCFG(false), + useUnoptimizedCFG(useUnoptimizedCFG), + ReferencedBlockVars(0) +{ + cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; + cfgBuildOptions.AddEHEdges = addehedges; + cfgBuildOptions.AddImplicitDtors = addImplicitDtors; + cfgBuildOptions.AddInitializers = addInitializers; +} + void AnalysisContextManager::clear() { for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) delete I->second; @@ -57,44 +75,38 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const { } CFG *AnalysisContext::getCFG() { - if (UseUnoptimizedCFG) + if (useUnoptimizedCFG) return getUnoptimizedCFG(); if (!builtCFG) { - CFG::BuildOptions B; - B.AddEHEdges = AddEHEdges; - B.AddImplicitDtors = AddImplicitDtors; - B.AddInitializers = AddInitializers; - cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), B); + cfg.reset(CFG::buildCFG(D, getBody(), + &D->getASTContext(), cfgBuildOptions)); // Even when the cfg is not successfully built, we don't // want to try building it again. builtCFG = true; } - return cfg; + return cfg.get(); } CFG *AnalysisContext::getUnoptimizedCFG() { if (!builtCompleteCFG) { - CFG::BuildOptions B; + CFG::BuildOptions B = cfgBuildOptions; B.PruneTriviallyFalseEdges = false; - B.AddEHEdges = AddEHEdges; - B.AddImplicitDtors = AddImplicitDtors; - B.AddInitializers = AddInitializers; - completeCFG = CFG::buildCFG(D, getBody(), &D->getASTContext(), B); + completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(), B)); // Even when the cfg is not successfully built, we don't // want to try building it again. builtCompleteCFG = true; } - return completeCFG; + return completeCFG.get(); } CFGStmtMap *AnalysisContext::getCFGStmtMap() { if (cfgStmtMap) - return cfgStmtMap; + return cfgStmtMap.get(); if (CFG *c = getCFG()) { - cfgStmtMap = CFGStmtMap::Build(c, &getParentMap()); - return cfgStmtMap; + cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); + return cfgStmtMap.get(); } return 0; @@ -102,11 +114,11 @@ CFGStmtMap *AnalysisContext::getCFGStmtMap() { CFGReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() { if (CFA) - return CFA; + return CFA.get(); if (CFG *c = getCFG()) { - CFA = new CFGReachabilityAnalysis(*c); - return CFA; + CFA.reset(new CFGReachabilityAnalysis(*c)); + return CFA.get(); } return 0; @@ -118,42 +130,37 @@ void AnalysisContext::dumpCFG() { ParentMap &AnalysisContext::getParentMap() { if (!PM) - PM = new ParentMap(getBody()); + PM.reset(new ParentMap(getBody())); return *PM; } PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() { if (!PCA) - PCA = new PseudoConstantAnalysis(getBody()); - return PCA; + PCA.reset(new PseudoConstantAnalysis(getBody())); + return PCA.get(); } LiveVariables *AnalysisContext::getLiveVariables() { if (!liveness) { - CFG *c = getCFG(); - if (!c) - return 0; - - liveness = new LiveVariables(*this); - liveness->runOnCFG(*c); - liveness->runOnAllBlocks(*c, 0, true); + if (CFG *c = getCFG()) { + liveness.reset(new LiveVariables(*this)); + liveness->runOnCFG(*c); + liveness->runOnAllBlocks(*c, 0, true); + } } - return liveness; + return liveness.get(); } LiveVariables *AnalysisContext::getRelaxedLiveVariables() { - if (!relaxedLiveness) { - CFG *c = getCFG(); - if (!c) - return 0; - - relaxedLiveness = new LiveVariables(*this, false); - relaxedLiveness->runOnCFG(*c); - relaxedLiveness->runOnAllBlocks(*c, 0, true); - } + if (!relaxedLiveness) + if (CFG *c = getCFG()) { + relaxedLiveness.reset(new LiveVariables(*this, false)); + relaxedLiveness->runOnCFG(*c); + relaxedLiveness->runOnAllBlocks(*c, 0, true); + } - return relaxedLiveness; + return relaxedLiveness.get(); } AnalysisContext *AnalysisContextManager::getContext(const Decl *D, @@ -370,14 +377,7 @@ AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) { //===----------------------------------------------------------------------===// AnalysisContext::~AnalysisContext() { - delete cfg; - delete completeCFG; - delete cfgStmtMap; - delete liveness; - delete relaxedLiveness; - delete PM; - delete PCA; - delete CFA; + delete forcedBlkExprs; delete ReferencedBlockVars; } diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index fa98f94057..0f5b1fae5c 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -275,22 +275,23 @@ class CFGBuilder { LabelSetTy AddressTakenLabels; bool badCFG; - CFG::BuildOptions BuildOpts; + const CFG::BuildOptions &BuildOpts; // State to track for building switch statements. bool switchExclusivelyCovered; Expr::EvalResult *switchCond; public: - explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG - Block(NULL), Succ(NULL), - SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), - TryTerminatedBlock(NULL), badCFG(false), - switchExclusivelyCovered(false), switchCond(0) {} + explicit CFGBuilder(ASTContext *astContext, + const CFG::BuildOptions &buildOpts) + : Context(astContext), cfg(new CFG()), // crew a new CFG + Block(NULL), Succ(NULL), + SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), + TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), + switchExclusivelyCovered(false), switchCond(0) {} // buildCFG - Used by external clients to construct the CFG. - CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, - CFG::BuildOptions BO); + CFG* buildCFG(const Decl *D, Stmt *Statement); private: // Visitors to walk an AST and construct the CFG. @@ -460,16 +461,11 @@ static const VariableArrayType *FindVA(const Type *t) { /// body (compound statement). The ownership of the returned CFG is /// transferred to the caller. If CFG construction fails, this method returns /// NULL. -CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C, - CFG::BuildOptions BO) { - - Context = C; +CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement) { assert(cfg.get()); if (!Statement) return NULL; - BuildOpts = BO; - // Create an empty block that will serve as the exit block for the CFG. Since // this is the first block added to the CFG, it will be implicitly registered // as the exit block. @@ -2768,9 +2764,9 @@ CFGBlock* CFG::createBlock() { /// buildCFG - Constructs a CFG from an AST. Ownership of the returned /// CFG is returned to the caller. CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C, - BuildOptions BO) { - CFGBuilder Builder; - return Builder.buildCFG(D, Statement, C, BO); + const BuildOptions &BO) { + CFGBuilder Builder(C, BO); + return Builder.buildCFG(D, Statement); } const CXXDestructorDecl * -- 2.40.0