Make sure that we always pop a function's scope *before* we call
ActOnFinishFunctionBody/ActOnBlockStmtExpr. This way, we ensure that
we diagnose undefined labels before the jump-scope checker gets run,
since the jump-scope checker requires (as its invariant) that all of
the GotoStmts be wired up correctly.

Fixes PR9495.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127738 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 3994738..baa038e 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -261,7 +261,7 @@
   Actions.ActOnStartOfFunctionDef(getCurScope(), LM.D);
 
   if (Tok.is(tok::kw_try)) {
-    ParseFunctionTryBlock(LM.D);
+    ParseFunctionTryBlock(LM.D, FnScope);
     assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                          Tok.getLocation()) &&
            "ParseFunctionTryBlock went over the cached tokens!");
@@ -276,13 +276,14 @@
 
     // Error recovery.
     if (!Tok.is(tok::l_brace)) {
+      FnScope.Exit();
       Actions.ActOnFinishFunctionBody(LM.D, 0);
       return;
     }
   } else
     Actions.ActOnDefaultCtorInitializers(LM.D);
 
-  ParseFunctionStatementBody(LM.D);
+  ParseFunctionStatementBody(LM.D, FnScope);
 
   if (Tok.getLocation() != origLoc) {
     // Due to parsing error, we either went over the cached tokens or
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 7cb9551..ecc02ac 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1954,6 +1954,7 @@
   }
 
   StmtResult Stmt(ParseCompoundStatementBody());
+  BlockScope.Exit();
   if (!Stmt.isInvalid())
     Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
   else
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 4b702e0..d4391ee 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -1724,9 +1724,12 @@
   // specified Declarator for the method.
   Actions.ActOnStartOfObjCMethodDef(getCurScope(), MDecl);
 
-  if (PP.isCodeCompletionEnabled())
-    if (trySkippingFunctionBodyForCodeCompletion())
+  if (PP.isCodeCompletionEnabled()) {
+    if (trySkippingFunctionBodyForCodeCompletion()) {
+      BodyScope.Exit();
       return Actions.ActOnFinishFunctionBody(MDecl, 0);
+    }
+  }
 
   StmtResult FnBody(ParseCompoundStatementBody());
 
@@ -1735,12 +1738,11 @@
     FnBody = Actions.ActOnCompoundStmt(BraceLoc, BraceLoc,
                                        MultiStmtArg(Actions), false);
 
-  // TODO: Pass argument information.
-  Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
-
   // Leave the function body scope.
   BodyScope.Exit();
-
+  
+  // TODO: Pass argument information.
+  Actions.ActOnFinishFunctionBody(MDecl, FnBody.take());
   return MDecl;
 }
 
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d7e9070..cd970ca 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -1531,14 +1531,17 @@
   return true;
 }
 
-Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
+Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
 
-  if (PP.isCodeCompletionEnabled())
-    if (trySkippingFunctionBodyForCodeCompletion())
+  if (PP.isCodeCompletionEnabled()) {
+    if (trySkippingFunctionBodyForCodeCompletion()) {
+      BodyScope.Exit();
       return Actions.ActOnFinishFunctionBody(Decl, 0);
-
+    }
+  }
+  
   PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc,
                                       "parsing function body");
 
@@ -1552,6 +1555,7 @@
     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
                                        MultiStmtArg(Actions), false);
 
+  BodyScope.Exit();
   return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
 }
 
@@ -1560,7 +1564,7 @@
 ///       function-try-block:
 ///         'try' ctor-initializer[opt] compound-statement handler-seq
 ///
-Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
+Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
   assert(Tok.is(tok::kw_try) && "Expected 'try'");
   SourceLocation TryLoc = ConsumeToken();
 
@@ -1571,9 +1575,12 @@
   if (Tok.is(tok::colon))
     ParseConstructorInitializer(Decl);
 
-  if (PP.isCodeCompletionEnabled())
-    if (trySkippingFunctionBodyForCodeCompletion())
+  if (PP.isCodeCompletionEnabled()) {
+    if (trySkippingFunctionBodyForCodeCompletion()) {
+      BodyScope.Exit();
       return Actions.ActOnFinishFunctionBody(Decl, 0);
+    }
+  }
 
   SourceLocation LBraceLoc = Tok.getLocation();
   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
@@ -1583,6 +1590,7 @@
     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
                                        MultiStmtArg(Actions), false);
 
+  BodyScope.Exit();
   return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
 }
 
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index d9b37d2..3946fc7 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -801,7 +801,7 @@
   D.getMutableDeclSpec().abort();
 
   if (Tok.is(tok::kw_try))
-    return ParseFunctionTryBlock(Res);
+    return ParseFunctionTryBlock(Res, BodyScope);
 
   // If we have a colon, then we're probably parsing a C++
   // ctor-initializer.
@@ -810,13 +810,14 @@
 
     // Recover from error.
     if (!Tok.is(tok::l_brace)) {
+      BodyScope.Exit();
       Actions.ActOnFinishFunctionBody(Res, 0);
       return Res;
     }
   } else
     Actions.ActOnDefaultCtorInitializers(Res);
 
-  return ParseFunctionStatementBody(Res);
+  return ParseFunctionStatementBody(Res, BodyScope);
 }
 
 /// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides