]> granicus.if.org Git - clang/commitdiff
modern objc translation of block literal expressions
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 23 Mar 2012 00:00:49 +0000 (00:00 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 23 Mar 2012 00:00:49 +0000 (00:00 +0000)
declared at file scope.
// rdar://11006566

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

lib/Rewrite/RewriteModernObjC.cpp
test/Rewriter/rewrite-block-literal.mm [moved from test/Rewriter/rewrite-block-literal.c with 58% similarity]

index c4b0e5e48ebd4baf3108e1e128720472dd37f783..43615b6ea82f61764bf80322ec9605b02239fc8f 100644 (file)
@@ -73,6 +73,7 @@ namespace {
     
     TypeDecl *ProtocolTypeDecl;
     VarDecl *GlobalVarDecl;
+    Expr *GlobalConstructionExp;
     unsigned RewriteFailedDiag;
     unsigned GlobalBlockRewriteFailedDiag;
     // ObjC string constant support.
@@ -612,6 +613,7 @@ void RewriteModernObjC::InitializeCommon(ASTContext &context) {
   CurFunctionDef = 0;
   CurFunctionDeclToDeclareForBlock = 0;
   GlobalVarDecl = 0;
+  GlobalConstructionExp = 0;
   SuperStructDecl = 0;
   ProtocolTypeDecl = 0;
   ConstantStringDecl = 0;
@@ -3269,7 +3271,7 @@ std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
   QualType RT = AFT->getResultType();
   std::string StructRef = "struct " + Tag;
   std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
-                  funcName.str() + "_" + "block_func_" + utostr(i);
+                  funcName.str() + "_block_func_" + utostr(i);
 
   BlockDecl *BD = CE->getBlockDecl();
 
@@ -3632,7 +3634,27 @@ void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
       SC += "restrict ";
     InsertText(FunLocStart, SC);
   }
+  if (GlobalConstructionExp) {
+    // extra fancy dance for global literal expression.
+    
+    // Always the latest block expression on the block stack.
+    std::string Tag = "__";
+    Tag += FunName;
+    Tag += "_block_impl_";
+    Tag += utostr(Blocks.size()-1);
+    std::string globalBuf = "static ";
+    globalBuf += Tag; globalBuf += " ";
+    std::string SStr;
   
+    llvm::raw_string_ostream constructorExprBuf(SStr);
+    GlobalConstructionExp->printPretty(constructorExprBuf, *Context, 0,
+                                         PrintingPolicy(LangOpts));
+    globalBuf += constructorExprBuf.str();
+    globalBuf += ";\n";
+    InsertText(FunLocStart, globalBuf);
+    GlobalConstructionExp = 0;
+  }
+
   Blocks.clear();
   InnerDeclRefsCount.clear();
   InnerDeclRefs.clear();
@@ -4418,9 +4440,6 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
   
   const BlockDecl *block = Exp->getBlockDecl();
   
-  if (block->getDeclContext()->getRedeclContext()->isFileContext())
-    Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
-  
   Blocks.push_back(Exp);
 
   CollectBlockDeclRefInfo(Exp);
@@ -4465,9 +4484,16 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
   else if (GlobalVarDecl)
     FuncName = std::string(GlobalVarDecl->getNameAsString());
 
+  bool GlobalBlockExpr = 
+    block->getDeclContext()->getRedeclContext()->isFileContext();
+  
+  if (GlobalBlockExpr && !GlobalVarDecl) {
+    Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
+    GlobalBlockExpr = false;
+  }
+  
   std::string BlockNumber = utostr(Blocks.size()-1);
 
-  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
   std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
 
   // Get a pointer to the function type so we can cast appropriately.
@@ -4478,6 +4504,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
   Expr *NewRep;
 
   // Simulate a contructor call...
+  std::string Tag;
+  
+  if (GlobalBlockExpr)
+    Tag = "__global_";
+  else
+    Tag = "__";
+  Tag += FuncName + "_block_impl_" + BlockNumber;
+  
   FD = SynthBlockInitFunctionDecl(Tag);
   DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue,
                                                SourceLocation());
@@ -4599,6 +4633,14 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
   }
   NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(),
                                   FType, VK_LValue, SourceLocation());
+  
+  if (GlobalBlockExpr) {
+    assert (GlobalConstructionExp == 0 && 
+            "SynthBlockInitExpr - GlobalConstructionExp must be null");
+    GlobalConstructionExp = NewRep;
+    NewRep = DRE;
+  }
+  
   NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf,
                              Context->getPointerType(NewRep->getType()),
                              VK_RValue, OK_Ordinary, SourceLocation());
similarity index 58%
rename from test/Rewriter/rewrite-block-literal.c
rename to test/Rewriter/rewrite-block-literal.mm
index c618f3e39e49125bffbb02225502f392f0f9ecd5..732d0b9f8db9ddf709a47865473122c490639522 100644 (file)
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 -rewrite-objc %s -fblocks -o -
+// RUN: %clang_cc1 -E %s -o %t.mm
+// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %t.mm -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc -fobjc-fragile-abi %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+
+// rdar: // 11006566
 
 void I( void (^)(void));
 void (^noop)(void);
@@ -36,11 +41,6 @@ void test2() {
   }
 }
 
-
-void (^test3())(void) { 
-  return ^{};
-}
-
 void test4() {
   void (^noop)(void) = ^{};
   void (*noop2)() = 0;
@@ -61,17 +61,11 @@ void test5() {
 
 void *X;
 
-void test_arguments() {
-  int y;
-  int (^c)(char);
-  (1 ? c : 0)('x');
-  (1 ? 0 : c)('x');
-
-  (1 ? c : c)('x');
-}
-
 static int global_x = 10;
-void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); }; // expected-warning {{rewriting block literal declared in global scope is not implemented}}
+void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); };
+
+// CHECK: static __global_block_block_impl_0 __global_global_block_block_impl_0((void *)__global_block_block_func_0, &__global_block_block_desc_0_DATA);
+// CHECK: void (*global_block)(void) = (void (*)())&__global_global_block_block_impl_0;
 
 typedef void (^void_block_t)(void);