[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