aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend/RewriteObjC.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-02-24 22:48:18 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-02-24 22:48:18 +0000
commit5e49b2f3e0bbc583076fe8af00dff06bcba06daf (patch)
tree71c05af563b22e056af3b42fcaaed0eab634a575 /lib/Frontend/RewriteObjC.cpp
parentb57fb49b6569db9716877de6857e4de572edfb75 (diff)
Implement nasty rewriting of nested blocks when inner
blocks use variables not used in any of the outer blocks. (Fixes radar 7682149). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97073 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/RewriteObjC.cpp')
-rw-r--r--lib/Frontend/RewriteObjC.cpp80
1 files changed, 76 insertions, 4 deletions
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 521abf489b..350d6b2009 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -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;