Fix bug in BugReporter where we didn't handle emitting diagnostics for
empty CFGBlocks that only contained a terminator.

Added improved diagnostics for break and continue statements and default branches in switch statements.

This fixes <rdar://problem/5889244>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50286 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp
index 9c55333..d00d329 100644
--- a/lib/Analysis/BugReporter.cpp
+++ b/lib/Analysis/BugReporter.cpp
@@ -48,8 +48,12 @@
 }
 
 static inline Stmt* GetStmt(const CFGBlock* B) {
-  assert (!B->empty());
-  return (*B)[0];
+  if (B->empty()) {
+    assert (B->getTerminator() && "Empty block should have a terminator.");
+    return const_cast<Stmt*>(B->getTerminator());
+  }
+  else
+    return (*B)[0];
 }
 
 Stmt* BugReport::getStmt() const {
@@ -60,7 +64,18 @@
 GetNextNode(ExplodedNode<ValueState>* N) {
   return N->pred_empty() ? NULL : *(N->pred_begin());
 }
+
+static void ExecutionContinues(std::ostream& os, SourceManager& SMgr,
+                               ExplodedNode<ValueState>* N) {
   
+  Stmt* S = GetStmt(N->getLocation());
+  
+  if (!S)
+    return;
+
+  os << "Execution continue on line "
+     << SMgr.getLogicalLineNumber(S->getLocStart()) << '.';
+}
   
 static Stmt* GetLastStmt(ExplodedNode<ValueState>* N) {
   assert (isa<BlockEntrance>(N->getLocation()));
@@ -311,9 +326,7 @@
                 }
                 
                 os << V.toString();
-              }
-              
-              
+              }              
               
               os << ":'  at line " 
                  << SMgr.getLogicalLineNumber(S->getLocStart()) << ".\n";
@@ -323,16 +336,21 @@
             }
           }
           else {
-            
-            // FIXME: Get line number.
-            
-            os << "'Default' branch taken. "
-                  "Execution continues after switch statement.";
+            os << "'Default' branch taken.";
+            ExecutionContinues(os, SMgr, LastNode);
           }
           
           PD.push_front(new PathDiagnosticPiece(L, os.str()));
           break;
         }
+          
+        case Stmt::BreakStmtClass:
+        case Stmt::ContinueStmtClass: {
+          std::ostringstream os;
+          ExecutionContinues(os, SMgr, LastNode);
+          PD.push_front(new PathDiagnosticPiece(L, os.str()));
+          break;
+        }
 
         case Stmt::ConditionalOperatorClass: {