[cfe-commits] r58427 - /cfe/trunk/Driver/RewriteObjC.cpp

Steve Naroff snaroff at apple.com
Thu Oct 30 03:07:53 PDT 2008


Author: snaroff
Date: Thu Oct 30 05:07:53 2008
New Revision: 58427

URL: http://llvm.org/viewvc/llvm-project?rev=58427&view=rev
Log:
Convert SynthesizeBlockCall() from test->AST based implementation.

Modified:
    cfe/trunk/Driver/RewriteObjC.cpp

Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=58427&r1=58426&r2=58427&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Thu Oct 30 05:07:53 2008
@@ -266,7 +266,7 @@
                                       const char *funcName, std::string Tag);
     std::string SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 
                                     bool hasCopyDisposeHelpers);
-    std::string SynthesizeBlockCall(CallExpr *Exp);
+    Stmt *SynthesizeBlockCall(CallExpr *Exp);
     void SynthesizeBlockLiterals(SourceLocation FunLocStart,
                                    const char *FunName);
     
@@ -3466,7 +3466,7 @@
   return;
 }
 
-std::string RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
+Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
   // Navigate to relevant type information.
   const char *closureName = 0;
   const BlockPointerType *CPT = 0;
@@ -3489,49 +3489,61 @@
   const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(FT);
   // FTP will be null for closures that don't take arguments.
   
-  // Build a closure call - start with a paren expr to enforce precedence.
-  std::string BlockCall = "(";
+  RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
+                                      SourceLocation(),
+                                      &Context->Idents.get("__block_impl"));
+  QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
 
-  // Synthesize the cast.  
-  BlockCall += "(" + Exp->getType().getAsString() + "(*)";
-  BlockCall += "(struct __block_impl *";
+  // Generate a funky cast.
+  llvm::SmallVector<QualType, 8> ArgTypes;
+    
+  // Push the block argument type.
+  ArgTypes.push_back(PtrBlock);
   if (FTP) {
     for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(), 
-         E = FTP->arg_type_end(); I && (I != E); ++I)
-      BlockCall += ", " + (*I).getAsString();
+         E = FTP->arg_type_end(); I && (I != E); ++I) {
+      QualType t = *I;
+      // Make sure we convert "t (^)(...)" to "t (*)(...)".
+      if (isBlockPointerType(t)) {
+        const BlockPointerType *BPT = t->getAsBlockPointerType();
+        t = Context->getPointerType(BPT->getPointeeType());
+      }
+      ArgTypes.push_back(t);
+    }
   }
-  BlockCall += "))"; // close the argument list and paren expression.
+  // Now do the pointer to function cast.
+  QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(), 
+    &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0);
+    
+  PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
+  
+  CastExpr *BlkCast = new CStyleCastExpr(PtrBlock, Exp->getCallee(), PtrBlock, SourceLocation());
+  // Don't forget the parens to enforce the proper binding.
+  ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), BlkCast);
+  //PE->dump();
   
-  // 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 += "((struct __block_impl *)";
-  BlockCall += closureExprBuf.str();
+  FieldDecl *FD = FieldDecl::Create(*Context, SourceLocation(),
+                     &Context->Idents.get("FuncPtr"), Context->VoidPtrTy);
+  MemberExpr *ME = new MemberExpr(PE, true, FD, SourceLocation(), FD->getType());
+  
+  CastExpr *FunkCast = new CStyleCastExpr(PtrToFuncCastType, ME, PtrToFuncCastType, SourceLocation());
+  PE = new ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
+  
+  llvm::SmallVector<Expr*, 8> BlkExprs;
+  // Add the implicit argument.
+  BlkExprs.push_back(BlkCast);
+  // Add the user arguments.
   for (CallExpr::arg_iterator I = Exp->arg_begin(), 
        E = Exp->arg_end(); I != E; ++I) {
-    std::string syncExprBufS;
-    llvm::raw_string_ostream Buf(syncExprBufS);
-    (*I)->printPretty(Buf);
-    BlockCall += ", " + Buf.str();
+    BlkExprs.push_back(*I);
   }
-  return BlockCall;
+  CallExpr *CE = new CallExpr(PE, &BlkExprs[0], BlkExprs.size(), Exp->getType(), SourceLocation());
+  return CE;
 }
 
 void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
-  std::string BlockCall = SynthesizeBlockCall(Exp);
-  
-  const char *startBuf = SM->getCharacterData(Exp->getLocStart());
-  const char *endBuf = SM->getCharacterData(Exp->getLocEnd());
-
-  ReplaceText(Exp->getLocStart(), endBuf-startBuf, 
-              BlockCall.c_str(), BlockCall.size());
+  Stmt *BlockCall = SynthesizeBlockCall(Exp);
+  ReplaceStmt(Exp, BlockCall);
 }
 
 void RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) {
@@ -3954,8 +3966,11 @@
       RewriteBlockDeclRefExpr(BDRE);
   }
   if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
-    if (CE->getCallee()->getType()->isBlockPointerType())
-      RewriteBlockCall(CE);
+    if (CE->getCallee()->getType()->isBlockPointerType()) {
+      Stmt *BlockCall = SynthesizeBlockCall(CE);
+      ReplaceStmt(S, BlockCall);
+      return BlockCall;
+    }
   }
   if (CastExpr *CE = dyn_cast<CastExpr>(S)) {
     RewriteCastExpr(CE);





More information about the cfe-commits mailing list