Change the 'super' messaging API in the rewriter.

Fixes radar 7738452.

llvm-svn: 98190
This commit is contained in:
Fariborz Jahanian 2010-03-10 21:17:41 +00:00
parent c9d4a84c2a
commit a4a925febb
2 changed files with 82 additions and 23 deletions

View File

@ -89,6 +89,7 @@ namespace {
FunctionDecl *MsgSendFpretFunctionDecl;
FunctionDecl *GetClassFunctionDecl;
FunctionDecl *GetMetaClassFunctionDecl;
FunctionDecl *GetSuperClassFunctionDecl;
FunctionDecl *SelGetUidFunctionDecl;
FunctionDecl *CFStringFunctionDecl;
FunctionDecl *SuperContructorFunctionDecl;
@ -271,7 +272,7 @@ namespace {
void RewriteTypeOfDecl(VarDecl *VD);
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
bool needToScanForQualifiers(QualType T);
ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
bool isSuperReceiver(Expr *recExpr);
QualType getSuperStructType();
QualType getConstantStringStructType();
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
@ -323,6 +324,7 @@ namespace {
void SynthMsgSendSuperStretFunctionDecl();
void SynthGetClassFunctionDecl();
void SynthGetMetaClassFunctionDecl();
void SynthGetSuperClassFunctionDecl();
void SynthSelGetUidFunctionDecl();
void SynthSuperContructorFunctionDecl();
@ -510,6 +512,7 @@ void RewriteObjC::Initialize(ASTContext &context) {
MsgSendFpretFunctionDecl = 0;
GetClassFunctionDecl = 0;
GetMetaClassFunctionDecl = 0;
GetSuperClassFunctionDecl = 0;
SelGetUidFunctionDecl = 0;
CFStringFunctionDecl = 0;
ConstantStringClassReference = 0;
@ -572,6 +575,8 @@ void RewriteObjC::Initialize(ASTContext &context) {
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
Preamble += "(const char *);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
Preamble += "(struct objc_class *);\n";
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
Preamble += "(const char *);\n";
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
@ -2491,6 +2496,23 @@ void RewriteObjC::SynthGetClassFunctionDecl() {
FunctionDecl::Extern, false);
}
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
void RewriteObjC::SynthGetSuperClassFunctionDecl() {
IdentifierInfo *getSuperClassIdent =
&Context->Idents.get("class_getSuperclass");
llvm::SmallVector<QualType, 16> ArgTys;
ArgTys.push_back(Context->getObjCClassType());
QualType getClassType = Context->getFunctionType(Context->getObjCClassType(),
&ArgTys[0], ArgTys.size(),
false /*isVariadic*/, 0,
false, false, 0, 0, false,
CC_Default);
GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
SourceLocation(),
getSuperClassIdent, getClassType, 0,
FunctionDecl::Extern, false);
}
// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
void RewriteObjC::SynthGetMetaClassFunctionDecl() {
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
@ -2551,18 +2573,10 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
return cast;
}
ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
bool RewriteObjC::isSuperReceiver(Expr *recExpr) {
// check if we are sending a message to 'super'
if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
const ObjCObjectPointerType *OPT =
Super->getType()->getAs<ObjCObjectPointerType>();
assert(OPT);
const ObjCInterfaceType *IT = OPT->getInterfaceType();
return IT->getDecl();
}
return 0;
if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return false;
return isa<ObjCSuperExpr>(recExpr);
}
// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
@ -2640,6 +2654,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SynthMsgSendFpretFunctionDecl();
if (!GetClassFunctionDecl)
SynthGetClassFunctionDecl();
if (!GetSuperClassFunctionDecl)
SynthGetSuperClassFunctionDecl();
if (!GetMetaClassFunctionDecl)
SynthGetMetaClassFunctionDecl();
@ -2669,8 +2685,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
ObjCInterfaceDecl *SuperDecl =
CurMethodDef->getClassInterface()->getSuperClass();
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
llvm::SmallVector<Expr*, 4> InitExprs;
@ -2683,19 +2698,31 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
SourceLocation()))
); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
SuperDecl->getIdentifier()->getNameStart(),
SuperDecl->getIdentifier()->getLength(),
ClassDecl->getIdentifier()->getNameStart(),
ClassDecl->getIdentifier()->getLength(),
false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size(),
StartLoc,
EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
CastExpr::CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
&ClsExprs[0], ClsExprs.size(),
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back( // set 'super class', using objc_getClass().
InitExprs.push_back( // set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context,
Context->getObjCIdType(),
CastExpr::CK_Unknown, Cls));
@ -2755,12 +2782,12 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
} else { // instance message.
Expr *recExpr = Exp->getReceiver();
if (ObjCInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
if (isSuperReceiver(recExpr)) {
MsgSendFlavor = MsgSendSuperFunctionDecl;
if (MsgSendStretFlavor)
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
llvm::SmallVector<Expr*, 4> InitExprs;
InitExprs.push_back(
@ -2770,20 +2797,32 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
Context->getObjCIdType(),
SourceLocation()))
); // set the 'receiver'.
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
llvm::SmallVector<Expr*, 8> ClsExprs;
QualType argType = Context->getPointerType(Context->CharTy);
ClsExprs.push_back(StringLiteral::Create(*Context,
SuperDecl->getIdentifier()->getNameStart(),
SuperDecl->getIdentifier()->getLength(),
ClassDecl->getIdentifier()->getNameStart(),
ClassDecl->getIdentifier()->getLength(),
false, argType, SourceLocation()));
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
&ClsExprs[0],
ClsExprs.size(),
StartLoc, EndLoc);
// (Class)objc_getClass("CurrentClass")
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
Context->getObjCClassType(),
CastExpr::CK_Unknown, Cls);
ClsExprs.clear();
ClsExprs.push_back(ArgExpr);
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl,
&ClsExprs[0], ClsExprs.size(),
StartLoc, EndLoc);
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
// To turn off a warning, type-cast to 'id'
InitExprs.push_back(
// set 'super class', using objc_getClass().
// set 'super class', using class_getSuperclass().
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
CastExpr::CK_Unknown, Cls));
// struct objc_super

View File

@ -0,0 +1,20 @@
// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=struct objc_object *" -D"Class=struct objc_class *" -D"SEL=void*" -D"__declspec(X)=" -emit-llvm -o - %t-rw.cpp | FileCheck %t-rw.cpp
// radar 7738453
void *sel_registerName(const char *);
@interface __NSCFType
@end
@interface __NSCFString : __NSCFType
- (const char *)UTF8String;
@end
@implementation __NSCFString
- (const char *)UTF8String {
return (const char *)[super UTF8String];
}
@end
// CHECK: call %struct.objc_class* @class_getSuperclass