Skip to content

Commit dec20e1

Browse files
authored
Merge pull request #11094 from tshortli/feature-availability-unavailable-methods-codegen-20240723
[stable/20240723] Skip adding unavailable methods to method lists during CodeGen
2 parents 35b08aa + 72dea13 commit dec20e1

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

clang/lib/CodeGen/CGObjCMac.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,8 +1173,11 @@ class ProtocolMethodLists {
11731173

11741174
static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
11751175
ProtocolMethodLists result;
1176+
ASTContext &Ctx = PD->getASTContext();
11761177

11771178
for (auto *MD : PD->methods()) {
1179+
if (Ctx.hasUnavailableFeature(MD))
1180+
continue;
11781181
size_t index = (2 * size_t(MD->isOptional()))
11791182
+ (size_t(MD->isClassMethod()));
11801183
result.Methods[index].push_back(MD);
@@ -3339,6 +3342,7 @@ CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name,
33393342
};
33403343
*/
33413344
void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
3345+
ASTContext &Ctx = CGM.getContext();
33423346
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
33433347

33443348
// FIXME: This is poor design, the OCD should have a pointer to the category
@@ -3363,6 +3367,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
33633367
};
33643368
SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
33653369
for (const auto *MD : OCD->methods()) {
3370+
if (Ctx.hasUnavailableFeature(MD))
3371+
continue;
33663372
if (!MD->isDirectMethod())
33673373
Methods[unsigned(MD->isClassMethod())].push_back(MD);
33683374
}
@@ -3509,6 +3515,7 @@ static bool hasMRCWeakIvars(CodeGenModule &CGM,
35093515
See EmitClassExtension();
35103516
*/
35113517
void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
3518+
ASTContext &Ctx = CGM.getContext();
35123519
IdentifierInfo *RuntimeName =
35133520
&CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
35143521
DefinedSymbols.insert(RuntimeName);
@@ -3546,6 +3553,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
35463553
};
35473554
SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
35483555
for (const auto *MD : ID->methods()) {
3556+
if (Ctx.hasUnavailableFeature(MD))
3557+
continue;
35493558
if (!MD->isDirectMethod())
35503559
Methods[unsigned(MD->isClassMethod())].push_back(MD);
35513560
}
@@ -6314,6 +6323,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
63146323
CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
63156324
CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
63166325

6326+
ASTContext &Ctx = CGM.getContext();
63176327
bool hasMRCWeak = false;
63186328
if (CGM.getLangOpts().ObjCAutoRefCount)
63196329
flags |= NonFragileABI_Class_CompiledByARC;
@@ -6334,13 +6344,21 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
63346344
// const struct _method_list_t * const baseMethods;
63356345
SmallVector<const ObjCMethodDecl*, 16> methods;
63366346
if (flags & NonFragileABI_Class_Meta) {
6337-
for (const auto *MD : ID->class_methods())
6338-
if (!MD->isDirectMethod())
6339-
methods.push_back(MD);
6347+
for (const auto *MD : ID->class_methods()) {
6348+
if (Ctx.hasUnavailableFeature(MD))
6349+
continue;
6350+
if (MD->isDirectMethod())
6351+
continue;
6352+
methods.push_back(MD);
6353+
}
63406354
} else {
6341-
for (const auto *MD : ID->instance_methods())
6342-
if (!MD->isDirectMethod())
6343-
methods.push_back(MD);
6355+
for (const auto *MD : ID->instance_methods()) {
6356+
if (Ctx.hasUnavailableFeature(MD))
6357+
continue;
6358+
if (MD->isDirectMethod())
6359+
continue;
6360+
methods.push_back(MD);
6361+
}
63446362
}
63456363

