Skip to content

Commit cfb22e2

Browse files
authored
Merge pull request #11151 from tshortli/feature-availability-unavailable-methods-codegen-21.x
[stable/21.x] Skip adding unavailable methods to method lists during CodeGen
2 parents 4b00780 + db4032f commit cfb22e2

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
@@ -1127,8 +1127,11 @@ class ProtocolMethodLists {
11271127

11281128
static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
11291129
ProtocolMethodLists result;
1130+
ASTContext &Ctx = PD->getASTContext();
11301131

11311132
for (auto *MD : PD->methods()) {
1133+
if (Ctx.hasUnavailableFeature(MD))
1134+
continue;
11321135
size_t index =
11331136
(2 * size_t(MD->isOptional())) + (size_t(MD->isClassMethod()));
11341137
result.Methods[index].push_back(MD);
@@ -3240,6 +3243,7 @@ llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(
32403243
};
32413244
*/
32423245
void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
3246+
ASTContext &Ctx = CGM.getContext();
32433247
unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);
32443248

32453249
// FIXME: This is poor design, the OCD should have a pointer to the category
@@ -3260,6 +3264,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
32603264
enum { InstanceMethods, ClassMethods, NumMethodLists };
32613265
SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
32623266
for (const auto *MD : OCD->methods()) {
3267+
if (Ctx.hasUnavailableFeature(MD))
3268+
continue;
32633269
if (!MD->isDirectMethod())
32643270
Methods[unsigned(MD->isClassMethod())].push_back(MD);
32653271
}
@@ -3408,6 +3414,7 @@ static bool hasMRCWeakIvars(CodeGenModule &CGM,
34083414
See EmitClassExtension();
34093415
*/
34103416
void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
3417+
ASTContext &Ctx = CGM.getContext();
34113418
IdentifierInfo *RuntimeName =
34123419
&CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
34133420
DefinedSymbols.insert(RuntimeName);
@@ -3442,6 +3449,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
34423449
enum { InstanceMethods, ClassMethods, NumMethodLists };
34433450
SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
34443451
for (const auto *MD : ID->methods()) {
3452+
if (Ctx.hasUnavailableFeature(MD))
3453+
continue;
34453454
if (!MD->isDirectMethod())
34463455
Methods[unsigned(MD->isClassMethod())].push_back(MD);
34473456
}
@@ -6213,6 +6222,7 @@ llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
62136222
CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
62146223
CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);
62156224

6225+
ASTContext &Ctx = CGM.getContext();
62166226
bool hasMRCWeak = false;
62176227
if (CGM.getLangOpts().ObjCAutoRefCount)
62186228
flags |= NonFragileABI_Class_CompiledByARC;
@@ -6233,13 +6243,21 @@ llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
62336243
// const struct _method_list_t * const baseMethods;
62346244
SmallVector<const ObjCMethodDecl *, 16> methods;
62356245
if (flags & NonFragileABI_Class_Meta) {
6236-
for (const auto *MD : ID->class_methods())
6237-
if (!MD->isDirectMethod())
6238-
methods.push_back(MD);
6246+
for (const auto *MD : ID->class_methods()) {
6247+
if (Ctx.hasUnavailableFeature(MD))
6248+
continue;
6249+
if (MD->isDirectMethod())
6250+
continue;
6251+
methods.push_back(MD);
6252+
}
62396253
} else {
6240-
for (const auto *MD : ID->instance_methods())
6241-
if (!MD->isDirectMethod())
6242-
methods.push_back(MD);
6254+
for (const auto *MD : ID->instance_methods()) {
6255+
if (Ctx.hasUnavailableFeature(MD))
6256+
continue;
6257+
if (MD->isDirectMethod())
6258+
continue;
6259+
methods.push_back(MD);
6260+
}
62436261
}
62446262

62456263
llvm::Constant *MethListPtr = emitMethodList(
@@ -6550,6 +6568,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
65506568
const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
65516569
const char *Prefix = "_OBJC_$_CATEGORY_";
65526570

6571+
ASTContext &Ctx = CGM.getContext();
65536572
llvm::SmallString<64> ExtCatName(Prefix);
65546573
ExtCatName += Interface->getObjCRuntimeNameAsString();
65556574
ExtCatName += "_$_";
@@ -6566,6 +6585,8 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
65666585
SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
65676586
SmallVector<const ObjCMethodDecl *, 8> classMethods;
65686587
for (const auto *MD : OCD->methods()) {
6588+
if (Ctx.hasUnavailableFeature(MD))
6589+
continue;
65696590
if (MD->isDirectMethod())
65706591
continue;
65716592
if (MD->isInstanceMethod()) {
@@ -6663,8 +6684,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
66636684
void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
66646685
const ObjCMethodDecl *MD,
66656686
bool forProtocol) {
6666-
if (CGM.getContext().hasUnavailableFeature(MD))
6667-
return;
6687+
assert(!CGM.getContext().hasUnavailableFeature(MD));
66686688

66696689
auto method = builder.beginStruct(ObjCTypes.MethodTy);
66706690
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
@@ -24,7 +24,7 @@
2424
// 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
2525
// 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
2626
// 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
27-
// 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
27+
// 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
2828
// CHECK-NEXT: @"OBJC_IVAR_$_C0.ivar0" = constant i32 0, section "__DATA, __objc_ivar", align 4
2929
// 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
3030
// 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
@@ -49,7 +49,7 @@
4949
// 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
5050
// 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
5151
// 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
52-
// 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
52+
// 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
5353
// CHECK-NEXT: @"OBJC_IVAR_$_C2._ivar1" = hidden constant i32 8, section "__DATA, __objc_ivar", align 4
5454
// 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
5555
// CHECK-NEXT: @OBJC_METH_VAR_TYPE_.21 = private unnamed_addr constant [2 x i8] c"@\00", section "__TEXT,__objc_methtype,cstring_literals", align 1
@@ -67,7 +67,26 @@
6767
// 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
6868
// 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
6969
// 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
70-
// 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
70+
// CHECK-NEXT: @OBJC_CLASS_NAME_.30 = private unnamed_addr constant [3 x i8] c"C3\00", section "__TEXT,__objc_classname,cstring_literals", align 1
71+
// 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
72+
// 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
73+
// CHECK-NEXT: @OBJC_CLASS_NAME_.32 = private unnamed_addr constant [3 x i8] c"P1\00", section "__TEXT,__objc_classname,cstring_literals", align 1
74+
// 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
75+
// 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
76+
// CHECK-NEXT: @"_OBJC_$_PROTOCOL_METHOD_TYPES_P1" = internal global [1 x ptr] [ptr @OBJC_METH_VAR_TYPE_], section "__DATA, __objc_const", align 8
77+
// 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
78+
// CHECK-NEXT: @"_OBJC_LABEL_PROTOCOL_$_P1" = weak hidden global ptr @"_OBJC_PROTOCOL_$_P1", section "__DATA,__objc_protolist,coalesced,no_dead_strip", align 8
79+
// 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
80+
// 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
81+
// 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
82+
// 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
83+
// 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
84+
// 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
85+
// CHECK-NEXT: @OBJC_CLASS_NAME_.34 = private unnamed_addr constant [5 x i8] c"cat3\00", section "__TEXT,__objc_classname,cstring_literals", align 1
86+
// 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
87+
// 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
88+
// 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
89+
// 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
7190

7291
@interface NSObject {
7392
id a;
@@ -171,9 +190,38 @@ @interface C2 : NSObject
171190
@implementation C2
172191
@end
173192

174-
@interface C3 : NSObject
193+
@protocol P1
194+
-(void)p1_m1;
195+
-(void)unavailable_p2_m2 __attribute__((availability(domain:feature2, AVAIL)));
196+
@end
197+
198+
@interface C3 : NSObject <P1>
175199
@property id prop0 __attribute__((availability(domain:feature2, AVAIL)));
200+
+(void)cm0;
201+
+(void)unavailable_cm1 __attribute__((availability(domain:feature2, AVAIL)));
176202
@end
177203

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

0 commit comments

Comments
 (0)