From 7ce77920a35060f1c8dd72e541e42ce296ccd168 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Sat, 28 Feb 2009 20:07:56 +0000 Subject: [PATCH] Obscure code gen bug related to sending message to 'super' in a class method declared in cateogy (darwin specific). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65709 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjC.cpp | 2 + lib/CodeGen/CGObjCGNU.cpp | 2 + lib/CodeGen/CGObjCMac.cpp | 42 +++++++++++++++---- lib/CodeGen/CGObjCRuntime.h | 1 + test/CodeGenObjC/super-classmethod-category.m | 13 ++++++ 5 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 test/CodeGenObjC/super-classmethod-category.m diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index ec11edb349..cebaa1eb03 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -89,9 +89,11 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E) { if (isSuperMessage) { // super is only valid in an Objective-C method const ObjCMethodDecl *OMD = cast(CurFuncDecl); + bool isCategoryImpl = isa(OMD->getDeclContext()); return Runtime.GenerateMessageSendSuper(*this, E->getType(), E->getSelector(), OMD->getClassInterface(), + isCategoryImpl, Receiver, isClassMessage, Args); diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index b41f76db63..7877baaf3e 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -107,6 +107,7 @@ public: QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CallArgList &CallArgs); @@ -269,6 +270,7 @@ CGObjCGNU::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CallArgList &CallArgs) { diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 3beb91a29e..549a6b9f52 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -559,6 +559,7 @@ private: QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CallArgList &CallArgs); @@ -711,6 +712,7 @@ public: QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CallArgList &CallArgs); @@ -821,6 +823,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CodeGen::CallArgList &CallArgs) { @@ -836,10 +839,23 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // If this is a class message the metaclass is passed as the target. llvm::Value *Target; if (IsClassMessage) { - llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); - llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); - llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); - Target = Super; + if (isCategoryImpl) { + // Message sent to 'super' in a class method defined in a category + // implementation requires an odd treatment. + // If we are in a class method, we must retrieve the + // _metaclass_ for the current class, pointed at by + // the class's "isa" pointer. The following assumes that + // isa" is the first ivar in a class (which it must be). + Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); + Target = CGF.Builder.CreateStructGEP(Target, 0); + Target = CGF.Builder.CreateLoad(Target); + } + else { + llvm::Value *MetaClassPtr = EmitMetaClassRef(Class); + llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1); + llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr); + Target = Super; + } } else { Target = EmitClassRef(CGF.Builder, Class->getSuperClass()); } @@ -4616,6 +4632,7 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, const CodeGen::CallArgList &CallArgs) { @@ -4631,9 +4648,20 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); // If this is a class message the metaclass is passed as the target. - llvm::Value *Target = - IsClassMessage ? EmitMetaClassRef(CGF.Builder, Class) - : EmitClassRef(CGF.Builder, Class, true); + llvm::Value *Target; + if (IsClassMessage) { + if (isCategoryImpl) { + // Message sent to "super' in a class method defined in + // a category implementation. + Target = EmitClassRef(CGF.Builder, Class, false); + Target = CGF.Builder.CreateStructGEP(Target, 0); + Target = CGF.Builder.CreateLoad(Target); + } + else + Target = EmitMetaClassRef(CGF.Builder, Class); + } + else + Target = EmitClassRef(CGF.Builder, Class, true); // FIXME: We shouldn't need to do this cast, rectify the ASTContext // and ObjCTypes types. diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 15131579a7..63a7630dc0 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -98,6 +98,7 @@ public: QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Self, bool IsClassMessage, const CallArgList &CallArgs) = 0; diff --git a/test/CodeGenObjC/super-classmethod-category.m b/test/CodeGenObjC/super-classmethod-category.m new file mode 100644 index 0000000000..2e9efde438 --- /dev/null +++ b/test/CodeGenObjC/super-classmethod-category.m @@ -0,0 +1,13 @@ +// RUN: clang -fnext-runtime -emit-llvm -o %t %s + +@interface SUPER ++ (void)Meth; +@end + +@interface CURRENT : SUPER ++ (void)Meth; +@end + +@implementation CURRENT(CAT) ++ (void)Meth { [super Meth]; } +@end -- 2.40.0