63466364
values.add(emitMethodList(ID->getObjCRuntimeNameAsString(),
@@ -6643,6 +6661,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
66436661
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
66446662
const char *Prefix = "_OBJC_$_CATEGORY_";
66456663

6664+
ASTContext &Ctx = CGM.getContext();
66466665
llvm::SmallString<64> ExtCatName(Prefix);
66476666
ExtCatName += Interface->getObjCRuntimeNameAsString();
66486667
ExtCatName += "_$_";
@@ -6659,6 +6678,8 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
66596678
SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
66606679
SmallVector<const ObjCMethodDecl *, 8> classMethods;
66616680
for (const auto *MD : OCD->methods()) {
6681+
if (Ctx.hasUnavailableFeature(MD))
6682+
continue;
66626683
if (MD->isDirectMethod())
66636684
continue;
66646685
if (MD->isInstanceMethod()) {
@@ -6744,8 +6765,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
67446765
void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
67456766
const ObjCMethodDecl *MD,
67466767
bool forProtocol) {
6747-
if (CGM.getContext().hasUnavailableFeature(MD))
6748-
return;
6768+
assert(!CGM.getContext().hasUnavailableFeature(MD));
67496769

67506770
auto method = builder.beginStruct(ObjCTypes.MethodTy);
67516771
method.add(GetMethodVarName(MD->getSelector()));

clang/test/CodeGenObjC/feature-availability.m

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.3 = private unnamed_addr constant [8 x i8] c"i16@0:8\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
2828
// CHECK-NEXT: @OBJC_METH_VAR_NAME_.4 = private unnamed_addr constant [10 x i8] c"setProp0:\00", section "__TEXT,__objc_methname,cstring_literals", align 1
2929
// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.5 = private unnamed_addr constant [11 x i8] c"v20@0:8i16\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
30-
// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C0" = internal global { i32, i32, [4 x %struct._objc_method] } { i32 24, i32 7, [4 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C0 m0]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.1, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C0 m1]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.2, ptr @OBJC_METH_VAR_TYPE_.3, ptr @"\01-[C0 prop0]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.4, ptr @OBJC_METH_VAR_TYPE_.5, ptr @"\01-[C0 setProp0:]" }] }, section "__DATA, __objc_const", align 8
30+
// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C0" = internal global { i32, i32, [4 x %struct._objc_method] } { i32 24, i32 4, [4 x %struct._objc_method] [%struct._objc_method { ptr @OBJC_METH_VAR_NAME_, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C0 m0]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.1, ptr @OBJC_METH_VAR_TYPE_, ptr @"\01-[C0 m1]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.2, ptr @OBJC_METH_VAR_TYPE_.3, ptr @"\01-[C0 prop0]" }, %struct._objc_method { ptr @OBJC_METH_VAR_NAME_.4, ptr @OBJC_METH_VAR_TYPE_.5, ptr @"\01-[C0 setProp0:]" }] }, section "__DATA, __objc_const", align 8
3131
// CHECK-NEXT: @"OBJC_IVAR_$_C0.ivar0" = global i32 0, section "__DATA, __objc_ivar", align 4
3232
// CHECK-NEXT: @OBJC_METH_VAR_NAME_.6 = private unnamed_addr constant [6 x i8] c"ivar0\00", section "__TEXT,__objc_methname,cstring_literals", align 1
3333
// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.7 = private unnamed_addr constant [2 x i8] c"i\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
@@ -51,7 +51,7 @@
5151
// 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
5252
// 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
5353
// 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
54-
// CHECK-NEXT: @"_OBJC_$_INSTANCE_METHODS_C2" = internal global { i32, i32, [6 x %struct._objc_method] } { i32 24, i32 8, [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
54+
// 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
5555
// CHECK-NEXT: @"OBJC_IVAR_$_C2._ivar1" = hidden constant i32 8, section "__DATA, __objc_ivar", align 4
5656
// 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
5757
// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.21 = private unnamed_addr constant [2 x i8] c"@\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
@@ -69,7 +69,26 @@
6969
// 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
7070
// 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
7171
// 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
72-
// CHECK: @"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
72+
// CHECK-NEXT: @OBJC_CLASS_NAME_.30 = private unnamed_addr constant [3 x i8] c"C3\00", section "__TEXT,__objc_classname,cstring_literals", align 1
73+
// 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
74+
// 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
75+
// CHECK-NEXT: @OBJC_CLASS_NAME_.32 = private unnamed_addr constant [3 x i8] c"P1\00", section "__TEXT,__objc_classname,cstring_literals", align 1
76+
// 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
77+
// 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
78+
// CHECK-NEXT: @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1" = internal global [1 x ptr] [ptr @OBJC_METH_VAR_TYPE_], section "__DATA, __objc_const", align 8
79+
// 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
80+
// CHECK-NEXT: @"_OBJC_LABEL_PROTOCOL_$_P1" = weak hidden global ptr @"_OBJC_PROTOCOL_$_P1", section "__DATA,__objc_protolist,coalesced,no_dead_strip", align 8
81+
// 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
82+
// 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
83+
// 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
84+
// 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
85+
// 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
86+
// 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
87+
// CHECK-NEXT: @OBJC_CLASS_NAME_.34 = private unnamed_addr constant [5 x i8] c"cat3\00", section "__TEXT,__objc_classname,cstring_literals", align 1
88+
// 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
89+
// 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
90+
// 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
91+
// 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
7392

7493
@interface NSObject {
7594
id a;
@@ -173,9 +192,38 @@ @interface C2 : NSObject
173192
@implementation C2
174193
@end
175194

176-
@interface C3 : NSObject
195+
@protocol P1
196+
-(void)p1_m1;
197+
-(void)unavailable_p2_m2 __attribute__((availability(___domain:feature2, AVAIL)));
198+
@end
199+
200+
@interface C3 : NSObject <P1>
177201
@property id prop0 __attribute__((availability(___domain:feature2, AVAIL)));
202+
+(void)cm0;
203+
+(void)unavailable_cm1 __attribute__((availability(___domain:feature2, AVAIL)));
178204
@end
179205

180206
@implementation C3
207+
-(void)p1_m1 {
208+
}
209+
-(void)unavailable_p2_m2 {
210+
unavailable_func1();
211+
}
212+
+(void)cm0 {
213+
}
214+
+(void)unavailable_cm1 {
215+
unavailable_func1();
216+
}
217+
@end
218+
219+
@interface C3(cat3)
220+
-(void)unavailable_m0 __attribute__((availability(___domain:feature2, AVAIL)));
221+
-(void)m1;
222+
@end
223+
224+
@implementation C3(cat3)
225+
-(void)unavailable_m0 {
226+
}
227+
-(void)m1 {
228+
}
181229
@end

0 commit comments

Comments
 (0)