diff options
| author | Chris Lattner <sabre@nondot.org> | 2009-04-21 22:26:47 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2009-04-21 22:26:47 +0000 |
| commit | 497d7b0c8acd6d55555b11e3d49121da71a5cf1d (patch) | |
| tree | b263c9c9ca29afa8c027160842cd235957a089f4 /clang/lib/Sema/SemaExpr.cpp | |
| parent | a868bbd392594290cff15a3d25e8a69fe43a3857 (diff) | |
| download | bcm5719-llvm-497d7b0c8acd6d55555b11e3d49121da71a5cf1d.tar.gz bcm5719-llvm-497d7b0c8acd6d55555b11e3d49121da71a5cf1d.zip | |
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
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 33fefe53bc0..57902cc02b5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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()); |

