Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -1690,6 +1690,13 @@ let Documentation = [Undocumented]; } +def ObjCNonLazyClass : Attr { + let Spellings = [Clang<"objc_nonlazy_class">]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let LangOpts = [ObjC] + let Documentation = [Undocumented]; +} + def ObjCSubclassingRestricted : InheritableAttr { let Spellings = [Clang<"objc_subclassing_restricted">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -3498,6 +3498,14 @@ }]; } +def ObjCNonLazyClassDocs : Documentation { + let Category = DocCatType; + let Content = [{ +This attribute can be added to an Objective-C ``@interface`` declaration to +add the class to the list of non-lazily initialized classes. These are classes +that are realized at objc_init() time rather than when first referenced. + }]; +} def SelectAnyDocs : Documentation { let Category = DocCatType; Index: clang/lib/CodeGen/CGObjCMac.cpp =================================================================== --- clang/lib/CodeGen/CGObjCMac.cpp +++ clang/lib/CodeGen/CGObjCMac.cpp @@ -6253,9 +6253,10 @@ return GV; } -bool -CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { - return OD->getClassMethod(GetNullarySelector("load")) != nullptr; +bool CGObjCNonFragileABIMac::ImplementationIsNonLazy( + const ObjCImplDecl *OD) const { + return OD->getClassMethod(GetNullarySelector("load")) != nullptr || + OD->getClassInterface()->hasAttr(); } void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6374,6 +6374,9 @@ case ParsedAttr::AT_ObjCRootClass: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_ObjCNonLazyClass: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_ObjCSubclassingRestricted: handleSimpleAttribute(S, D, AL); break; Index: clang/test/CodeGenObjC/non-lazy-classes.m =================================================================== --- clang/test/CodeGenObjC/non-lazy-classes.m +++ clang/test/CodeGenObjC/non-lazy-classes.m @@ -1,11 +1,12 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -emit-llvm -o - %s | \ // RUN: FileCheck %s -// CHECK: @"OBJC_LABEL_NONLAZY_CLASS_$" = private global [1 x {{.*}}] {{.*}}@"OBJC_CLASS_$_A"{{.*}}, section "__DATA,__objc_nlclslist,regular,no_dead_strip", align 8 +// CHECK: @"OBJC_LABEL_NONLAZY_CLASS_$" = private global [2 x {{.*}}]{{.*}}@"OBJC_CLASS_$_A"{{.*}},{{.*}}@"OBJC_CLASS_$_D"{{.*}} section "__DATA,__objc_nlclslist,regular,no_dead_strip", align 8 // CHECK: @"OBJC_LABEL_NONLAZY_CATEGORY_$" = private global [1 x {{.*}}] {{.*}}@"\01l_OBJC_$_CATEGORY_A_$_Cat"{{.*}}, section "__DATA,__objc_nlcatlist,regular,no_dead_strip", align 8 -@interface A @end +@interface A +@end @implementation A -+(void) load { ++ (void)load { } @end @@ -27,6 +28,13 @@ } @end -@interface C : A @end +@interface C : A +@end @implementation C @end + +__attribute__((objc_nonlazy_class)) +@interface D @end + + @implementation D + @end