Move the rest of the unreachable code analysis from libSema
to libAnalysis (with only the error reporting in libSema).

llvm-svn: 96893
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3863e15..5a2ab2c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2105,148 +2105,18 @@
   return;
 }
 
-static SourceLocation GetUnreachableLoc(CFGBlock &b, SourceRange &R1,
-                                        SourceRange &R2) {
-  Stmt *S;
-  unsigned sn = 0;
-  R1 = R2 = SourceRange();
 
-  top:
-  if (sn < b.size())
-    S = b[sn].getStmt();
-  else if (b.getTerminator())
-    S = b.getTerminator();
-  else
-    return SourceLocation();
-
-  switch (S->getStmtClass()) {
-  case Expr::BinaryOperatorClass: {
-    BinaryOperator *BO = cast<BinaryOperator>(S);
-    if (BO->getOpcode() == BinaryOperator::Comma) {
-      if (sn+1 < b.size())
-        return b[sn+1].getStmt()->getLocStart();
-      CFGBlock *n = &b;
-      while (1) {
-        if (n->getTerminator())
-          return n->getTerminator()->getLocStart();
-        if (n->succ_size() != 1)
-          return SourceLocation();
-        n = n[0].succ_begin()[0];
-        if (n->pred_size() != 1)
-          return SourceLocation();
-        if (!n->empty())
-          return n[0][0].getStmt()->getLocStart();
-      }
-    }
-    R1 = BO->getLHS()->getSourceRange();
-    R2 = BO->getRHS()->getSourceRange();
-    return BO->getOperatorLoc();
-  }
-  case Expr::UnaryOperatorClass: {
-    const UnaryOperator *UO = cast<UnaryOperator>(S);
-    R1 = UO->getSubExpr()->getSourceRange();
-    return UO->getOperatorLoc();
-  }
-  case Expr::CompoundAssignOperatorClass: {
-    const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
-    R1 = CAO->getLHS()->getSourceRange();
-    R2 = CAO->getRHS()->getSourceRange();
-    return CAO->getOperatorLoc();
-  }
-  case Expr::ConditionalOperatorClass: {
-    const ConditionalOperator *CO = cast<ConditionalOperator>(S);
-    return CO->getQuestionLoc();
-  }
-  case Expr::MemberExprClass: {
-    const MemberExpr *ME = cast<MemberExpr>(S);
-    R1 = ME->getSourceRange();
-    return ME->getMemberLoc();
-  }
-  case Expr::ArraySubscriptExprClass: {
-    const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
-    R1 = ASE->getLHS()->getSourceRange();
-    R2 = ASE->getRHS()->getSourceRange();
-    return ASE->getRBracketLoc();
-  }
-  case Expr::CStyleCastExprClass: {
-    const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
-    R1 = CSC->getSubExpr()->getSourceRange();
-    return CSC->getLParenLoc();
-  }
-  case Expr::CXXFunctionalCastExprClass: {
-    const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
-    R1 = CE->getSubExpr()->getSourceRange();
-    return CE->getTypeBeginLoc();
-  }
-  case Expr::ImplicitCastExprClass:
-    ++sn;
-    goto top;
-  case Stmt::CXXTryStmtClass: {
-    return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
-  }
-  default: ;
-  }
-  R1 = S->getSourceRange();
-  return S->getLocStart();
-}
-
-static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
-                               SourceManager &SM) {
-  std::queue<CFGBlock*> workq;
-  // Prep work queue
-  workq.push(e);
-  SourceRange R1, R2;
-  SourceLocation top = GetUnreachableLoc(*e, R1, R2);
-  bool FromMainFile = false;
-  bool FromSystemHeader = false;
-  bool TopValid = false;
-  if (top.isValid()) {
-    FromMainFile = SM.isFromMainFile(top);
-    FromSystemHeader = SM.isInSystemHeader(top);
-    TopValid = true;
-  }
-  // Solve
-  while (!workq.empty()) {
-    CFGBlock *item = workq.front();
-    workq.pop();
-    SourceLocation c = GetUnreachableLoc(*item, R1, R2);
-    if (c.isValid()
-        && (!TopValid
-            || (SM.isFromMainFile(c) && !FromMainFile)
-            || (FromSystemHeader && !SM.isInSystemHeader(c))
-            || SM.isBeforeInTranslationUnit(c, top))) {
-      top = c;
-      FromMainFile = SM.isFromMainFile(top);
-      FromSystemHeader = SM.isInSystemHeader(top);
-    }
-    live.set(item->getBlockID());
-    for (CFGBlock::succ_iterator I=item->succ_begin(),
-           E=item->succ_end();
-         I != E;
-         ++I) {
-      if ((*I) && !live[(*I)->getBlockID()]) {
-        live.set((*I)->getBlockID());
-        workq.push(*I);
-      }
-    }
-  }
-  return top;
-}
-
-static int LineCmp(const void *p1, const void *p2) {
-  SourceLocation *Line1 = (SourceLocation *)p1;
-  SourceLocation *Line2 = (SourceLocation *)p2;
-  return !(*Line1 < *Line2);
-}
 
 namespace {
-  struct ErrLoc {
-    SourceLocation Loc;
-    SourceRange R1;
-    SourceRange R2;
-    ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2)
-      : Loc(l), R1(r1), R2(r2) { }
-  };
+class UnreachableCodeHandler : public reachable_code::Callback {
+  Sema &S;
+public:
+  UnreachableCodeHandler(Sema *s) : S(*s) {}
+  
+  void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) {
+    S.Diag(L, diag::warn_unreachable) << R1 << R2;
+  }
+};  
 }
 
 /// CheckUnreachable - Check for unreachable code.
