Implement jump checking for initialized c++ variables, implementing
a fixme and PR6451.

Only perform jump checking if the containing function has no errors,
and add the infrastructure needed to do this.

On the testcase in the PR, we produce:

t.cc:6:3: error: illegal goto into protected scope
  goto later;
  ^
t.cc:7:5: note: jump bypasses variable initialization
  X x;
    ^



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97497 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp
index 2b37e9d..7cf207f 100644
--- a/lib/Sema/JumpDiagnostics.cpp
+++ b/lib/Sema/JumpDiagnostics.cpp
@@ -77,7 +77,7 @@
 
 /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a
 /// diagnostic that should be emitted if control goes over it. If not, return 0.
-static unsigned GetDiagForGotoScopeDecl(const Decl *D) {
+static unsigned GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) {
   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
     if (VD->getType()->isVariablyModifiedType())
       return diag::note_protected_by_vla;
@@ -85,6 +85,9 @@
       return diag::note_protected_by_cleanup;
     if (VD->hasAttr<BlocksAttr>())
       return diag::note_protected_by___block;
+    if (isCPlusPlus && VD->hasLocalStorage() && VD->hasInit())
+      return diag::note_protected_by_variable_init;
+    
   } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
     if (TD->getUnderlyingType()->isVariablyModifiedType())
       return diag::note_protected_by_vla_typedef;
@@ -116,18 +119,17 @@
     Stmt *SubStmt = *CI;
     if (SubStmt == 0) continue;
 
-    // FIXME: diagnose jumps past initialization: required in C++, warning in C.
-    //   goto L; int X = 4;   L: ;
+    bool isCPlusPlus = this->S.getLangOptions().CPlusPlus;
 
     // If this is a declstmt with a VLA definition, it defines a scope from here
     // to the end of the containing context.
     if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) {
-      // The decl statement creates a scope if any of the decls in it are VLAs or
-      // have the cleanup attribute.
+      // The decl statement creates a scope if any of the decls in it are VLAs
+      // or have the cleanup attribute.
       for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
            I != E; ++I) {
         // If this decl causes a new scope, push and switch to it.
-        if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) {
+        if (unsigned Diag = GetDiagForGotoScopeDecl(*I, isCPlusPlus)) {
           Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation()));
           ParentScope = Scopes.size()-1;
         }