diff options
-rw-r--r-- | lib/Sema/Sema.h | 5 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 5 | ||||
-rw-r--r-- | test/Sema/block-labels.c | 17 |
4 files changed, 27 insertions, 3 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index b403a8ba1d..d49efdddb1 100644 --- a/lib/Sema/Sema.h +++ b/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<IdentifierInfo*, LabelStmt*> LabelMap; + /// PrevBlockInfo - If this is nested inside another block, this points /// to the outer block. BlockSemaInfo *PrevBlockInfo; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9f915fc7f9..8324d8d472 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index f8e225540b..96e59f0f82 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -170,7 +170,7 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation ColonLoc, StmtArg subStmt) { Stmt *SubStmt = static_cast<Stmt*>(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/test/Sema/block-labels.c b/test/Sema/block-labels.c index e69de29bb2..15e6f61ced 100644 --- a/test/Sema/block-labels.c +++ b/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'}} +} |