[cfe-commits] r43685 - /cfe/trunk/Driver/RewriteTest.cpp

Steve Naroff snaroff at apple.com
Sun Nov 4 14:37:50 PST 2007


Author: snaroff
Date: Sun Nov  4 16:37:50 2007
New Revision: 43685

URL: http://llvm.org/viewvc/llvm-project?rev=43685&view=rev
Log:

Two additions...

- Synthesize the funky cast for objc_msgSend(). For the basic case, it looks like...

((id (*)(id, SEL))(void *)objc_msgSend)(obj, sel);

The "void *" cast is needed to workaround a GCC "bandaid" (Chris says it has something to do with the inliner). Without the extra "void *" cast, we get spurious warnings/notes that look like...

xx.m:17: warning: function called through a non-compatible type
xx.m:17: note: if this code is reached, the program will abort

- Add prototypes for the ObjC functions we call, objc_msgSend/objc_getClass for now (don't depend on them being included).

Modified:
    cfe/trunk/Driver/RewriteTest.cpp

Modified: cfe/trunk/Driver/RewriteTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteTest.cpp?rev=43685&r1=43684&r2=43685&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteTest.cpp (original)
+++ cfe/trunk/Driver/RewriteTest.cpp Sun Nov  4 16:37:50 2007
@@ -42,7 +42,7 @@
     // ObjC string constant support.
     FileVarDecl *ConstantStringClassReference;
     RecordDecl *NSStringRecord;
-      
+    
     static const int OBJC_ABI_VERSION =7 ;
   public:
     void Initialize(ASTContext &context, unsigned mainFileID) {
@@ -55,6 +55,12 @@
       ConstantStringClassReference = 0;
       NSStringRecord = 0;
       Rewrite.setSourceMgr(Context->SourceMgr);
+      const char *s = "extern struct objc_object *objc_msgSend"
+                      "(struct objc_object *, struct objc_selector *, ...);\n"
+                      "extern struct objc_object *objc_getClass"
+                      "(const char *);\n";
+      Rewrite.InsertText(SourceLocation::getFileLoc(mainFileID, 0), 
+                         s, strlen(s));
     }
 
     // Top Level Driver code.
@@ -63,6 +69,7 @@
     ~RewriteTest();
 
     // Syntactic Rewriting.
+    void RewritePrologue(SourceLocation Loc);
     void RewriteInclude(SourceLocation Loc);
     void RewriteTabs();
     void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
@@ -644,13 +651,53 @@
     // the original expression, since we will delete it below.
     Exp->setArg(i, 0);
   }
-  CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
-                                                 &MsgExprs[0], MsgExprs.size());
+  // Generate the funky cast.
+  CastExpr *cast;
+  llvm::SmallVector<QualType, 8> ArgTypes;
+  QualType returnType;
+  
+  // Push 'id' and 'SEL', the 2 implicit arguments.
+  ArgTypes.push_back(Context->getObjcIdType());
+  ArgTypes.push_back(Context->getObjcSelType());
+  if (ObjcMethodDecl *mDecl = Exp->getMethodDecl()) {
+    // Push any user argument types.
+    for (int i = 0; i < mDecl->getNumParams(); i++) 
+      ArgTypes.push_back(mDecl->getParamDecl(i)->getType());
+    returnType = mDecl->getResultType();
+  } else {
+    returnType = Context->getObjcIdType();
+  }
+  // Get the type, we will need to reference it in a couple spots.
+  QualType msgSendType = MsgSendFunctionDecl->getType();
+  
+  // Create a reference to the objc_msgSend() declaration.
+  DeclRefExpr *DRE = new DeclRefExpr(MsgSendFunctionDecl, msgSendType, SourceLocation());
+
+  // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 
+  // If we don't do this cast, we get the following bizarre warning/note:
+  // xx.m:13: warning: function called through a non-compatible type
+  // xx.m:13: note: if this code is reached, the program will abort
+  cast = new CastExpr(Context->getPointerType(Context->VoidTy), DRE, 
+                      SourceLocation());
+                                                   
+  // Now do the "normal" pointer to function cast.
+  QualType castType = Context->getFunctionType(returnType, 
+                                               &ArgTypes[0], ArgTypes.size(),
+                                               false/*FIXME:variadic*/);
+  castType = Context->getPointerType(castType);
+  cast = new CastExpr(castType, cast, SourceLocation());
+
+  // Don't forget the parens to enforce the proper binding.
+  ParenExpr *PE = new ParenExpr(SourceLocation(), SourceLocation(), cast);
+  
+  const FunctionType *FT = msgSendType->getAsFunctionType();
+  CallExpr *CE = new CallExpr(PE, &MsgExprs[0], MsgExprs.size(), 
+                              FT->getResultType(), SourceLocation());
   // Now do the actual rewrite.
-  Rewrite.ReplaceStmt(Exp, MessExp);
+  Rewrite.ReplaceStmt(Exp, CE);
   
   delete Exp;
-  return MessExp;
+  return CE;
 }
 
 /// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to





More information about the cfe-commits mailing list