]> granicus.if.org Git - clang/commitdiff
Make sure that we always pop a function's scope *before* we call
authorDouglas Gregor <dgregor@apple.com>
Wed, 16 Mar 2011 17:05:57 +0000 (17:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 16 Mar 2011 17:05:57 +0000 (17:05 +0000)
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

include/clang/Parse/Parser.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
test/SemaCXX/goto.cpp
test/SemaObjCXX/goto.mm [new file with mode: 0644]

index d39fa47cf03f71f2c32a7cbb20a80b3e9f34fe30..bd39cdb452e92249908c6348fdf1d5a7207ba220 100644 (file)
@@ -1286,8 +1286,8 @@ private:
                                 SourceLocation *DeclEnd = 0);
   Decl *ParseDeclarationAfterDeclarator(Declarator &D,
                const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
-  Decl *ParseFunctionStatementBody(Decl *Decl);
-  Decl *ParseFunctionTryBlock(Decl *Decl);
+  Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope);
+  Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope);
 
   /// \brief When in code-completion, skip parsing of the function/method body
   /// unless the body contains the code-completion point.
index 399473840a9471dece99ee511e2c3f3cdf28f866..baa038ea98da66dd19fb00690dc0574001bb535e 100644 (file)
@@ -261,7 +261,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
   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 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
 
     // 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
index 7cb955134a4f9cc61c97c173a3555c418f38bb75..ecc02ac42e3fc35d6d10c3cd764a29750ac44867 100644 (file)
@@ -1954,6 +1954,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
   }
 
   StmtResult Stmt(ParseCompoundStatementBody());
+  BlockScope.Exit();
   if (!Stmt.isInvalid())
     Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
   else
index 4b702e07618e00dbfeded2d576dd80af58502ec1..d4391ee3e93fad02c1de120de41cbc816d3254ae 100644 (file)
@@ -1724,9 +1724,12 @@ Decl *Parser::ParseObjCMethodDefinition() {
   // 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 @@ Decl *Parser::ParseObjCMethodDefinition() {
     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;
 }
 
index d7e9070520d682f91416b982189132da6a505211..cd970ca60f283ef9bcf172bef1cc1c92f8ba52a7 100644 (file)
@@ -1531,14 +1531,17 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
   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 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
                                        MultiStmtArg(Actions), false);
 
+  BodyScope.Exit();
   return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
 }
 
@@ -1560,7 +1564,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl) {
 ///       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 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
   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 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl) {
     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
                                        MultiStmtArg(Actions), false);
 
+  BodyScope.Exit();
   return Actions.ActOnFinishFunctionBody(Decl, FnBody.take());
 }
 
index d9b37d2c56cf4641ba081f19c2db6cbe1d563c0f..3946fc72080750cd6ff70bb8e2fd92da422635d1 100644 (file)
@@ -801,7 +801,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
   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 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
 
     // 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
index e8b7822c32322668727716dfbf9629260bab2ac1..8b8379613d81098cd164c58ce906ba3a2449faf5 100644 (file)
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s
+
 // PR9463
 double *end;
 void f() {
@@ -44,3 +45,25 @@ void rdar9135994()
 X:  
     goto X;
 }
+
+namespace PR9495 {
+  struct NonPOD { NonPOD(); ~NonPOD(); };  
+  
+  void f(bool b) {
+    NonPOD np;
+    if (b) {
+      goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+    }
+  }
+
+  void g() {
+    (void)^(bool b){
+      NonPOD np;
+      if (b) {
+        goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+      }
+    };
+  }
+}
+
+
diff --git a/test/SemaObjCXX/goto.mm b/test/SemaObjCXX/goto.mm
new file mode 100644 (file)
index 0000000..67df1f4
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR9495
+struct NonPOD { NonPOD(); ~NonPOD(); };
+
+@interface A
+@end
+
+@implementation A
+- (void)method:(bool)b {
+  NonPOD np;
+  if (b) {
+    goto undeclared; // expected-error{{use of undeclared label 'undeclared'}}
+  }
+}
+@end