From 314825bc8ac6ef3245ca4c1b3aee89f0da2632f6 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 19 Jan 2010 23:08:01 +0000 Subject: [PATCH] Implement goto inside of blocks. llvm-svn: 93945 --- .../clang/Basic/DiagnosticSemaKinds.td | 2 -- clang/lib/Sema/SemaExpr.cpp | 20 +++++++++++++++++++ clang/lib/Sema/SemaStmt.cpp | 4 ---- clang/test/Sema/block-literal.c | 3 ++- clang/test/Sema/block-misc.c | 3 +-- clang/test/Sema/scope-check.c | 11 +++++----- 6 files changed, 28 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7e59f88fcef5..78173be8b5ae 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2458,8 +2458,6 @@ def warn_stringcompare : Warning< def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" " or pick a deployment target that supports them">; def err_expected_block_lbrace : Error<"expected '{' in block literal">; -def err_goto_in_block : Error< - "goto not allowed in block literal">; def err_return_in_block_expression : Error< "return not allowed in block expression literal">; def err_block_returns_array : Error< diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8c740dd1dbf6..19d38bf9d122 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6884,6 +6884,26 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, CurFunctionNeedsScopeChecking = BSI->SavedFunctionNeedsScopeChecking; BSI->TheDecl->setBody(body.takeAs()); + + bool Good = true; + // Check goto/label use. + for (llvm::DenseMap::iterator + I = BSI->LabelMap.begin(), E = BSI->LabelMap.end(); I != E; ++I) { + LabelStmt *L = I->second; + + // Verify that we have no forward references left. If so, there was a goto + // or address of a label taken, but no definition of it. + if (L->getSubStmt() != 0) + continue; + + // Emit error. + Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName(); + Good = false; + } + BSI->LabelMap.clear(); + if (!Good) + return ExprError(); + AnalysisContext AC(BSI->TheDecl); CheckFallThroughForBlock(BlockTy, BSI->TheDecl->getBody(), AC); CheckUnreachable(AC); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7855a7f60935..f0bbdfe7624e 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -879,10 +879,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Action::OwningStmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, IdentifierInfo *LabelII) { - // If we are in a block, reject all gotos for now. - if (CurBlock) - return StmtError(Diag(GotoLoc, diag::err_goto_in_block)); - // Look up the record for this label identifier. LabelStmt *&LabelDecl = getLabelMap()[LabelII]; diff --git a/clang/test/Sema/block-literal.c b/clang/test/Sema/block-literal.c index e9c2341a99c7..c303b8417d94 100644 --- a/clang/test/Sema/block-literal.c +++ b/clang/test/Sema/block-literal.c @@ -33,7 +33,8 @@ void test2() { break; // expected-error {{'break' statement not in loop or switch statement}} continue; // expected-error {{'continue' statement not in loop statement}} while(1) break; // ok - goto foo; // expected-error {{goto not allowed}} + goto foo; // expected-error {{use of undeclared label 'foo'}} + a: goto a; // ok }); break; } diff --git a/clang/test/Sema/block-misc.c b/clang/test/Sema/block-misc.c index 52cebfe8922f..1109be6311b0 100644 --- a/clang/test/Sema/block-misc.c +++ b/clang/test/Sema/block-misc.c @@ -87,8 +87,7 @@ int test7(void (^p)()) { void test8() { somelabel: - // FIXME: This should say "jump out of block not legal" when gotos are allowed. - ^{ goto somelabel; }(); // expected-error {{goto not allowed in block literal}} + ^{ goto somelabel; }(); // expected-error {{use of undeclared label 'somelabel'}} } void test9() { diff --git a/clang/test/Sema/scope-check.c b/clang/test/Sema/scope-check.c index 4d3f6cbcf2b8..74bc7c46f8f5 100644 --- a/clang/test/Sema/scope-check.c +++ b/clang/test/Sema/scope-check.c @@ -181,15 +181,14 @@ void test11(int n) { // TODO: When and if gotos are allowed in blocks, this should work. void test12(int n) { void *P = ^{ - goto L1; // expected-error {{goto not allowed in block literal}} + goto L1; L1: - goto L2; // expected-error {{goto not allowed in block literal}} + goto L2; L2: - goto L3; // expected-error {{goto not allowed in block literal}} - // todo-error {{illegal goto into protected scope}} - int Arr[n]; // todo-note {{jump bypasses initialization of variable length array}} + goto L3; // expected-error {{illegal goto into protected scope}} + int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}} L3: - goto L4; // expected-error {{goto not allowed in block literal}} + goto L4; L4: return; }; }