Don't warn on fall-through from unreachable code.

Summary:
A motivating example:
class ClassWithDtor {
public:
  ~ClassWithDtor() {}
};
void fallthrough3(int n) {
  switch (n) {
    case 2:
      do {
        ClassWithDtor temp;
        return;
      } while (0);  // This generates a chain of unreachable CFG blocks.
    case 3:
      break;
  }
}

Reviewers: rsmith, doug.gregor, alexfh

Reviewed By: alexfh

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D330

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173889 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 1687f69..b362239 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -702,7 +702,27 @@
       return FallthroughStmts;
     }
 
+    void fillReachableBlocks(CFG *Cfg) {
+      assert(ReachableBlocks.empty() && "ReachableBlocks already filled");
+      std::deque<const CFGBlock *> BlockQueue;
+
+      ReachableBlocks.insert(&Cfg->getEntry());
+      BlockQueue.push_back(&Cfg->getEntry());
+      while (!BlockQueue.empty()) {
+        const CFGBlock *P = BlockQueue.front();
+        BlockQueue.pop_front();
+        for (CFGBlock::const_succ_iterator I = P->succ_begin(),
+                                           E = P->succ_end();
+             I != E; ++I) {
+          if (ReachableBlocks.insert(*I))
+            BlockQueue.push_back(*I);
+        }
+      }
+    }
+
     bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) {
+      assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
+
       int UnannotatedCnt = 0;
       AnnotatedCnt = 0;
 
@@ -726,8 +746,7 @@
         if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
           continue; // Case label is preceded with a normal label, good.
 
-        if (P->pred_begin() == P->pred_end()) {  // The block is unreachable.
-          // This only catches trivially unreachable blocks.
+        if (!ReachableBlocks.count(P)) {
           for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end();
                ElIt != ElEnd; ++ElIt) {
             if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){
@@ -816,6 +835,7 @@
     bool FoundSwitchStatements;
     AttrStmts FallthroughStmts;
     Sema &S;
+    llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
   };
 }
 
@@ -847,7 +867,7 @@
   if (!Cfg)
     return;
 
-  int AnnotatedCnt;
+  FM.fillReachableBlocks(Cfg);
 
   for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) {
     const CFGBlock *B = *I;
@@ -856,6 +876,8 @@
     if (!Label || !isa<SwitchCase>(Label))
       continue;
 
+    int AnnotatedCnt;
+
     if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt))
       continue;