forked from OSchip/llvm-project
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). llvm-svn: 43685
This commit is contained in:
parent
eea82746b3
commit
f36987c79b
|
@ -42,7 +42,7 @@ namespace {
|
||||||
// ObjC string constant support.
|
// ObjC string constant support.
|
||||||
FileVarDecl *ConstantStringClassReference;
|
FileVarDecl *ConstantStringClassReference;
|
||||||
RecordDecl *NSStringRecord;
|
RecordDecl *NSStringRecord;
|
||||||
|
|
||||||
static const int OBJC_ABI_VERSION =7 ;
|
static const int OBJC_ABI_VERSION =7 ;
|
||||||
public:
|
public:
|
||||||
void Initialize(ASTContext &context, unsigned mainFileID) {
|
void Initialize(ASTContext &context, unsigned mainFileID) {
|
||||||
|
@ -55,6 +55,12 @@ namespace {
|
||||||
ConstantStringClassReference = 0;
|
ConstantStringClassReference = 0;
|
||||||
NSStringRecord = 0;
|
NSStringRecord = 0;
|
||||||
Rewrite.setSourceMgr(Context->SourceMgr);
|
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.
|
// Top Level Driver code.
|
||||||
|
@ -63,6 +69,7 @@ namespace {
|
||||||
~RewriteTest();
|
~RewriteTest();
|
||||||
|
|
||||||
// Syntactic Rewriting.
|
// Syntactic Rewriting.
|
||||||
|
void RewritePrologue(SourceLocation Loc);
|
||||||
void RewriteInclude(SourceLocation Loc);
|
void RewriteInclude(SourceLocation Loc);
|
||||||
void RewriteTabs();
|
void RewriteTabs();
|
||||||
void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
|
void RewriteForwardClassDecl(ObjcClassDecl *Dcl);
|
||||||
|
@ -644,13 +651,53 @@ Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) {
|
||||||
// the original expression, since we will delete it below.
|
// the original expression, since we will delete it below.
|
||||||
Exp->setArg(i, 0);
|
Exp->setArg(i, 0);
|
||||||
}
|
}
|
||||||
CallExpr *MessExp = SynthesizeCallToFunctionDecl(MsgSendFunctionDecl,
|
// Generate the funky cast.
|
||||||
&MsgExprs[0], MsgExprs.size());
|
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.
|
// Now do the actual rewrite.
|
||||||
Rewrite.ReplaceStmt(Exp, MessExp);
|
Rewrite.ReplaceStmt(Exp, CE);
|
||||||
|
|
||||||
delete Exp;
|
delete Exp;
|
||||||
return MessExp;
|
return CE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
|
/// SynthesizeObjcInternalStruct - Rewrite one internal struct corresponding to
|
||||||
|
|
Loading…
Reference in New Issue