From: Fariborz Jahanian Date: Tue, 20 Mar 2012 19:54:33 +0000 (+0000) Subject: modern objective-c translator: provide meta-data initialization X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a03e40ce9d729fca50e817351e3b1b48691dcd64;p=clang modern objective-c translator: provide meta-data initialization via functions for certain pointer initialization fields. // rdar://11076938 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153117 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp index cbae690677..ead1ce6a5d 100644 --- a/lib/Rewrite/RewriteModernObjC.cpp +++ b/lib/Rewrite/RewriteModernObjC.cpp @@ -5595,9 +5595,19 @@ static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Resu static void Write_class_t(ASTContext *Context, std::string &Result, StringRef VarName, - const ObjCInterfaceDecl *CDecl, bool metadata) { - - if (metadata && !CDecl->getSuperClass()) { + const ObjCInterfaceDecl *CDecl, bool metaclass) { + bool rootClass = (!CDecl->getSuperClass()); + const ObjCInterfaceDecl *RootClass = CDecl; + + if (!rootClass) { + // Find the Root class + RootClass = CDecl->getSuperClass(); + while (RootClass->getSuperClass()) { + RootClass = RootClass->getSuperClass(); + } + } + + if (metaclass && rootClass) { // Need to handle a case of use of forward declaration. Result += "\n"; if (CDecl->getImplementation()) @@ -5607,7 +5617,7 @@ static void Write_class_t(ASTContext *Context, std::string &Result, Result += ";\n"; } // Also, for possibility of 'super' metadata class not having been defined yet. - if (CDecl->getSuperClass()) { + if (!rootClass) { Result += "\n"; if (CDecl->getSuperClass()->getImplementation()) Result += "__declspec(dllexport) "; @@ -5620,43 +5630,87 @@ static void Write_class_t(ASTContext *Context, std::string &Result, Result += "\n__declspec(dllexport) struct _class_t "; Result += VarName; Result += CDecl->getNameAsString(); Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n"; Result += "\t"; - if (metadata) { - if (CDecl->getSuperClass()) { - Result += "&"; Result += VarName; - Result += CDecl->getSuperClass()->getNameAsString(); + if (metaclass) { + if (!rootClass) { + Result += "0, // &"; Result += VarName; + Result += RootClass->getNameAsString(); Result += ",\n\t"; - Result += "&"; Result += VarName; + Result += "0, // &"; Result += VarName; Result += CDecl->getSuperClass()->getNameAsString(); Result += ",\n\t"; } else { - Result += "&"; Result += VarName; + Result += "0, // "; Result += VarName; Result += CDecl->getNameAsString(); Result += ",\n\t"; - Result += "&OBJC_CLASS_$_"; Result += CDecl->getNameAsString(); + Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString(); Result += ",\n\t"; } } else { - Result += "&OBJC_METACLASS_$_"; + Result += "0, // &OBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); Result += ",\n\t"; - if (CDecl->getSuperClass()) { - Result += "&"; Result += VarName; + if (!rootClass) { + Result += "0, // &"; Result += VarName; Result += CDecl->getSuperClass()->getNameAsString(); Result += ",\n\t"; } else Result += "0,\n\t"; } - Result += "(void *)&_objc_empty_cache,\n\t"; - Result += "(void *)&_objc_empty_vtable,\n\t"; - if (metadata) + Result += "0, // (void *)&_objc_empty_cache,\n\t"; + Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t"; + if (metaclass) Result += "&_OBJC_METACLASS_RO_$_"; else Result += "&_OBJC_CLASS_RO_$_"; Result += CDecl->getNameAsString(); Result += ",\n};\n"; + + // Add static function to initialize some of the meta-data fields. + // avoid doing it twice. + if (metaclass) + return; + + const ObjCInterfaceDecl *SuperClass = + rootClass ? CDecl : CDecl->getSuperClass(); + + Result += "static void OBJC_CLASS_SETUP_$_"; + Result += CDecl->getNameAsString(); + Result += "(void ) {\n"; + Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; + Result += CDecl->getNameAsString(); Result += ";\n"; + + Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".superclass = "; Result += "&OBJC_METACLASS_$_"; + Result += SuperClass->getNameAsString(); Result += ";\n"; + + Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; + + Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; + Result += CDecl->getNameAsString(); Result += ";\n"; + + if (!rootClass) { + Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".superclass = "; Result += "&OBJC_CLASS_$_"; + Result += SuperClass->getNameAsString(); Result += ";\n"; + } + + Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); + Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; + Result += "}\n"; + + Result += "#pragma section(\".objc_inithooks$B\", long, read, write\n"; + Result += "__declspec(allocate(\".objc_inithooks$B\")) "; + Result += "static void *OBJC_CLASS_SETUP2_$_"; + Result += CDecl->getNameAsString(); + Result += " = (void *)&OBJC_CLASS_SETUP_$_"; + Result += CDecl->getNameAsString(); + Result += ";\n\n"; } static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context, diff --git a/test/Rewriter/objc-modern-class-init.mm b/test/Rewriter/objc-modern-class-init.mm new file mode 100644 index 0000000000..4a21bc4e30 --- /dev/null +++ b/test/Rewriter/objc-modern-class-init.mm @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// rdar:// 11076938 + +@interface Root @end + +@interface Super : Root +@end + +@interface Sub : Super +@end + +@implementation Sub @end + +@implementation Root @end