diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index b403a8ba1d173c67e4de914cc2159fce8cceedd5..d49efdddb193d20157122af8b6424dee3924dee7 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2310,6 +2310,11 @@ struct BlockSemaInfo { /// return types, if any, in the block body. Type *ReturnType; + /// LabelMap - This is a mapping from label identifiers to the LabelStmt for + /// it (which acts like the label decl in some ways). Forward referenced + /// labels have a LabelStmt created for them with a null location & SubStmt. + llvm::DenseMap LabelMap; + /// PrevBlockInfo - If this is nested inside another block, this points /// to the outer block. BlockSemaInfo *PrevBlockInfo; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 9f915fc7f97811a24e256571d5e50aa24e3d24d3..8324d8d4727d8b8fedf944d97208e8bc38645d39 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4336,7 +4336,8 @@ Sema::ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, IdentifierInfo *LabelII) { // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[LabelII]; + LabelStmt *&LabelDecl = CurBlock ? CurBlock->LabelMap[LabelII] : + LabelMap[LabelII]; // If we haven't seen this label yet, create a forward reference. It // will be validated and/or cleaned up in ActOnFinishFunctionBody. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index f8e225540bc949a8902d00dbcfde61e6ce1511ac..96e59f0f82b26c8130efcdfde770e22e60be08d2 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -170,7 +170,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, StmtArg subStmt) { Stmt *SubStmt = static_cast(subStmt.release()); // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[II]; + LabelStmt *&LabelDecl = CurBlock ? CurBlock->LabelMap[II] : LabelMap[II]; // If not forward referenced or defined already, just create a new LabelStmt. if (LabelDecl == 0) @@ -676,7 +676,8 @@ Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, return StmtError(Diag(GotoLoc, diag::err_goto_in_block)); // Look up the record for this label identifier. - LabelStmt *&LabelDecl = LabelMap[LabelII]; + LabelStmt *&LabelDecl = CurBlock ? CurBlock->LabelMap[LabelII] : + LabelMap[LabelII]; // If we haven't seen this label yet, create a forward reference. if (LabelDecl == 0) diff --git a/clang/test/Sema/block-labels.c b/clang/test/Sema/block-labels.c index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..15e6f61cede391d9af601dc09338e287847f2a8b 100644 --- a/clang/test/Sema/block-labels.c +++ b/clang/test/Sema/block-labels.c @@ -0,0 +1,17 @@ +// RUN: clang %s -verify -fblocks -fsyntax-only + +int a() { + A:if (1) xx(); + return ^{A:return 1;}(); +} +int b() { + A: return ^{int a; A:return 1;}(); +} + +int d() { + A: return ^{int a; A: a = ^{int a; A:return 1;}() + ^{int b; A:return 2;}(); return a; }(); +} + +int c() { + goto A; return ^{ A:return 1;}(); // expected-error {{use of undeclared label 'A'}} +}