From 0d28d360b5559abda755e50b855ba5e59727d9cd Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 10 Mar 2011 03:50:34 +0000 Subject: [PATCH] When doing reachability analysis for warnings issued under DiagRuntimeBehavior, don't construct a ParentMap or CFGStmtMap. Instead, create a small set of Stmt* -> CFGBlock* mappings during CFG construction for only the statements we care about relating to the diagnostics we want to check for reachability. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127396 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/AnalysisContext.h | 3 ++ include/clang/Analysis/CFG.h | 2 +- lib/Analysis/AnalysisContext.cpp | 20 +++++++++++ lib/Analysis/CFG.cpp | 36 ++++++++++++++++--- lib/Sema/AnalysisBasedWarnings.cpp | 44 ++++++++++++++++-------- 5 files changed, 86 insertions(+), 19 deletions(-) diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index e449fe3c01..c4dbcb8825 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -92,6 +92,9 @@ public: bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } + void registerForcedBlockExpression(const Stmt *stmt); + const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + Stmt *getBody(); CFG *getCFG(); diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 18d31001b6..864c0caf0e 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -534,7 +534,7 @@ public: class BuildOptions { public: - typedef llvm::DenseMap ForcedBlkExprs; + typedef llvm::DenseMap ForcedBlkExprs; ForcedBlkExprs **forcedBlkExprs; bool PruneTriviallyFalseEdges:1; diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 0085f3af15..461468de92 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -74,6 +74,26 @@ const ImplicitParamDecl *AnalysisContext::getSelfDecl() const { return NULL; } +void AnalysisContext::registerForcedBlockExpression(const Stmt *stmt) { + if (!forcedBlkExprs) + forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); + // Default construct an entry for 'stmt'. + if (const ParenExpr *pe = dyn_cast(stmt)) + stmt = pe->IgnoreParens(); + (void) (*forcedBlkExprs)[stmt]; +} + +const CFGBlock * +AnalysisContext::getBlockForRegisteredExpression(const Stmt *stmt) { + assert(forcedBlkExprs); + if (const ParenExpr *pe = dyn_cast(stmt)) + stmt = pe->IgnoreParens(); + CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = + forcedBlkExprs->find(stmt); + assert(itr != forcedBlkExprs->end()); + return itr->second; +} + CFG *AnalysisContext::getCFG() { if (useUnoptimizedCFG) return getUnoptimizedCFG(); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index a22a5aa033..fa054f66e2 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -282,6 +282,8 @@ class CFGBuilder { // State to track for building switch statements. bool switchExclusivelyCovered; Expr::EvalResult *switchCond; + + CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry; public: explicit CFGBuilder(ASTContext *astContext, @@ -290,11 +292,14 @@ public: Block(NULL), Succ(NULL), SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL), TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), - switchExclusivelyCovered(false), switchCond(0) {} + switchExclusivelyCovered(false), switchCond(0), + cachedEntry(0) {} // buildCFG - Used by external clients to construct the CFG. CFG* buildCFG(const Decl *D, Stmt *Statement); + bool alwaysAdd(const Stmt *stmt); + private: // Visitors to walk an AST and construct the CFG. CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); @@ -387,6 +392,12 @@ private: // Interface to CFGBlock - adding CFGElements. void appendStmt(CFGBlock *B, Stmt *S) { + if (cachedEntry) { + assert(cachedEntry->first == S); + cachedEntry->second = B; + cachedEntry = 0; + } + B->appendStmt(S, cfg->getBumpVectorContext()); } void appendInitializer(CFGBlock *B, CXXCtorInitializer *I) { @@ -443,9 +454,26 @@ private: }; -bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, - const Stmt *stmt) const { - return kind == AlwaysAdd; +inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder, + const Stmt *stmt) const { + return builder.alwaysAdd(stmt) || kind == AlwaysAdd; +} + +bool CFGBuilder::alwaysAdd(const Stmt *stmt) { + if (!BuildOpts.forcedBlkExprs) + return false; + + CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs; + + if (!fb) + return false; + + CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt); + if (itr == fb->end()) + return false; + + cachedEntry = &*itr; + return true; } // FIXME: Add support for dependent-sized array types in C++? diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 710f5ef70f..6c29f38bf7 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -546,25 +546,41 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, // Emit delayed diagnostics. if (!fscope->PossiblyUnreachableDiags.empty()) { bool analyzed = false; - if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) - if (CFGStmtMap *csm = AC.getCFGStmtMap()) { - analyzed = true; - for (llvm::SmallVectorImpl::iterator - i = fscope->PossiblyUnreachableDiags.begin(), - e = fscope->PossiblyUnreachableDiags.end(); - i != e; ++i) { - const sema::PossiblyUnreachableDiag &D = *i; - if (const CFGBlock *blk = csm->getBlock(D.stmt)) { + + // Register the expressions with the CFGBuilder. + for (llvm::SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + if (const Stmt *stmt = i->stmt) + AC.registerForcedBlockExpression(stmt); + } + + if (AC.getCFG()) { + analyzed = true; + for (llvm::SmallVectorImpl::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) + { + const sema::PossiblyUnreachableDiag &D = *i; + bool processed = false; + if (const Stmt *stmt = i->stmt) { + const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); + assert(block); + if (CFGReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { // Can this block be reached from the entrance? - if (cra->isReachable(&AC.getCFG()->getEntry(), blk)) + if (cra->isReachable(&AC.getCFG()->getEntry(), block)) S.Diag(D.Loc, D.PD); + processed = true; } - else { - // Emit the warning anyway if we cannot map to a basic block. - S.Diag(D.Loc, D.PD); - } + } + if (!processed) { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); } } + } if (!analyzed) flushDiagnostics(S, fscope); -- 2.40.0