[cfe-commits] r97073 - in /cfe/trunk: lib/Frontend/RewriteObjC.cpp test/Rewriter/rewrite-nested-blocks.mm
Fariborz Jahanian
fjahanian at apple.com
Wed Feb 24 14:48:18 PST 2010
Author: fjahanian
Date: Wed Feb 24 16:48:18 2010
New Revision: 97073
URL: http://llvm.org/viewvc/llvm-project?rev=97073&view=rev
Log:
Implement nasty rewriting of nested blocks when inner
blocks use variables not used in any of the outer blocks.
(Fixes radar 7682149).
Added:
cfe/trunk/test/Rewriter/rewrite-nested-blocks.mm
Modified:
cfe/trunk/lib/Frontend/RewriteObjC.cpp
Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=97073&r1=97072&r2=97073&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Wed Feb 24 16:48:18 2010
@@ -120,6 +120,9 @@
// 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 @@
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 @@
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 @@
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 @@
ImportedBlockDecls.clear();
}
Blocks.clear();
+ InnerDeclRefsCount.clear();
+ InnerDeclRefs.clear();
RewrittenBlockExprs.clear();
}
@@ -4265,6 +4281,33 @@
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 @@
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 @@
}
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 @@
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;
Added: cfe/trunk/test/Rewriter/rewrite-nested-blocks.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-nested-blocks.mm?rev=97073&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/rewrite-nested-blocks.mm (added)
+++ cfe/trunk/test/Rewriter/rewrite-nested-blocks.mm Wed Feb 24 16:48:18 2010
@@ -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));
+
+ at interface X {
+ int y;
+}
+- (void)foo;
+ at end
+
+ at implementation X
+- (void)foo {
+ f(^{
+ f(^{
+ f(^{
+ y=42;
+ });
+ });
+});
+
+}
+ at end
+
More information about the cfe-commits
mailing list