aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-03-16 17:05:57 +0000
committerDouglas Gregor <dgregor@apple.com>2011-03-16 17:05:57 +0000
commitc9977d09a2de7f7d2245973413d4caf86c736640 (patch)
tree96f62846c27d60cf053f957dcfc32c0bbd575e71
parent250e7a74d5a23db5bd7202ecb0bb4a8fef6016b4 (diff)
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
-rw-r--r--include/clang/Parse/Parser.h4
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp5
-rw-r--r--lib/Parse/ParseExpr.cpp1
-rw-r--r--lib/Parse/ParseObjc.cpp14
-rw-r--r--lib/Parse/ParseStmt.cpp22
-rw-r--r--lib/Parse/Parser.cpp5
-rw-r--r--test/SemaCXX/goto.cpp25
-rw-r--r--test/SemaObjCXX/goto.mm16
8 files changed, 72 insertions, 20 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d39fa47cf0..bd39cdb452 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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.
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 399473840a..baa038ea98 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -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
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 7cb955134a..ecc02ac42e 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1954,6 +1954,7 @@ ExprResult Parser::ParseBlockLiteralExpression() {
}
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 4b702e0761..d4391ee3e9 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -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;
}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index d7e9070520..cd970ca60f 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -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());
}
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index d9b37d2c56..3946fc7208 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -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
diff --git a/test/SemaCXX/goto.cpp b/test/SemaCXX/goto.cpp
index e8b7822c32..8b8379613d 100644
--- a/test/SemaCXX/goto.cpp
+++ b/test/SemaCXX/goto.cpp
@@ -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
index 0000000000..67df1f4c32
--- /dev/null
+++ b/test/SemaObjCXX/goto.mm
@@ -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