xref: /llvm-project/clang/test/Modules/odr_hash.mm (revision a171d248ca34b8b6f8de11d42a83ad981285963a)
1// Clear and create directories
2// RUN: rm -rf %t
3// RUN: mkdir %t
4// RUN: mkdir %t/cache
5// RUN: mkdir %t/Inputs
6
7// Build first header file
8// RUN: echo "#define FIRST" >> %t/Inputs/first.h
9// RUN: cat %s               >> %t/Inputs/first.h
10
11// Build second header file
12// RUN: echo "#define SECOND" >> %t/Inputs/second.h
13// RUN: cat %s                >> %t/Inputs/second.h
14
15// Test that each header can compile
16// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/first.h -fblocks -fobjc-arc
17// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/second.h -fblocks -fobjc-arc
18
19// Build module map file
20// RUN: echo "module FirstModule {"     >> %t/Inputs/module.modulemap
21// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.modulemap
22// RUN: echo "}"                        >> %t/Inputs/module.modulemap
23// RUN: echo "module SecondModule {"    >> %t/Inputs/module.modulemap
24// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.modulemap
25// RUN: echo "}"                        >> %t/Inputs/module.modulemap
26
27// Run test
28// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c++ -I%t/Inputs -verify %s -fblocks -fobjc-arc
29
30#if !defined(FIRST) && !defined(SECOND)
31#include "first.h"
32#include "second.h"
33#endif
34
35#if defined(FIRST) || defined(SECOND)
36@protocol P1
37@end
38
39@protocol P2
40@end
41
42@interface I1
43@end
44
45@interface I2 : I1
46@end
47
48@interface Interface1 <T : I1 *> {
49@public
50  T<P1> x;
51}
52@end
53
54@interface Interface2 <T : I1 *>
55@end
56
57@interface Interface3 <T : I1 *>
58@end
59
60@interface EmptySelectorSlot
61- (void)method:(int)arg;
62- (void)method:(int)arg :(int)empty;
63
64- (void)multiple:(int)arg1 args:(int)arg2 :(int)arg3;
65- (void)multiple:(int)arg1 :(int)arg2 args:(int)arg3;
66@end
67
68#endif
69
70#if defined(FIRST)
71struct S {
72  Interface1 *I;
73  decltype(I->x) x;
74  int y;
75};
76#elif defined(SECOND)
77struct S {
78  Interface1 *I;
79  decltype(I->x) x;
80  bool y;
81};
82#else
83S s;
84// expected-error@second.h:* {{'S::y' from module 'SecondModule' is not present in definition of 'S' in module 'FirstModule'}}
85// expected-note@first.h:* {{declaration of 'y' does not match}}
86#endif
87
88namespace Types {
89namespace Attributed {
90#if defined(FIRST)
91void invalid1() {
92  static double __attribute((objc_gc(strong))) *x;
93}
94void invalid2() {
95  static int __attribute((objc_gc(strong))) *x;
96}
97void valid() {
98  static int __attribute((objc_gc(strong))) *x;
99}
100#elif defined(SECOND)
101void invalid1() {
102  static int __attribute((objc_gc(strong))) *x;
103}
104void invalid2() {
105  static int __attribute((objc_gc(weak))) *x;
106}
107void valid() {
108  static int __attribute((objc_gc(strong))) *x;
109}
110#else
111auto function1 = invalid1;
112// expected-error@second.h:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
113// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
114auto function2 = invalid2;
115
116auto function3 = valid;
117#endif
118}  // namespace Attributed
119
120namespace BlockPointer {
121#if defined(FIRST)
122void invalid1() {
123  void (^x)(int);
124}
125void invalid2() {
126  void (^x)(int);
127}
128void invalid3() {
129  void (^x)(int);
130}
131void invalid4() {
132  void (^x)(int);
133}
134void valid() {
135  void (^x1)(int);
136  int (^x2)(int);
137  void (^x3)(int, int);
138  void (^x4)(short);
139}
140#elif defined(SECOND)
141void invalid1() {
142  void (^x)();
143}
144void invalid2() {
145  void (^x)(int, int);
146}
147void invalid3() {
148  int (^x)(int);
149}
150void invalid4() {
151  void (^x)(float);
152}
153void valid() {
154  void (^x1)(int);
155  int (^x2)(int);
156  void (^x3)(int, int);
157  void (^x4)(short);
158}
159#else
160auto function1 = invalid1;
161// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
162// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
163auto function2 = invalid2;
164// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
165// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
166auto function3 = invalid3;
167// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
168// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
169auto function4 = invalid4;
170// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
171// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
172auto function5 = valid;
173#endif
174}  // namespace BlockPointer
175
176namespace ObjCObject {
177#if defined(FIRST)
178struct Invalid1 {
179  using T = Interface2<I1*>;
180};
181struct Invalid2 {
182  using T = Interface2<I1*>;
183};
184struct Invalid3 {
185  using T = Interface2<P1, P1>;
186};
187struct Invalid4 {
188  using T = Interface2<P1>;
189};
190struct Valid {
191  using T1 = Interface2<I1*>;
192  using T2 = Interface3<I1*>;
193  using T3 = Interface2<P1>;
194  using T4 = Interface3<P1, P2>;
195  using T5 = __kindof Interface2;
196};
197#elif defined(SECOND)
198struct Invalid1 {
199  using T = Interface3<I1*>;
200};
201struct Invalid2 {
202  using T = Interface2<I2*>;
203};
204struct Invalid3 {
205  using T = Interface2<P1>;
206};
207struct Invalid4 {
208  using T = Interface2<P2>;
209};
210struct Valid {
211  using T1 = Interface2<I1*>;
212  using T2 = Interface3<I1*>;
213  using T3 = Interface2<P1>;
214  using T4 = Interface3<P1, P2>;
215  using T5 = __kindof Interface2;
216};
217#else
218Invalid1 i1;
219// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}
220// expected-note@second.h:* {{declaration of 'T' does not match}}
221Invalid2 i2;
222// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}
223// expected-note@second.h:* {{declaration of 'T' does not match}}
224Invalid3 i3;
225// expected-error@second.h:* {{'Types::ObjCObject::Invalid3' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'T' with underlying type 'Interface2<P1>'}}
226// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}
227Invalid4 i4;
228// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}
229// expected-note@second.h:* {{declaration of 'T' does not match}}
230Valid v;
231#endif
232}  // namespace VisitObjCObject
233}  // namespace Types
234
235#if defined(FIRST)
236@interface Interface4 <T : I1 *> {
237@public
238  T<P1> x;
239}
240@end
241@interface Interface5 <T : I1 *> {
242@public
243  T<P1> y;
244}
245@end
246@interface Interface6 <T1 : I1 *, T2 : I2 *> {
247@public
248  T1 z;
249}
250@end
251#elif defined(SECOND)
252@interface Interface4 <T : I1 *> {
253@public
254  T<P2> x;
255}
256@end
257@interface Interface5 <T : I1 *> {
258@public
259  T<P1, P2> y;
260}
261@end
262@interface Interface6 <T1 : I1 *, T2 : I2 *> {
263@public
264  T2 z;
265}
266@end
267#else
268
269#endif
270
271namespace Types {
272namespace ObjCTypeParam {
273#if defined(FIRST) || defined(SECOND)
274struct Invalid1 {
275  Interface4 *I;
276  decltype(I->x) x;
277};
278struct Invalid2 {
279  Interface5 *I;
280  decltype(I->y) y;
281};
282struct Invalid3 {
283  Interface6 *I;
284  decltype(I->z) z;
285};
286#else
287Invalid1 i1;
288
289Invalid2 i2;
290
291Invalid3 i3;
292
293// FIXME: We should reject to merge these structs and diagnose for the
294// different definitions for Interface4/Interface5/Interface6.
295
296#endif
297
298}  // namespace ObjCTypeParam
299}  // namespace Types
300
301namespace CallMethods {
302#if defined(FIRST)
303void invalid1(EmptySelectorSlot *obj) {
304  [obj method:0];
305}
306void invalid2(EmptySelectorSlot *obj) {
307  [obj multiple:0 args:0 :0];
308}
309#elif defined(SECOND)
310void invalid1(EmptySelectorSlot *obj) {
311  [obj method:0 :0];
312}
313void invalid2(EmptySelectorSlot *obj) {
314  [obj multiple:0 :0 args:0];
315}
316#endif
317// expected-error@second.h:* {{'CallMethods::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
318// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
319
320// expected-error@second.h:* {{'CallMethods::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
321// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
322}  // namespace CallMethods
323
324// Keep macros contained to one file.
325#ifdef FIRST
326#undef FIRST
327#endif
328
329#ifdef SECOND
330#undef SECOND
331#endif
332