aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-03-01 23:36:21 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-03-01 23:36:21 +0000
commit72952fc11f80c975492a2a1e0f6e3601c5252e0a (patch)
treed41cd73439aa0ccb79ba3db7dc2333b07cf91255
parentd6d4fcf7fd2cdb8c75e6feb5ab1a7132784e96e1 (diff)
More rewriter of nested blocks fun stuff.
Radar 7696893. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97520 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Frontend/RewriteObjC.cpp47
-rw-r--r--test/Rewriter/rewrite-nested-blocks-1.mm47
2 files changed, 75 insertions, 19 deletions
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 635280bf43..98dee264e9 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -26,6 +26,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseSet.h"
+
using namespace clang;
using llvm::utostr;
@@ -390,7 +391,7 @@ namespace {
void GetBlockDeclRefExprs(Stmt *S);
void GetInnerBlockDeclRefExprs(Stmt *S,
llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<ValueDecl *, 8> &InnerBlockValueDecls);
+ llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
// We avoid calling Type::isBlockPointerType(), since it operates on the
// canonical type. We only care if the top-level type is a closure pointer.
@@ -4264,16 +4265,23 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
// Insert closures that were part of the function.
- for (unsigned i = 0; i < Blocks.size(); i++) {
+ for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
+ CollectBlockDeclRefInfo(Blocks[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);
+ for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
+ BlockDeclRefExpr *Exp = InnerDeclRefs[count++];
+ ValueDecl *VD = Exp->getDecl();
+ BlockDeclRefs.push_back(Exp);
+ if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) {
+ BlockByCopyDeclsPtrSet.insert(VD);
+ BlockByCopyDecls.push_back(VD);
+ }
+ if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) {
+ BlockByRefDeclsPtrSet.insert(VD);
+ BlockByRefDecls.push_back(VD);
+ }
+ }
std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i);
std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i);
@@ -4353,28 +4361,28 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<ValueDecl *, 8> &InnerBlockValueDecls) {
+ llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
CI != E; ++CI)
if (*CI) {
- if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI))
+ if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
+ InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
GetInnerBlockDeclRefExprs(CBE->getBody(),
InnerBlockDeclRefs,
- InnerBlockValueDecls);
+ InnerContexts);
+ }
else
GetInnerBlockDeclRefExprs(*CI,
InnerBlockDeclRefs,
- InnerBlockValueDecls);
+ InnerContexts);
}
// Handle specific things.
if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
if (!isa<FunctionDecl>(CDRE->getDecl()) &&
- !isa<ParmVarDecl>(CDRE->getDecl()) &&
- !InnerBlockValueDecls.count(CDRE->getDecl())) {
- InnerBlockValueDecls.insert(CDRE->getDecl());
+ !InnerContexts.count(CDRE->getDecl()->getDeclContext()))
InnerBlockDeclRefs.push_back(CDRE);
- }
+
return;
}
@@ -5166,10 +5174,11 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
- llvm::SmallPtrSet<ValueDecl *, 8> InnerBlockValueDecls;
llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
+ llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
+ InnerContexts.insert(BE->getBlockDecl());
GetInnerBlockDeclRefExprs(BE->getBody(),
- InnerBlockDeclRefs, InnerBlockValueDecls);
+ InnerBlockDeclRefs, InnerContexts);
// Rewrite the block body in place.
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
diff --git a/test/Rewriter/rewrite-nested-blocks-1.mm b/test/Rewriter/rewrite-nested-blocks-1.mm
new file mode 100644
index 0000000000..582f5f4c0d
--- /dev/null
+++ b/test/Rewriter/rewrite-nested-blocks-1.mm
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// radar 7696893
+
+void *sel_registerName(const char *);
+
+void f(void (^block)(void));
+void f2(id);
+void f3(int);
+char f4(id, id);
+
+@interface Baz
+- (void)b:(void (^)(void))block;
+@end
+
+@interface Bar
+@end
+
+@interface Foo {
+ int _x;
+}
+@end
+
+@implementation Foo
+- (void)method:(Bar *)up {
+ Baz *down;
+ int at;
+ id cq;
+ __block char didit = 'a';
+ __block char upIsFinished = 'b';
+ f(^{
+ id old_cq;
+ f2(cq);
+ [down b:^{
+ [down b:^{
+ f(^{
+ didit = f4(up, down);
+ upIsFinished = 'c';
+ self->_x++;
+ });
+ }];
+ }];
+ f2(old_cq);
+ f3(at);
+ });
+}
+@end