[cfe-commits] r69738 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/Sema/block-misc.c

Chris Lattner sabre at nondot.org
Tue Apr 21 15:26:47 PDT 2009


Author: lattner
Date: Tue Apr 21 17:26:47 2009
New Revision: 69738

URL: http://llvm.org/viewvc/llvm-project?rev=69738&view=rev
Log:
fix marking of nested blocks with the "hasBlockDeclRefExprs" to
mark exactly the blocks which have references that are "live through".
This fixes a rejects valid: 
rdar://6808730 - [sema] [blocks] block rejected at global scope

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Sema/block-misc.c

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=69738&r1=69737&r2=69738&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Apr 21 17:26:47 2009
@@ -402,9 +402,9 @@
 /// variables defined outside the block) or false if this is not needed (e.g.
 /// for values inside the block or for globals).
 ///
-/// FIXME: This will create BlockDeclRefExprs for global variables,
-/// function references, etc which is suboptimal :) and breaks
-/// things like "integer constant expression" tests.
+/// This also keeps the 'hasBlockDeclRefExprs' in the BlockSemaInfo records
+/// up-to-date.
+///
 static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
                                               ValueDecl *VD) {
   // If the value is defined inside the block, we couldn't snapshot it even if
@@ -420,7 +420,27 @@
   // snapshot it.
   // FIXME: What about 'const' variables in C++?
   if (const VarDecl *Var = dyn_cast<VarDecl>(VD))
-    return Var->hasLocalStorage();
+    if (!Var->hasLocalStorage())
+      return false;
+  
+  // Blocks that have these can't be constant.
+  CurBlock->hasBlockDeclRefExprs = true;
+
+  // If we have nested blocks, the decl may be declared in an outer block (in
+  // which case that outer block doesn't get "hasBlockDeclRefExprs") or it may
+  // be defined outside all of the current blocks (in which case the blocks do
+  // all get the bit).  Walk the nesting chain.
+  for (BlockSemaInfo *NextBlock = CurBlock->PrevBlockInfo; NextBlock;
+       NextBlock = NextBlock->PrevBlockInfo) {
+    // If we found the defining block for the variable, don't mark the block as
+    // having a reference outside it.
+    if (NextBlock->TheDecl == VD->getDeclContext())
+      break;
+    
+    // Otherwise, the DeclRef from the inner block causes the outer one to need
+    // a snapshot as well.
+    NextBlock->hasBlockDeclRefExprs = true;
+  }
   
   return true;
 }  
@@ -948,9 +968,6 @@
   // as they do not get snapshotted.
   //
   if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
-    // Blocks that have these can't be constant.
-    CurBlock->hasBlockDeclRefExprs = true;
-
     QualType ExprTy = VD->getType().getNonReferenceType();
     // The BlocksAttr indicates the variable is bound by-reference.
     if (VD->getAttr<BlocksAttr>())
@@ -4763,11 +4780,6 @@
   if (BSI->ReturnType)
     RetTy = QualType(BSI->ReturnType, 0);
 
-  // A reference in a nested block, winds up being a reference in the outer
-  // block.
-  if (CurBlock)
-    CurBlock->hasBlockDeclRefExprs |= BSI->hasBlockDeclRefExprs;
-
   llvm::SmallVector<QualType, 8> ArgTypes;
   for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
     ArgTypes.push_back(BSI->Params[i]->getType());

Modified: cfe/trunk/test/Sema/block-misc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/block-misc.c?rev=69738&r1=69737&r2=69738&view=diff

==============================================================================
--- cfe/trunk/test/Sema/block-misc.c (original)
+++ cfe/trunk/test/Sema/block-misc.c Tue Apr 21 17:26:47 2009
@@ -112,6 +112,25 @@
     ^{ break; }();     // expected-error {{'break' statement not in loop or switch statement}}
 }
 
+// rdar://6808730
+void *test13 = ^{
+  int X = 32;
+
+  void *P = ^{
+    return X+4;  // References outer block's "X", so outer block is constant.
+  };
+};
+
+void test14() {
+  int X = 32;
+  static void *P = ^{  // expected-error {{initializer element is not a compile-time constant}}
+
+    void *Q = ^{
+      // References test14's "X": outer block is non constant.
+      return X+4;
+    };
+  };
+}
 
 void (^test12f)(void);
 void test12() {





More information about the cfe-commits mailing list