]> granicus.if.org Git - clang/commitdiff
More rewriter of nested blocks fun stuff.
authorFariborz Jahanian <fjahanian@apple.com>
Mon, 1 Mar 2010 23:36:21 +0000 (23:36 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Mon, 1 Mar 2010 23:36:21 +0000 (23:36 +0000)
Radar 7696893.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97520 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Frontend/RewriteObjC.cpp
test/Rewriter/rewrite-nested-blocks-1.mm [new file with mode: 0644]

index 635280bf4326fc5f7ef653643738892a350f0fba..98dee264e901541785f4cad3ee1e1cc99ac9b7d9 100644 (file)
@@ -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 (file)
index 0000000..582f5f4
--- /dev/null
@@ -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