Skip to content

Commit 3c787d5

Browse files
committed
[lld-macho] Don't emit spurious dupe method warnings for +load methods
+load methods are static initializers and treated specially by the runtime: all +load methods for a class & its categories are called when loading that class, unlike regular methods where only one definition will get called per message. Thus, there is no need to check for duplicates. Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D147230
1 parent 96d0875 commit 3c787d5

File tree

2 files changed

+62
-8
lines changed

2 files changed

+62
-8
lines changed

lld/MachO/ObjC.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,19 @@ void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
197197
continue;
198198

199199
CachedHashStringRef methodName(getReferentString(r));
200+
// +load methods are special: all implementations are called by the runtime
201+
// even if they are part of the same class. Thus there is no need to check
202+
// for duplicates.
203+
// NOTE: Instead of specifically checking for this method name, ld64 simply
204+
// checks whether a class / category is present in __objc_nlclslist /
205+
// __objc_nlcatlist respectively. This will be the case if the class /
206+
// category has a +load method. It skips optimizing the categories if there
207+
// are multiple +load methods. Since it does dupe checking as part of the
208+
// optimization process, this avoids spurious dupe messages around +load,
209+
// but it also means that legit dupe issues for other methods are ignored.
210+
if (mKind == MK_Static && methodName.val() == "load")
211+
continue;
212+
200213
auto &methodMap =
201214
mKind == MK_Instance ? klass.instanceMethods : klass.classMethods;
202215
if (methodMap

lld/test/MachO/objc-category-conflicts.s

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
44
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
55
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat1-with-load.o
7+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat2-with-load.o
8+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s --defsym MAKE_LOAD_METHOD=1 -o %t/klass-with-load.o
69
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass-with-no-rodata.s -o %t/klass-with-no-rodata.o
710
# RUN: %lld -dylib -lobjc %t/klass.o -o %t/libklass.dylib
811

@@ -11,24 +14,32 @@
1114
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/libklass.dylib %t/cat1.o \
1215
# RUN: %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT
1316

17+
## Check that we don't emit spurious warnings around the +load method while
18+
## still emitting the other warnings. Note that we have made separate
19+
## `*-with-load.s` files for ease of comparison with ld64; ld64 will not warn
20+
## at all if multiple +load methods are present.
21+
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass-with-load.o \
22+
# RUN: %t/cat1-with-load.o %t/cat2-with-load.o -o /dev/null 2>&1 | \
23+
# RUN: FileCheck %s --check-prefixes=CATCLS,CATCAT --implicit-check-not '+load'
24+
1425
## Regression test: Check that we don't crash.
1526
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null
1627

1728
# CATCLS: warning: method '+s1' has conflicting definitions:
18-
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
19-
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
29+
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
30+
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o
2031

2132
# CATCLS: warning: method '-m1' has conflicting definitions:
22-
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
23-
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
33+
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
34+
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o
2435

2536
# CATCAT: warning: method '+s2' has conflicting definitions:
26-
# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2.o
27-
# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
37+
# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o
38+
# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
2839

2940
# CATCAT: warning: method '-m2' has conflicting definitions:
30-
# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2.o
31-
# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
41+
# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o
42+
# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
3243

3344
#--- cat1.s
3445

@@ -51,6 +62,11 @@
5162
.section __DATA,__objc_catlist,regular,no_dead_strip
5263
.quad __OBJC_$_CATEGORY_Foo_$_Cat1
5364

65+
.ifdef MAKE_LOAD_METHOD
66+
.section __DATA,__objc_nlcatlist,regular,no_dead_strip
67+
.quad __OBJC_$_CATEGORY_Foo_$_Cat1
68+
.endif
69+
5470
.section __DATA,__objc_const
5571
__OBJC_$_CATEGORY_Foo_$_Cat1:
5672
.objc_classname "Cat1"
@@ -71,7 +87,12 @@ __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1:
7187

7288
__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1:
7389
.long 24
90+
.ifdef MAKE_LOAD_METHOD
91+
.long 3
92+
.empty_objc_method "load", "v16@0:8", "+[Foo(Cat1) load]"
93+
.else
7494
.long 2
95+
.endif
7596
.empty_objc_method "s1", "v16@0:8", "+[Foo(Cat1) s1]"
7697
.empty_objc_method "s2", "v16@0:8", "+[Foo(Cat1) s2]"
7798

@@ -98,6 +119,11 @@ __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1:
98119
.section __DATA,__objc_catlist,regular,no_dead_strip
99120
.quad __OBJC_$_CATEGORY_Foo_$_Cat2
100121

122+
.ifdef MAKE_LOAD_METHOD
123+
.section __DATA,__objc_nlcatlist,regular,no_dead_strip
124+
.quad __OBJC_$_CATEGORY_Foo_$_Cat2
125+
.endif
126+
101127
.section __DATA,__objc_const
102128
__OBJC_$_CATEGORY_Foo_$_Cat2:
103129
.objc_classname "Cat2"
@@ -117,7 +143,12 @@ __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2:
117143

118144
__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2:
119145
.long 24
146+
.ifdef MAKE_LOAD_METHOD
147+
.long 2
148+
.empty_objc_method "load", "v16@0:8", "+[Foo(Cat2) load]"
149+
.else
120150
.long 1
151+
.endif
121152
.empty_objc_method "s2", "v16@0:8", "+[Foo(Cat2) m2]"
122153

123154
.section __DATA,__objc_imageinfo,regular,no_dead_strip
@@ -186,7 +217,12 @@ __OBJC_CLASS_RO_$_Foo:
186217

187218
__OBJC_$_CLASS_METHODS_Foo:
188219
.long 24
220+
.ifdef MAKE_LOAD_METHOD
221+
.long 2
222+
.empty_objc_method "load", "v16@0:8", "+[Foo load]"
223+
.else
189224
.long 1
225+
.endif
190226
.empty_objc_method "s1", "v16@0:8", "+[Foo s1]"
191227

192228
__OBJC_$_INSTANCE_METHODS_Foo:
@@ -197,6 +233,11 @@ __OBJC_$_INSTANCE_METHODS_Foo:
197233
.section __DATA,__objc_classlist,regular,no_dead_strip
198234
.quad _OBJC_CLASS_$_Foo
199235

236+
.ifdef MAKE_LOAD_METHOD
237+
.section __DATA,__objc_nlclslist,regular,no_dead_strip
238+
.quad _OBJC_CLASS_$_Foo
239+
.endif
240+
200241
.section __DATA,__objc_imageinfo,regular,no_dead_strip
201242
.long 0
202243
.long 64

0 commit comments

Comments
 (0)