@@ -2257,66 +2127,8 @@
       Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored)
     return;
 
-  CFG *cfg = AC.getCFG();
-  if (cfg == 0)
-    return;
-
-  // Mark all live things first.
-  llvm::BitVector reachable(cfg->getNumBlockIDs());
-  unsigned numReachable = ScanReachableFromBlock(cfg->getEntry(), reachable);
-
-  // If there are no dead blocks, we're done.
-  if (numReachable == cfg->getNumBlockIDs())
-    return;
-
-  SourceRange R1, R2;
-
-  llvm::SmallVector<ErrLoc, 24> lines;
-  bool AddEHEdges = AC.getAddEHEdges();
-  // First, give warnings for blocks with no predecessors, as they
-  // can't be part of a loop.
-  for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
-    CFGBlock &b = **I;
-    if (!reachable[b.getBlockID()]) {
-      if (b.pred_empty()) {
-        if (!AddEHEdges && dyn_cast_or_null<CXXTryStmt>(b.getTerminator())) {
-          // When not adding EH edges from calls, catch clauses
-          // can otherwise seem dead.  Avoid noting them as dead.
-          numReachable += ScanReachableFromBlock(b, reachable);
-          continue;
-        }
-        SourceLocation c = GetUnreachableLoc(b, R1, R2);
-        if (!c.isValid()) {
-          // Blocks without a location can't produce a warning, so don't mark
-          // reachable blocks from here as live.
-          reachable.set(b.getBlockID());
-          ++numReachable;
-          continue;
-        }
-        lines.push_back(ErrLoc(c, R1, R2));
-        // Avoid excessive errors by marking everything reachable from here
-        numReachable += ScanReachableFromBlock(b, reachable);
-      }
-    }
-  }
-
-  if (numReachable < cfg->getNumBlockIDs()) {
-    // And then give warnings for the tops of loops.
-    for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
-      CFGBlock &b = **I;
-      if (!reachable[b.getBlockID()])
-        // Avoid excessive errors by marking everything reachable from here
-        lines.push_back(ErrLoc(MarkLiveTop(&b, reachable,
-                                           Context.getSourceManager()),
-                               SourceRange(), SourceRange()));
-    }
-  }
-
-  llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp);
-  for (llvm::SmallVectorImpl<ErrLoc>::iterator I=lines.begin(), E=lines.end();
-       I != E; ++I)
-    if (I->Loc.isValid())
-      Diag(I->Loc, diag::warn_unreachable) << I->R1 << I->R2;
+  UnreachableCodeHandler UC(this);
+  reachable_code::FindUnreachableCode(AC, UC);
 }
 
 /// CheckFallThrough - Check that we don't fall off the end of a
@@ -2338,7 +2150,8 @@
   // confuse us, so we mark all live things first.
   std::queue<CFGBlock*> workq;
   llvm::BitVector live(cfg->getNumBlockIDs());
-  unsigned count = ScanReachableFromBlock(cfg->getEntry(), live);
+  unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(),
+                                                          live);
 
   bool AddEHEdges = AC.getAddEHEdges();
   if (!AddEHEdges && count != cfg->getNumBlockIDs())
@@ -2352,7 +2165,7 @@
           if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator()))
             // When not adding EH edges from calls, catch clauses
             // can otherwise seem dead.  Avoid noting them as dead.
-            count += ScanReachableFromBlock(b, live);
+            count += reachable_code::ScanReachableFromBlock(b, live);
           continue;
         }
       }