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
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 0085f3a..461468d 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -74,6 +74,26 @@
   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 a22a5aa..fa054f6 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -282,6 +282,8 @@
   // 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 @@
       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 @@
 
   // 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 @@
   
 };
 
-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++?