forked from OSchip/llvm-project
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 llvm-svn: 69738
This commit is contained in:
parent
a868bbd392
commit
497d7b0c8a
|
@ -402,9 +402,9 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) {
|
|||
/// 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 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
|
|||
// 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 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
// 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 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
|||
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());
|
||||
|
|
|
@ -112,6 +112,25 @@ void test11(int i) {
|
|||
^{ 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() {
|
||||
|
|
Loading…
Reference in New Issue