aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/Sema.h5
-rw-r--r--lib/Sema/SemaExpr.cpp3
-rw-r--r--lib/Sema/SemaStmt.cpp5
-rw-r--r--test/Sema/block-labels.c17
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'}}
+}