- Add a convenience constructor to Type.
- Many rewriter modifications.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57003 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/RewriteBlocks.cpp b/Driver/RewriteBlocks.cpp
index 103072c..ea03650 100644
--- a/Driver/RewriteBlocks.cpp
+++ b/Driver/RewriteBlocks.cpp
@@ -540,7 +540,7 @@
     // Finish writing the constructor.
     // FIXME: handle NSConcreteGlobalBlock.
     Constructor += ", int flags=0) {\n";
-    Constructor += "    impl.isa = &_NSConcreteStackBlock;\n    impl.Size = sizeof(";
+    Constructor += "    impl.isa = 0/*&_NSConcreteStackBlock*/;\n    impl.Size = sizeof(";
     Constructor += Tag + ");\n    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
     
     // Initialize all "by copy" arguments.
@@ -559,10 +559,16 @@
       Constructor += Name + " = _";
       Constructor += Name + ";\n";
     }
-    Constructor += "  ";
-    Constructor += "}\n";
-    S += Constructor;
+  } else {
+    // Finish writing the constructor.
+    // FIXME: handle NSConcreteGlobalBlock.
+    Constructor += ", int flags=0) {\n";
+    Constructor += "    impl.isa = 0/*&_NSConcreteStackBlock*/;\n    impl.Size = sizeof(";
+    Constructor += Tag + ");\n    impl.Flags = flags;\n    impl.FuncPtr = fp;\n";
   }
+  Constructor += "  ";
+  Constructor += "}\n";
+  S += Constructor;
   S += "};\n";
   return S;
 }
@@ -654,6 +660,17 @@
       RewriteBlockPointerDecl(TD);
     return;
   }
+  if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+    if (RD->isDefinition()) {
+      for (RecordDecl::field_const_iterator i = RD->field_begin(), 
+             e = RD->field_end(); i != e; ++i) {
+        FieldDecl *FD = *i;
+        if (isBlockPointerType(FD->getType()))
+          RewriteBlockPointerDecl(FD);
+      }
+    }
+    return;
+  }
 }
 
 void RewriteBlocks::GetBlockDeclRefExprs(Stmt *S) {
@@ -733,6 +750,9 @@
   } else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
     closureName = CDRE->getDecl()->getName();
     CPT = CDRE->getType()->getAsBlockPointerType();
+  } else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
+    closureName = MExpr->getMemberDecl()->getName();
+    CPT = MExpr->getType()->getAsBlockPointerType();
   } else {
     assert(1 && "RewriteBlockClass: Bad type");
   }
@@ -755,12 +775,17 @@
   }
   BlockCall += "))"; // close the argument list and paren expression.
   
-  // Invoke the closure.
-  BlockCall += closureName;
-  BlockCall += "->Invoke)";
+  // Invoke the closure. We need to cast it since the declaration type is
+  // bogus (it's a function pointer type)
+  BlockCall += "((struct __block_impl *)";
+  std::string closureExprBufStr;
+  llvm::raw_string_ostream closureExprBuf(closureExprBufStr);
+  Exp->getCallee()->printPretty(closureExprBuf);
+  BlockCall += closureExprBuf.str();
+  BlockCall += ")->FuncPtr)";
   
   // Add the arguments.
-  BlockCall += "(";
+  BlockCall += "((struct __block_impl *)";
   BlockCall += closureName;
   for (CallExpr::arg_iterator I = Exp->arg_begin(), 
        E = Exp->arg_end(); I != E; ++I) {
@@ -903,6 +928,8 @@
     DeclT = VD->getType();
   else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
     DeclT = TDD->getUnderlyingType();
+  else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
+    DeclT = FD->getType();
   else 
     assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled");
     
@@ -965,16 +992,22 @@
   }
   std::string BlockNumber = utostr(Blocks.size()-1);
   
-  std::string Tag = "struct __" + FuncName + "_block_impl_" + BlockNumber;
+  std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
   std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
   
+  std::string FunkTypeStr;
+  
+  // Get a pointer to the function type so we can cast appropriately.
+  Context->getPointerType(QualType(Exp->getFunctionType(),0)).getAsStringInternal(FunkTypeStr);
+  
   // Rewrite the closure block with a compound literal. The first cast is
   // to prevent warnings from the C compiler.
-  std::string Init = "(struct __block_impl *)&(" + Tag + "){{0,";
+  std::string Init = "(" + FunkTypeStr;
   
-  // Initialize the Flags, Size, and Invoke fields.
-  Init += (haveByRefDecls ? "HAS_BYREF," : "0,");
-  Init += "sizeof(" + Tag + ")," + Func + "}";
+  Init += ")&" + Tag;
+  
+  // Initialize the block function.
+  Init += "((void*)" + Func;
   
   // Add initializers for any closure decl refs.
   if (BlockDeclRefs.size()) {
@@ -997,7 +1030,7 @@
       Init += (*I)->getName();
     }
   }
-  Init += "}";
+  Init += ")";
   BlockDeclRefs.clear();
   BlockByRefDecls.clear();
   BlockByCopyDecls.clear();