aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-03-10 03:50:34 +0000
committerTed Kremenek <kremenek@apple.com>2011-03-10 03:50:34 +0000
commit0d28d360b5559abda755e50b855ba5e59727d9cd (patch)
tree51890a6ad004bbc62e394584103d384a9121967d /lib/Analysis
parentd5e3ed085032def4ac875d64cb029fc3926652ed (diff)
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
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/AnalysisContext.cpp20
-rw-r--r--lib/Analysis/CFG.cpp36
2 files changed, 52 insertions, 4 deletions
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<ParenExpr>(stmt))
+ stmt = pe->IgnoreParens();
+ (void) (*forcedBlkExprs)[stmt];
+}
+
+const CFGBlock *
+AnalysisContext::getBlockForRegisteredExpression(const Stmt *stmt) {
+ assert(forcedBlkExprs);
+ if (const ParenExpr *pe = dyn_cast<ParenExpr>(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++?