[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