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.
|
/// variables defined outside the block) or false if this is not needed (e.g.
|
||||||
/// for values inside the block or for globals).
|
/// for values inside the block or for globals).
|
||||||
///
|
///
|
||||||
/// FIXME: This will create BlockDeclRefExprs for global variables,
|
/// This also keeps the 'hasBlockDeclRefExprs' in the BlockSemaInfo records
|
||||||
/// function references, etc which is suboptimal :) and breaks
|
/// up-to-date.
|
||||||
/// things like "integer constant expression" tests.
|
///
|
||||||
static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
|
static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock,
|
||||||
ValueDecl *VD) {
|
ValueDecl *VD) {
|
||||||
// If the value is defined inside the block, we couldn't snapshot it even if
|
// 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.
|
// snapshot it.
|
||||||
// FIXME: What about 'const' variables in C++?
|
// FIXME: What about 'const' variables in C++?
|
||||||
if (const VarDecl *Var = dyn_cast<VarDecl>(VD))
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -948,9 +968,6 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
||||||
// as they do not get snapshotted.
|
// as they do not get snapshotted.
|
||||||
//
|
//
|
||||||
if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
|
if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) {
|
||||||
// Blocks that have these can't be constant.
|
|
||||||
CurBlock->hasBlockDeclRefExprs = true;
|
|
||||||
|
|
||||||
QualType ExprTy = VD->getType().getNonReferenceType();
|
QualType ExprTy = VD->getType().getNonReferenceType();
|
||||||
// The BlocksAttr indicates the variable is bound by-reference.
|
// The BlocksAttr indicates the variable is bound by-reference.
|
||||||
if (VD->getAttr<BlocksAttr>())
|
if (VD->getAttr<BlocksAttr>())
|
||||||
|
@ -4763,11 +4780,6 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
||||||
if (BSI->ReturnType)
|
if (BSI->ReturnType)
|
||||||
RetTy = QualType(BSI->ReturnType, 0);
|
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;
|
llvm::SmallVector<QualType, 8> ArgTypes;
|
||||||
for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
|
for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i)
|
||||||
ArgTypes.push_back(BSI->Params[i]->getType());
|
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}}
|
^{ 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 (^test12f)(void);
|
||||||
void test12() {
|
void test12() {
|
||||||
|
|
Loading…
Reference in New Issue