forked from OSchip/llvm-project
Implement nasty rewriting of nested blocks when inner
blocks use variables not used in any of the outer blocks. (Fixes radar 7682149). llvm-svn: 97073
This commit is contained in:
parent
d3aa3aa0ec
commit
8652be05b7
|
@ -120,6 +120,9 @@ namespace {
|
|||
|
||||
// Block expressions.
|
||||
llvm::SmallVector<BlockExpr *, 32> Blocks;
|
||||
llvm::SmallVector<int, 32> InnerDeclRefsCount;
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs;
|
||||
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
|
||||
llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
|
||||
|
||||
|
@ -385,6 +388,9 @@ namespace {
|
|||
void CollectBlockDeclRefInfo(BlockExpr *Exp);
|
||||
void GetBlockCallExprs(Stmt *S);
|
||||
void GetBlockDeclRefExprs(Stmt *S);
|
||||
void GetInnerBlockDeclRefExprs(Stmt *S,
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
|
||||
llvm::SmallPtrSet<ValueDecl *, 8> &InnerBlockValueDecls);
|
||||
|
||||
// We avoid calling Type::isBlockPointerType(), since it operates on the
|
||||
// canonical type. We only care if the top-level type is a closure pointer.
|
||||
|
@ -416,7 +422,8 @@ namespace {
|
|||
void RewriteCastExpr(CStyleCastExpr *CE);
|
||||
|
||||
FunctionDecl *SynthBlockInitFunctionDecl(const char *name);
|
||||
Stmt *SynthBlockInitExpr(BlockExpr *Exp);
|
||||
Stmt *SynthBlockInitExpr(BlockExpr *Exp,
|
||||
const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs);
|
||||
|
||||
void QuoteDoublequotes(std::string &From, std::string &To) {
|
||||
for (unsigned i = 0; i < From.length(); i++) {
|
||||
|
@ -4187,8 +4194,15 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
|
|||
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
|
||||
// Insert closures that were part of the function.
|
||||
for (unsigned i = 0; i < Blocks.size(); i++) {
|
||||
|
||||
// Need to copy-in the inner copied-in variables not actually used in this
|
||||
// block.
|
||||
for (int j = 0; j < InnerDeclRefsCount[i]; j++)
|
||||
BlockDeclRefs.push_back(InnerDeclRefs[j]);
|
||||
CollectBlockDeclRefInfo(Blocks[i]);
|
||||
llvm::SmallPtrSet<ValueDecl *, 8> InnerBlockValueDecls;
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
|
||||
GetInnerBlockDeclRefExprs(Blocks[i]->getBody(),
|
||||
InnerBlockDeclRefs, InnerBlockValueDecls);
|
||||
|
||||
std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
|
||||
std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
|
||||
|
@ -4218,6 +4232,8 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
|
|||
ImportedBlockDecls.clear();
|
||||
}
|
||||
Blocks.clear();
|
||||
InnerDeclRefsCount.clear();
|
||||
InnerDeclRefs.clear();
|
||||
RewrittenBlockExprs.clear();
|
||||
}
|
||||
|
||||
|
@ -4265,6 +4281,33 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
|
|||
return;
|
||||
}
|
||||
|
||||
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
|
||||
llvm::SmallPtrSet<ValueDecl *, 8> &InnerBlockValueDecls) {
|
||||
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
|
||||
CI != E; ++CI)
|
||||
if (*CI) {
|
||||
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
|
||||
GetInnerBlockDeclRefExprs(CBE->getBody(),
|
||||
InnerBlockDeclRefs,
|
||||
InnerBlockValueDecls);
|
||||
else
|
||||
GetInnerBlockDeclRefExprs(*CI,
|
||||
InnerBlockDeclRefs,
|
||||
InnerBlockValueDecls);
|
||||
|
||||
}
|
||||
// Handle specific things.
|
||||
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
|
||||
if (!isa<FunctionDecl>(CDRE->getDecl()) &&
|
||||
!CDRE->isByRef() &&
|
||||
!InnerBlockValueDecls.count(CDRE->getDecl())) {
|
||||
InnerBlockValueDecls.insert(CDRE->getDecl());
|
||||
InnerBlockDeclRefs.push_back(CDRE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void RewriteObjC::GetBlockCallExprs(Stmt *S) {
|
||||
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
|
||||
CI != E; ++CI)
|
||||
|
@ -4854,10 +4897,34 @@ FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) {
|
|||
false);
|
||||
}
|
||||
|
||||
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) {
|
||||
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
|
||||
const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) {
|
||||
Blocks.push_back(Exp);
|
||||
|
||||
CollectBlockDeclRefInfo(Exp);
|
||||
|
||||
// Add inner imported variables now used in current block.
|
||||
int countOfInnerDecls = 0;
|
||||
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
|
||||
BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i];
|
||||
ValueDecl *VD = Exp->getDecl();
|
||||
if (!BlockByCopyDeclsPtrSet.count(VD)) {
|
||||
// We need to save the copied-in variables in nested
|
||||
// blocks because it is needed at the end for some of the API generations.
|
||||
// See SynthesizeBlockLiterals routine.
|
||||
InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
|
||||
BlockDeclRefs.push_back(Exp);
|
||||
BlockByCopyDeclsPtrSet.insert(VD);
|
||||
BlockByCopyDecls.push_back(VD);
|
||||
if (Exp->getType()->isObjCObjectPointerType() ||
|
||||
Exp->getType()->isBlockPointerType()) {
|
||||
GetBlockCallExprs(Exp);
|
||||
ImportedBlockDecls.insert(VD);
|
||||
}
|
||||
}
|
||||
}
|
||||
InnerDeclRefsCount.push_back(countOfInnerDecls);
|
||||
|
||||
std::string FuncName;
|
||||
|
||||
if (CurFunctionDef)
|
||||
|
@ -5036,6 +5103,10 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
|
|||
}
|
||||
|
||||
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
|
||||
llvm::SmallPtrSet<ValueDecl *, 8> InnerBlockValueDecls;
|
||||
llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
|
||||
GetInnerBlockDeclRefExprs(BE->getBody(),
|
||||
InnerBlockDeclRefs, InnerBlockValueDecls);
|
||||
// Rewrite the block body in place.
|
||||
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
|
||||
|
||||
|
@ -5043,7 +5114,8 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
|
|||
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
|
||||
RewrittenBlockExprs[BE] = Str;
|
||||
|
||||
Stmt *blockTranscribed = SynthBlockInitExpr(BE);
|
||||
Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
|
||||
|
||||
//blockTranscribed->dump();
|
||||
ReplaceStmt(S, blockTranscribed);
|
||||
return blockTranscribed;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
|
||||
// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
|
||||
// radar 7682149
|
||||
|
||||
|
||||
void f(void (^block)(void));
|
||||
|
||||
@interface X {
|
||||
int y;
|
||||
}
|
||||
- (void)foo;
|
||||
@end
|
||||
|
||||
@implementation X
|
||||
- (void)foo {
|
||||
f(^{
|
||||
f(^{
|
||||
f(^{
|
||||
y=42;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
@end
|
||||
|
Loading…
Reference in New Issue