]> granicus.if.org Git - clang/commitdiff
Reimplement fix for <rdar://problem/6451399> problems with labels and blocks.
authorSteve Naroff <snaroff@apple.com>
Fri, 13 Mar 2009 16:03:38 +0000 (16:03 +0000)
committerSteve Naroff <snaroff@apple.com>
Fri, 13 Mar 2009 16:03:38 +0000 (16:03 +0000)
This solution is much simpler (and doesn't add any per-scope overhead, which concerned Chris).

The only downside is the LabelMap is now declared in two places (Sema and BlockSemaInfo). My original fix tried to unify the LabelMap in "Scope" (which would support nested functions in general). In any event, this fixes the bug given the current language definition. If/when we decide to support GCC style nested functions, this will need to be tweaked.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66896 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaStmt.cpp
test/Sema/block-labels.c

index b403a8ba1d173c67e4de914cc2159fce8cceedd5..d49efdddb193d20157122af8b6424dee3924dee7 100644 (file)
@@ -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;
index 9f915fc7f97811a24e256571d5e50aa24e3d24d3..8324d8d4727d8b8fedf944d97208e8bc38645d39 100644 (file)
@@ -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.
index f8e225540bc949a8902d00dbcfde61e6ce1511ac..96e59f0f82b26c8130efcdfde770e22e60be08d2 100644 (file)
@@ -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)
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..15e6f61cede391d9af601dc09338e287847f2a8b 100644 (file)
@@ -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'}}
+}