diff options
author | Steve Naroff <snaroff@apple.com> | 2007-11-04 22:37:50 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2007-11-04 22:37:50 +0000 |
commit | ab972d3c4b49fb0b99ae2beee70c1771a05342ba (patch) | |
tree | 5efa0235c7ddece64df18984edd7cd9d8d31657a /Driver/RewriteTest.cpp | |
parent | db611d556f71f98b66b69514d45958d76e5727ab (diff) |
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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43685 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'Driver/RewriteTest.cpp')
-rw-r--r-- | Driver/RewriteTest.cpp | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index b4d2fdf4a7..68ca142732 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -42,7 +42,7 @@ namespace { // 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 @@ namespace { 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 @@ namespace { ~RewriteTest(); // Syntactic Rewriting. + void RewritePrologue(SourceLocation Loc); void RewriteInclude(SourceLocation Loc); void RewriteTabs(); void RewriteForwardClassDecl(ObjcClassDecl *Dcl); @@ -644,13 +651,53 @@ Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) { // 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 |