xref: /llvm-project/lld/test/MachO/objc-category-conflicts.s (revision 89a1f144f3890d9bd8ab30537b36f8c18038719b)
1# REQUIRES: x86
2# RUN: rm -rf %t; split-file %s %t
3# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
5# 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 -g -o %t/cat1_w_sym.o
7# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -g -o %t/cat2_w_sym.o
8# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -g -o %t/klass_w_sym.o
9# 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
10# 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
11# 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
12# 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
13# RUN: %lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o -o %t/libklass.dylib
14
15# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \
16# RUN:   /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT
17# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1.o \
18# RUN:   %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT
19
20# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass_w_sym.o %t/cat1_w_sym.o %t/cat2_w_sym.o -o \
21# RUN:   /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS_W_SYM,CATCAT_W_SYM
22# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1_w_sym.o \
23# RUN:   %t/cat2_w_sym.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT_W_SYM
24
25## Check that we don't emit spurious warnings around the +load method while
26## still emitting the other warnings. Note that we have made separate
27## `*-with-load.s` files for ease of comparison with ld64; ld64 will not warn
28## at all if multiple +load methods are present.
29# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-load.o \
30# RUN:   %t/cat1-with-load.o %t/cat2-with-load.o -o /dev/null 2>&1 | \
31# RUN:   FileCheck %s --check-prefixes=CATCLS,CATCAT --implicit-check-not '+load'
32
33## Regression test: Check that we don't crash.
34# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null
35
36## Check that we don't emit any warnings without --check-category-conflicts.
37# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \
38# RUN:   /dev/null 2>&1 | FileCheck %s --implicit-check-not 'warning' --allow-empty
39
40# CATCLS:      warning: method '+s1' has conflicting definitions:
41# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
42# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o
43
44# CATCLS:      warning: method '-m1' has conflicting definitions:
45# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
46# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass{{.*}}.o
47
48# CATCAT:      warning: method '+s2' has conflicting definitions:
49# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o
50# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
51
52# CATCAT:      warning: method '-m2' has conflicting definitions:
53# CATCAT-NEXT: >>> defined in category Cat2 from {{.*}}cat2{{.*}}.o
54# CATCAT-NEXT: >>> defined in category Cat1 from {{.*}}cat1{{.*}}.o
55
56
57# CATCLS_W_SYM:      warning: method '+s1' has conflicting definitions:
58# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
59# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}})
60
61# CATCLS_W_SYM:      warning: method '-m1' has conflicting definitions:
62# CATCLS_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
63# CATCLS_W_SYM-NEXT: >>> defined in class Foo from {{.*}}klass_w_sym{{.*}}.o ({{.*}}klass.s{{.*}})
64
65# CATCAT_W_SYM:      warning: method '+s2' has conflicting definitions:
66# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}})
67# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
68
69# CATCAT_W_SYM:      warning: method '-m2' has conflicting definitions:
70# CATCAT_W_SYM-NEXT: >>> defined in category Cat2 from {{.*}}cat2_w_sym{{.*}}.o ({{.*}}cat2.s{{.*}})
71# CATCAT_W_SYM-NEXT: >>> defined in category Cat1 from {{.*}}cat1_w_sym{{.*}}.o ({{.*}}cat1.s{{.*}})
72
73
74#--- cat1.s
75
76.include "objc-macros.s"
77
78## @interface Foo(Cat1)
79## -(void) m1;
80## -(void) m2;
81## +(void) s1;
82## +(void) s2;
83## @end
84##
85## @implementation Foo(Cat1)
86## -(void) m1 {}
87## -(void) m2 {}
88## +(void) s1 {}
89## +(void) s2 {}
90## @end
91
92.section __DATA,__objc_catlist,regular,no_dead_strip
93  .quad __OBJC_$_CATEGORY_Foo_$_Cat1
94
95.ifdef MAKE_LOAD_METHOD
96.section __DATA,__objc_nlcatlist,regular,no_dead_strip
97  .quad __OBJC_$_CATEGORY_Foo_$_Cat1
98.endif
99
100.section __DATA,__objc_const
101__OBJC_$_CATEGORY_Foo_$_Cat1:
102  .objc_classname "Cat1"
103  .quad _OBJC_CLASS_$_Foo
104  .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1
105  .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1
106  .quad 0
107  .quad 0
108  .quad 0
109  .long 64
110  .space 4
111
112__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat1:
113  .long 24 # size of method entry
114  .long 2 # number of methods
115  .empty_objc_method "m1", "v16@0:8", "-[Foo(Cat1) m1]"
116  .empty_objc_method "m2", "v16@0:8", "-[Foo(Cat2) m2]"
117
118__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat1:
119  .long 24
120.ifdef MAKE_LOAD_METHOD
121  .long 3
122  .empty_objc_method "load", "v16@0:8", "+[Foo(Cat1) load]"
123.else
124  .long 2
125.endif
126  .empty_objc_method "s1", "v16@0:8", "+[Foo(Cat1) s1]"
127  .empty_objc_method "s2", "v16@0:8", "+[Foo(Cat1) s2]"
128
129.section __DATA,__objc_imageinfo,regular,no_dead_strip
130  .long 0
131  .long 64
132
133.subsections_via_symbols
134
135#--- cat2.s
136
137.include "objc-macros.s"
138
139## @interface Foo(Cat2)
140## -(void) m2;
141## +(void) s2;
142## @end
143##
144## @implementation Foo(Cat2)
145## -(void) m2 {}
146## +(void) s2 {}
147## @end
148
149.section __DATA,__objc_catlist,regular,no_dead_strip
150  .quad __OBJC_$_CATEGORY_Foo_$_Cat2
151
152.ifdef MAKE_LOAD_METHOD
153.section __DATA,__objc_nlcatlist,regular,no_dead_strip
154  .quad __OBJC_$_CATEGORY_Foo_$_Cat2
155.endif
156
157.section __DATA,__objc_const
158__OBJC_$_CATEGORY_Foo_$_Cat2:
159  .objc_classname "Cat2"
160  .quad _OBJC_CLASS_$_Foo
161  .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2
162  .quad __OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2
163  .quad 0
164  .quad 0
165  .quad 0
166  .long 64
167  .space 4
168
169__OBJC_$_CATEGORY_INSTANCE_METHODS_Foo_$_Cat2:
170  .long 24
171  .long 1
172  .empty_objc_method "m2", "v16@0:8", "-[Foo(Cat2) m2]"
173
174__OBJC_$_CATEGORY_CLASS_METHODS_Foo_$_Cat2:
175  .long 24
176.ifdef MAKE_LOAD_METHOD
177  .long 2
178  .empty_objc_method "load", "v16@0:8", "+[Foo(Cat2) load]"
179.else
180  .long 1
181.endif
182  .empty_objc_method "s2", "v16@0:8", "+[Foo(Cat2) m2]"
183
184.section __DATA,__objc_imageinfo,regular,no_dead_strip
185  .long 0
186  .long 64
187
188.subsections_via_symbols
189
190#--- klass.s
191
192.include "objc-macros.s"
193
194## @interface Foo
195## -(void) m1;
196## +(void) s1;
197## @end
198##
199## @implementation Foo
200## -(void) m1 {}
201## +(void) s1 {}
202## @end
203
204.globl _OBJC_CLASS_$_Foo, _OBJC_METACLASS_$_Foo
205
206.section __DATA,__objc_data
207_OBJC_CLASS_$_Foo:
208  .quad _OBJC_METACLASS_$_Foo
209  .quad 0
210  .quad __objc_empty_cache
211  .quad 0
212  .quad __OBJC_CLASS_RO_$_Foo
213
214_OBJC_METACLASS_$_Foo:
215  .quad _OBJC_METACLASS_$_Foo
216  .quad _OBJC_CLASS_$_Foo
217  .quad __objc_empty_cache
218  .quad 0
219  .quad __OBJC_METACLASS_RO_$_Foo
220
221.section __DATA,__objc_const
222__OBJC_METACLASS_RO_$_Foo:
223  .long 3
224  .long 40
225  .long 40
226  .space 4
227  .quad 0
228  .objc_classname "Foo"
229  .quad __OBJC_$_CLASS_METHODS_Foo
230  .quad 0
231  .quad 0
232  .quad 0
233  .quad 0
234
235__OBJC_CLASS_RO_$_Foo:
236  .long 2
237  .long 0
238  .long 0
239  .space 4
240  .quad 0
241  .objc_classname "Foo"
242  .quad __OBJC_$_INSTANCE_METHODS_Foo
243  .quad 0
244  .quad 0
245  .quad 0
246  .quad 0
247
248__OBJC_$_CLASS_METHODS_Foo:
249  .long 24
250.ifdef MAKE_LOAD_METHOD
251  .long 2
252  .empty_objc_method "load", "v16@0:8", "+[Foo load]"
253.else
254  .long 1
255.endif
256  .empty_objc_method "s1", "v16@0:8", "+[Foo s1]"
257
258__OBJC_$_INSTANCE_METHODS_Foo:
259  .long 24
260  .long 1
261  .empty_objc_method "m1", "v16@0:8", "-[Foo m1]"
262
263.section __DATA,__objc_classlist,regular,no_dead_strip
264  .quad _OBJC_CLASS_$_Foo
265
266.ifdef MAKE_LOAD_METHOD
267.section __DATA,__objc_nlclslist,regular,no_dead_strip
268  .quad _OBJC_CLASS_$_Foo
269.endif
270
271.section __DATA,__objc_imageinfo,regular,no_dead_strip
272  .long 0
273  .long 64
274
275.subsections_via_symbols
276
277#--- klass-with-no-rodata.s
278
279.include "objc-macros.s"
280
281## swiftc generates some classes without a statically-linked rodata. Not
282## entirely sure what the corresponding Swift inputs are required for this to
283## happen; this test merely checks that we can gracefully handle this case
284## without crashing.
285## FIXME: It would be better if this test used the output of some real Swift
286## code.
287
288.globl _$s11FooAACfD
289
290.section __DATA,__objc_data
291_$s11FooAACfD:
292  .quad _$s11FooAACfD
293  .quad 0
294  .quad __objc_empty_cache
295  .quad 0
296  .quad __objc_empty_cache
297
298.section __DATA,__objc_catlist,regular,no_dead_strip
299  .quad __CATEGORY_METAFoo_$_Foo20
300
301.section __DATA,__objc_const
302__CATEGORY_METAFoo_$_Foo20:
303  .objc_classname "Foo20"
304  .quad _$s11FooAACfD
305  .quad 0
306  .quad 0
307  .quad 0
308  .quad 0
309  .quad 0
310  .long 64
311  .space 4
312
313#--- objc-macros.s
314
315# Macros for taking some of the boilerplate out of defining objc structs.
316
317# NOTE: \@ below is a variable that gets auto-incremented by the assembler on
318# each macro invocation. It serves as a mechanism for generating unique symbol
319# names for each macro call.
320
321.macro .objc_classname name
322
323  .section __TEXT,__objc_classname,cstring_literals
324  L_OBJC_CLASS_NAME_.\@:
325    .asciz "\name"
326
327  .section __DATA,__objc_const
328  .quad L_OBJC_CLASS_NAME_.\@
329
330.endm
331
332# struct method_t {
333#   const char *name;
334#   const char *type;
335#   void *impl;
336# }
337.macro .objc_method name, type, impl
338
339  .section __TEXT,__objc_methname,cstring_literals
340  L_OBJC_METH_VAR_NAME_.\@:
341    .asciz "\name"
342
343  .section __TEXT,__objc_methtype,cstring_literals
344  L_OBJC_METH_VAR_TYPE_.\@:
345    .asciz "\type"
346
347  .section __DATA,__objc_const
348    .quad L_OBJC_METH_VAR_NAME_.\@
349    .quad L_OBJC_METH_VAR_TYPE_.\@
350    .quad "\impl"
351
352.endm
353
354# Generate a method_t with a basic impl that just contains `ret`.
355.macro .empty_objc_method name, type, impl
356
357  .text
358  "\impl":
359    ret
360
361  .objc_method "\name", "\type", "\impl"
362
363.endm
364