From 939cf8c4bbe309d23cc6c7fe211ae7fd7512d53d Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 3 Dec 2025 22:14:25 -0800 Subject: [PATCH] [domain availability] Ignore disabled ivars during CodeGen Fix a bug where disabled ivars weren't being ignored during codegen for method .cxx_destruct and ivar bitmap layout. rdar://165722993 --- clang/lib/CodeGen/CGObjC.cpp | 3 + clang/lib/CodeGen/CGObjCMac.cpp | 3 +- clang/test/CodeGenObjC/feature-availability.m | 169 +++++++++++------- 3 files changed, 107 insertions(+), 68 deletions(-) diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 946adaeda2390..ae4cf7f295bee 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1722,6 +1722,9 @@ static void emitCXXDestructMethod(CodeGenFunction &CGF, const ObjCInterfaceDecl *iface = impl->getClassInterface(); for (const ObjCIvarDecl *ivar = iface->all_declared_ivar_begin(); ivar; ivar = ivar->getNextIvar()) { + if (CGF.CGM.getContext().hasUnavailableFeature(ivar)) + continue; + QualType type = ivar->getType(); // Check whether the ivar is a destructible type. diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index c5b587c70ec22..4ce293767ed52 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -5488,7 +5488,8 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD; IVD = IVD->getNextIvar()) - ivars.push_back(IVD); + if (!CGM.getContext().hasUnavailableFeature(IVD)) + ivars.push_back(IVD); if (isNonFragileABI()) { baseOffset = beginOffset; // InstanceStart diff --git a/clang/test/CodeGenObjC/feature-availability.m b/clang/test/CodeGenObjC/feature-availability.m index 13b2a43b9d756..1f991fd305aaa 100644 --- a/clang/test/CodeGenObjC/feature-availability.m +++ b/clang/test/CodeGenObjC/feature-availability.m @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -ffeature-availability=feature3:on -emit-llvm -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN %s | FileCheck %s -// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -ffeature-availability=feature1:on -ffeature-availability=feature2:off -ffeature-availability=feature3:on -emit-llvm -fobjc-arc -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -fobjc-arc -o - -DUSE_DOMAIN %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-macosx -fblocks -emit-llvm -fobjc-arc -o - -DUSE_DOMAIN -DALWAYS_ENABLED %s | FileCheck %s #include @@ -20,7 +20,7 @@ // CHECK: @"OBJC_CLASS_$_C0" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C0", ptr null, ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_CLASS_RO_$_C0" }, section "__DATA, __objc_data", align 8 // CHECK-NEXT: @"OBJC_METACLASS_$_C0" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C0", ptr @"OBJC_CLASS_$_C0", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_METACLASS_RO_$_C0" }, section "__DATA, __objc_data", align 8 // CHECK-NEXT: @OBJC_CLASS_NAME_ = private unnamed_addr constant [3 x i8] c"C0\00", section "__TEXT,__objc_classname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C0" = internal global %struct._class_ro_t { i32 3, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_, ptr null, ptr null, ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C0" = internal global %struct._class_ro_t { i32 131, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_, ptr null, ptr null, ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @OBJC_METH_VAR_NAME_ = private unnamed_addr constant [3 x i8] c"m0\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK-NEXT: @OBJC_METH_VAR_TYPE_ = private unnamed_addr constant [8 x i8] c"v16@0:8\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 // CHECK-NEXT: @OBJC_METH_VAR_NAME_.1 = private unnamed_addr constant [3 x i8] c"m1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 @@ -38,58 +38,72 @@ // CHECK-NEXT: @OBJC_PROP_NAME_ATTR_ = private unnamed_addr constant [6 x i8] c"prop0\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.9 = private unnamed_addr constant [11 x i8] c"Ti,V_prop0\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK-NEXT: @"_OBJC_$_PROP_LIST_C0" = internal global { i32, i32, [1 x %struct._prop_t] } { i32 16, i32 1, [1 x %struct._prop_t] [%struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_, ptr @OBJC_PROP_NAME_ATTR_.9 }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C0" = internal global %struct._class_ro_t { i32 2, i32 0, i32 8, ptr null, ptr @OBJC_CLASS_NAME_, ptr @"_OBJC_$_INSTANCE_METHODS_C0", ptr null, ptr @"_OBJC_$_INSTANCE_VARIABLES_C0", ptr null, ptr @"_OBJC_$_PROP_LIST_C0" }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C0" = internal global %struct._class_ro_t { i32 130, i32 0, i32 8, ptr null, ptr @OBJC_CLASS_NAME_, ptr @"_OBJC_$_INSTANCE_METHODS_C0", ptr null, ptr @"_OBJC_$_INSTANCE_VARIABLES_C0", ptr null, ptr @"_OBJC_$_PROP_LIST_C0" }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @OBJC_CLASS_NAME_.10 = private unnamed_addr constant [5 x i8] c"Cat0\00", section "__TEXT,__objc_classname,cstring_literals", align 1 // CHECK-NEXT: @"OBJC_METACLASS_$_NSObject" = external global %struct._class_t // CHECK-NEXT: @OBJC_CLASS_NAME_.11 = private unnamed_addr constant [3 x i8] c"C2\00", section "__TEXT,__objc_classname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C2" = internal global %struct._class_ro_t { i32 1, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_.11, ptr null, ptr null, ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C2" = internal global %struct._class_ro_t { i32 389, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_.11, ptr null, ptr null, ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"OBJC_METACLASS_$_C2" = global %struct._class_t { ptr @"OBJC_METACLASS_$_NSObject", ptr @"OBJC_METACLASS_$_NSObject", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_METACLASS_RO_$_C2" }, section "__DATA, __objc_data", align 8 // CHECK-NEXT: @"OBJC_CLASS_$_NSObject" = external global %struct._class_t -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.12 = private unnamed_addr constant [6 x i8] c"ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.13 = private unnamed_addr constant [8 x i8] c"@16@0:8\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.14 = private unnamed_addr constant [10 x i8] c"setIvar1:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.15 = private unnamed_addr constant [11 x i8] c"v24@0:8@16\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.16 = private unnamed_addr constant [6 x i8] c"ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.17 = private unnamed_addr constant [10 x i8] c"setIvar3:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.18 = private unnamed_addr constant [6 x i8] c"ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.19 = private unnamed_addr constant [10 x i8] c"setIvar4:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C2" = internal global { i32, i32, [6 x %struct._objc_method] } { i32 24, i32 6, [6 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.12, ptr @OBJC_METH_VAR_TYPE_.13, ptr @"\01-[C2 ivar1]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.14, ptr @OBJC_METH_VAR_TYPE_.15, ptr @"\01-[C2 setIvar1:]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.16, ptr @OBJC_METH_VAR_TYPE_.13, ptr @"\01-[C2 ivar3]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.17, ptr @OBJC_METH_VAR_TYPE_.15, ptr @"\01-[C2 setIvar3:]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.18, ptr @OBJC_METH_VAR_TYPE_.13, ptr @"\01-[C2 ivar4]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.19, ptr @OBJC_METH_VAR_TYPE_.15, ptr @"\01-[C2 setIvar4:]" }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_CLASS_NAME_.12 = private unnamed_addr constant [2 x i8] c"\03\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.13 = private unnamed_addr constant [6 x i8] c"ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.14 = private unnamed_addr constant [8 x i8] c"@16@0:8\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.15 = private unnamed_addr constant [10 x i8] c"setIvar1:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.16 = private unnamed_addr constant [11 x i8] c"v24@0:8@16\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.17 = private unnamed_addr constant [6 x i8] c"ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.18 = private unnamed_addr constant [10 x i8] c"setIvar3:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.19 = private unnamed_addr constant [6 x i8] c"ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.20 = private unnamed_addr constant [10 x i8] c"setIvar4:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.21 = private unnamed_addr constant [14 x i8] c".cxx_destruct\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C2" = internal global { i32, i32, [7 x %struct._objc_method] } { i32 24, i32 7, [7 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.13, ptr @OBJC_METH_VAR_TYPE_.14, ptr @"\01-[C2 ivar1]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.15, ptr @OBJC_METH_VAR_TYPE_.16, ptr @"\01-[C2 setIvar1:]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.17, ptr @OBJC_METH_VAR_TYPE_.14, ptr @"\01-[C2 ivar3]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.18, ptr @OBJC_METH_VAR_TYPE_.16, ptr @"\01-[C2 setIvar3:]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.19, ptr @OBJC_METH_VAR_TYPE_.14, ptr @"\01-[C2 ivar4]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.20, ptr @OBJC_METH_VAR_TYPE_.16, ptr @"\01-[C2 setIvar4:]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.21, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C2 .cxx_destruct]" }] }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"OBJC_IVAR_$_C2._ivar1" = hidden constant i32 8, section "__DATA, __objc_ivar", align 4 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.20 = private unnamed_addr constant [7 x i8] c"_ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.21 = private unnamed_addr constant [2 x i8] c"@\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.22 = private unnamed_addr constant [7 x i8] c"_ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.23 = private unnamed_addr constant [2 x i8] c"@\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 // CHECK-NEXT: @"OBJC_IVAR_$_C2._ivar3" = hidden constant i32 16, section "__DATA, __objc_ivar", align 4 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.22 = private unnamed_addr constant [7 x i8] c"_ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.24 = private unnamed_addr constant [7 x i8] c"_ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK-NEXT: @"OBJC_IVAR_$_C2._ivar4" = hidden constant i32 24, section "__DATA, __objc_ivar", align 4 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.23 = private unnamed_addr constant [7 x i8] c"_ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_$_INSTANCE_VARIABLES_C2" = internal global { i32, i32, [3 x %struct._ivar_t] } { i32 32, i32 3, [3 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar1", ptr @OBJC_METH_VAR_NAME_.20, ptr @OBJC_METH_VAR_TYPE_.21, i32 3, i32 8 }, %struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar3", ptr @OBJC_METH_VAR_NAME_.22, ptr @OBJC_METH_VAR_TYPE_.21, i32 3, i32 8 }, %struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar4", ptr @OBJC_METH_VAR_NAME_.23, ptr @OBJC_METH_VAR_TYPE_.21, i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.24 = private unnamed_addr constant [6 x i8] c"ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.25 = private unnamed_addr constant [11 x i8] c"T@,V_ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.26 = private unnamed_addr constant [6 x i8] c"ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.27 = private unnamed_addr constant [11 x i8] c"T@,V_ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.28 = private unnamed_addr constant [6 x i8] c"ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.29 = private unnamed_addr constant [11 x i8] c"T@,V_ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_$_PROP_LIST_C2" = internal global { i32, i32, [3 x %struct._prop_t] } { i32 16, i32 3, [3 x %struct._prop_t] [%struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.24, ptr @OBJC_PROP_NAME_ATTR_.25 }, %struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.26, ptr @OBJC_PROP_NAME_ATTR_.27 }, %struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.28, ptr @OBJC_PROP_NAME_ATTR_.29 }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C2" = internal global %struct._class_ro_t { i32 0, i32 8, i32 32, ptr null, ptr @OBJC_CLASS_NAME_.11, ptr @"_OBJC_$_INSTANCE_METHODS_C2", ptr null, ptr @"_OBJC_$_INSTANCE_VARIABLES_C2", ptr null, ptr @"_OBJC_$_PROP_LIST_C2" }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.25 = private unnamed_addr constant [7 x i8] c"_ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_INSTANCE_VARIABLES_C2" = internal global { i32, i32, [3 x %struct._ivar_t] } { i32 32, i32 3, [3 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar1", ptr @OBJC_METH_VAR_NAME_.22, ptr @OBJC_METH_VAR_TYPE_.23, i32 3, i32 8 }, %struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar3", ptr @OBJC_METH_VAR_NAME_.24, ptr @OBJC_METH_VAR_TYPE_.23, i32 3, i32 8 }, %struct._ivar_t { ptr @"OBJC_IVAR_$_C2._ivar4", ptr @OBJC_METH_VAR_NAME_.25, ptr @OBJC_METH_VAR_TYPE_.23, i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.26 = private unnamed_addr constant [6 x i8] c"ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.27 = private unnamed_addr constant [13 x i8] c"T@,&,V_ivar1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.28 = private unnamed_addr constant [6 x i8] c"ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.29 = private unnamed_addr constant [13 x i8] c"T@,&,V_ivar3\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.30 = private unnamed_addr constant [6 x i8] c"ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_PROP_NAME_ATTR_.31 = private unnamed_addr constant [13 x i8] c"T@,&,V_ivar4\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_PROP_LIST_C2" = internal global { i32, i32, [3 x %struct._prop_t] } { i32 16, i32 3, [3 x %struct._prop_t] [%struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.26, ptr @OBJC_PROP_NAME_ATTR_.27 }, %struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.28, ptr @OBJC_PROP_NAME_ATTR_.29 }, %struct._prop_t { ptr @OBJC_PROP_NAME_ATTR_.30, ptr @OBJC_PROP_NAME_ATTR_.31 }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C2" = internal global %struct._class_ro_t { i32 388, i32 8, i32 32, ptr @OBJC_CLASS_NAME_.12, ptr @OBJC_CLASS_NAME_.11, ptr @"_OBJC_$_INSTANCE_METHODS_C2", ptr null, ptr @"_OBJC_$_INSTANCE_VARIABLES_C2", ptr null, ptr @"_OBJC_$_PROP_LIST_C2" }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"OBJC_CLASS_$_C2" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C2", ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_CLASS_RO_$_C2" }, section "__DATA, __objc_data", align 8 -// CHECK-NEXT: @OBJC_CLASS_NAME_.30 = private unnamed_addr constant [3 x i8] c"C3\00", section "__TEXT,__objc_classname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.31 = private unnamed_addr constant [4 x i8] c"cm0\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_$_CLASS_METHODS_C3" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.31, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01+[C3 cm0]" }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @OBJC_CLASS_NAME_.32 = private unnamed_addr constant [3 x i8] c"P1\00", section "__TEXT,__objc_classname,cstring_literals", align 1 -// CHECK-NEXT: @OBJC_METH_VAR_NAME_.33 = private unnamed_addr constant [6 x i8] c"p1_m1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK-NEXT: @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P1" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.33, ptr @OBJC_METH_VAR_TYPE_, ptr null }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_CLASS_NAME_.32 = private unnamed_addr constant [3 x i8] c"C3\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.33 = private unnamed_addr constant [4 x i8] c"cm0\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_CLASS_METHODS_C3" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.33, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01+[C3 cm0]" }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_CLASS_NAME_.34 = private unnamed_addr constant [3 x i8] c"P1\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.35 = private unnamed_addr constant [6 x i8] c"p1_m1\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P1" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.35, ptr @OBJC_METH_VAR_TYPE_, ptr null }] }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1" = internal global [1 x ptr] [ptr @OBJC_METH_VAR_TYPE_], section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_PROTOCOL_$_P1" = weak hidden global %struct._protocol_t { ptr null, ptr @OBJC_CLASS_NAME_.32, ptr null, ptr @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P1", ptr null, ptr null, ptr null, ptr null, i32 96, i32 0, ptr @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1", ptr null, ptr null }, align 8 +// CHECK-NEXT: @"_OBJC_PROTOCOL_$_P1" = weak hidden global %struct._protocol_t { ptr null, ptr @OBJC_CLASS_NAME_.34, ptr null, ptr @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_P1", ptr null, ptr null, ptr null, ptr null, i32 96, i32 0, ptr @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1", ptr null, ptr null }, align 8 // CHECK-NEXT: @"_OBJC_LABEL_PROTOCOL_$_P1" = weak hidden global ptr @"_OBJC_PROTOCOL_$_P1", section "__DATA,__objc_protolist,coalesced,no_dead_strip", align 8 // CHECK-NEXT: @"_OBJC_CLASS_PROTOCOLS_$_C3" = internal global { i64, [2 x ptr] } { i64 1, [2 x ptr] [ptr @"_OBJC_PROTOCOL_$_P1", ptr null] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C3" = internal global %struct._class_ro_t { i32 1, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_.30, ptr @"_OBJC_$_CLASS_METHODS_C3", ptr @"_OBJC_CLASS_PROTOCOLS_$_C3", ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C3" = internal global %struct._class_ro_t { i32 129, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_.32, ptr @"_OBJC_$_CLASS_METHODS_C3", ptr @"_OBJC_CLASS_PROTOCOLS_$_C3", ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"OBJC_METACLASS_$_C3" = global %struct._class_t { ptr @"OBJC_METACLASS_$_NSObject", ptr @"OBJC_METACLASS_$_NSObject", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_METACLASS_RO_$_C3" }, section "__DATA, __objc_data", align 8 -// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C3" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.33, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C3 p1_m1]" }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C3" = internal global %struct._class_ro_t { i32 0, i32 8, i32 8, ptr null, ptr @OBJC_CLASS_NAME_.30, ptr @"_OBJC_$_INSTANCE_METHODS_C3", ptr @"_OBJC_CLASS_PROTOCOLS_$_C3", ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C3" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.35, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C3 p1_m1]" }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C3" = internal global %struct._class_ro_t { i32 128, i32 8, i32 8, ptr null, ptr @OBJC_CLASS_NAME_.32, ptr @"_OBJC_$_INSTANCE_METHODS_C3", ptr @"_OBJC_CLASS_PROTOCOLS_$_C3", ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 // CHECK-NEXT: @"OBJC_CLASS_$_C3" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C3", ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_CLASS_RO_$_C3" }, section "__DATA, __objc_data", align 8 -// CHECK-NEXT: @OBJC_CLASS_NAME_.34 = private unnamed_addr constant [5 x i8] c"cat3\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @OBJC_CLASS_NAME_.36 = private unnamed_addr constant [5 x i8] c"cat3\00", section "__TEXT,__objc_classname,cstring_literals", align 1 // CHECK-NEXT: @"_OBJC_$_CATEGORY_INSTANCE_METHODS_C3_$_cat3" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.1, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C3(cat3) m1]" }] }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"_OBJC_$_CATEGORY_C3_$_cat3" = internal global %struct._category_t { ptr @OBJC_CLASS_NAME_.34, ptr @"OBJC_CLASS_$_C3", ptr @"_OBJC_$_CATEGORY_INSTANCE_METHODS_C3_$_cat3", ptr null, ptr null, ptr null, ptr null, i32 64 }, section "__DATA, __objc_const", align 8 -// CHECK-NEXT: @"OBJC_LABEL_CLASS_$" = private global [3 x ptr] [ptr @"OBJC_CLASS_$_C0", ptr @"OBJC_CLASS_$_C2", ptr @"OBJC_CLASS_$_C3"], section "__DATA,__objc_classlist,regular,no_dead_strip", align 8 +// CHECK-NEXT: @"_OBJC_$_CATEGORY_C3_$_cat3" = internal global %struct._category_t { ptr @OBJC_CLASS_NAME_.36, ptr @"OBJC_CLASS_$_C3", ptr @"_OBJC_$_CATEGORY_INSTANCE_METHODS_C3_$_cat3", ptr null, ptr null, ptr null, ptr null, i32 64 }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"OBJC_IVAR_$_C5.ivar6" = global i32 8, section "__DATA, __objc_ivar", align 4 +// CHECK-NEXT: @"OBJC_METACLASS_$_C4" = external global %struct._class_t +// CHECK-NEXT: @OBJC_CLASS_NAME_.37 = private unnamed_addr constant [3 x i8] c"C5\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_METACLASS_RO_$_C5" = internal global %struct._class_ro_t { i32 389, i32 40, i32 40, ptr null, ptr @OBJC_CLASS_NAME_.37, ptr null, ptr null, ptr null, ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"OBJC_METACLASS_$_C5" = global %struct._class_t { ptr @"OBJC_METACLASS_$_NSObject", ptr @"OBJC_METACLASS_$_C4", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_METACLASS_RO_$_C5" }, section "__DATA, __objc_data", align 8 +// CHECK-NEXT: @"OBJC_CLASS_$_C4" = external global %struct._class_t +// CHECK-NEXT: @OBJC_CLASS_NAME_.38 = private unnamed_addr constant [2 x i8] c"\01\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C5" = internal global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_.21, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C5 .cxx_destruct]" }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @OBJC_METH_VAR_NAME_.39 = private unnamed_addr constant [6 x i8] c"ivar6\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +// CHECK-NEXT: @"_OBJC_$_INSTANCE_VARIABLES_C5" = internal global { i32, i32, [1 x %struct._ivar_t] } { i32 32, i32 1, [1 x %struct._ivar_t] [%struct._ivar_t { ptr @"OBJC_IVAR_$_C5.ivar6", ptr @OBJC_METH_VAR_NAME_.39, ptr @OBJC_METH_VAR_TYPE_.23, i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"_OBJC_CLASS_RO_$_C5" = internal global %struct._class_ro_t { i32 388, i32 8, i32 16, ptr @OBJC_CLASS_NAME_.38, ptr @OBJC_CLASS_NAME_.37, ptr @"_OBJC_$_INSTANCE_METHODS_C5", ptr null, ptr @"_OBJC_$_INSTANCE_VARIABLES_C5", ptr null, ptr null }, section "__DATA, __objc_const", align 8 +// CHECK-NEXT: @"OBJC_CLASS_$_C5" = global %struct._class_t { ptr @"OBJC_METACLASS_$_C5", ptr @"OBJC_CLASS_$_C4", ptr @_objc_empty_cache, ptr @_objc_empty_vtable, ptr @"_OBJC_CLASS_RO_$_C5" }, section "__DATA, __objc_data", align 8 +// CHECK-NEXT: @"OBJC_LABEL_CLASS_$" = private global [4 x ptr] [ptr @"OBJC_CLASS_$_C0", ptr @"OBJC_CLASS_$_C2", ptr @"OBJC_CLASS_$_C3", ptr @"OBJC_CLASS_$_C5"], section "__DATA,__objc_classlist,regular,no_dead_strip", align 8 // CHECK-NEXT: @"OBJC_LABEL_CATEGORY_$" = private global [1 x ptr] [ptr @"_OBJC_$_CATEGORY_C3_$_cat3"], section "__DATA,__objc_catlist,regular,no_dead_strip", align 8 @interface NSObject { @@ -158,38 +172,47 @@ @interface C2 : NSObject @property id ivar4; @end -// CHECK: define internal ptr @"\01-[C2 ivar1]"(ptr noundef %[[SELF:.*]], ptr noundef %{{.*}}) -// CHECK: %[[RETVAL:.*]] = alloca ptr, align 8 +// CHECK: define internal ptr @"\01-[C2 ivar1]"(ptr noundef %[[SELF:.*]], ptr noundef %[[CMD:.*]]) // CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[SELF:.*]], ptr %[[SELF_ADDR]], align 8 +// CHECK: %[[CMD_ADDR:.*]] = alloca ptr, align 8 +// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8 +// CHECK: store ptr %[[CMD]], ptr %[[CMD_ADDR]], align 8 +// CHECK: %[[CMD:.*]] = load ptr, ptr %[[CMD_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8 -// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 8 -// CHECK: %[[LOAD:.*]] = load atomic i64, ptr %[[ADD_PTR]] unordered, align 8 -// CHECK: store i64 %[[LOAD]], ptr %[[RETVAL]], align 8 -// CHECK: %[[V1:.*]] = load ptr, ptr %[[RETVAL]], align 8 -// CHECK: ret ptr %[[V1]] - -// CHECK: define internal ptr @"\01-[C2 ivar3]"(ptr noundef %[[SELF:.*]], ptr noundef %{{.*}}) -// CHECK: %[[RETVAL:.*]] = alloca ptr, align 8 +// CHECK: %[[CALL:.*]] = tail call ptr @objc_getProperty(ptr noundef %[[V0]], ptr noundef %[[CMD]], i64 noundef 8, i1 noundef true) +// CHECK: ret ptr %[[CALL]] + +// CHECK: define internal ptr @"\01-[C2 ivar3]"(ptr noundef %[[SELF:.*]], ptr noundef %[[CMD:.*]]) +// CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8 +// CHECK: %[[CMD_ADDR:.*]] = alloca ptr, align 8 +// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8 +// CHECK: store ptr %[[CMD]], ptr %[[CMD_ADDR]], align 8 +// CHECK: %[[CMD:.*]] = load ptr, ptr %[[CMD_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8 +// CHECK: %[[CALL:.*]] = tail call ptr @objc_getProperty(ptr noundef %[[V0]], ptr noundef %[[CMD]], i64 noundef 16, i1 noundef true) +// CHECK: ret ptr %[[CALL]] + +// CHECK: define internal ptr @"\01-[C2 ivar4]"(ptr noundef %[[SELF:.*]], ptr noundef %[[CMD:.*]]) // CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[SELF:.*]], ptr %[[SELF_ADDR]], align 8 +// CHECK: %[[CMD_ADDR:.*]] = alloca ptr, align 8 +// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8 +// CHECK: store ptr %[[CMD]], ptr %[[CMD_ADDR]], align 8 +// CHECK: %[[CMD:.*]] = load ptr, ptr %[[CMD_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8 -// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 16 -// CHECK: %[[LOAD:.*]] = load atomic i64, ptr %[[ADD_PTR]] unordered, align 8 -// CHECK: store i64 %[[LOAD]], ptr %[[RETVAL]], align 8 -// CHECK: %[[V1:.*]] = load ptr, ptr %[[RETVAL]], align 8 -// CHECK: ret ptr %[[V1]] - -// CHECK: define internal ptr @"\01-[C2 ivar4]"(ptr noundef %[[SELF:.*]], ptr noundef %{{.*}}) -// CHECK: %[[RETVAL:.*]] = alloca ptr, align 8 +// CHECK: %[[CALL:.*]] = tail call ptr @objc_getProperty(ptr noundef %[[V0]], ptr noundef %[[CMD]], i64 noundef 24, i1 noundef true) +// CHECK: ret ptr %[[CALL]] + +// CHECK: define internal void @"\01-[C5 .cxx_destruct]"(ptr noundef %[[SELF:.*]], ptr noundef %[[CMD:.*]]) // CHECK: %[[SELF_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[SELF:.*]], ptr %[[SELF_ADDR]], align 8 +// CHECK: %[[CMD_ADDR:.*]] = alloca ptr, align 8 +// CHECK: store ptr %[[SELF]], ptr %[[SELF_ADDR]], align 8 +// CHECK: store ptr %[[CMD]], ptr %[[CMD_ADDR]], align 8 // CHECK: %[[V0:.*]] = load ptr, ptr %[[SELF_ADDR]], align 8 -// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 24 -// CHECK: %[[LOAD:.*]] = load atomic i64, ptr %[[ADD_PTR]] unordered, align 8 -// CHECK: store i64 %[[LOAD]], ptr %[[RETVAL]], align 8 -// CHECK: %[[V1:.*]] = load ptr, ptr %[[RETVAL]], align 8 -// CHECK: ret ptr %[[V1]] +// CHECK: %[[IVAR:.*]] = load i32, ptr @"OBJC_IVAR_$_C5.ivar6", align 8 +// CHECK: %[[IVAR_CONV:.*]] = sext i32 %[[IVAR]] to i64 +// CHECK: %[[ADD_PTR:.*]] = getelementptr inbounds i8, ptr %[[V0]], i64 %[[IVAR_CONV]] +// CHECK: call void @llvm.objc.storeStrong(ptr %[[ADD_PTR]], ptr null) +// CHECK: ret void @implementation C2 @end @@ -229,3 +252,15 @@ -(void)unavailable_m0 { -(void)m1 { } @end + +@interface C4 : NSObject +@end + +@interface C5 : C4 { + id unavailable_ivar5 __attribute__((availability(domain:feature2, AVAIL))); + id ivar6; +} +@end + +@implementation C5 +@end