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.map
21// RUN: echo "    header \"first.h\""   >> %t/Inputs/module.map
22// RUN: echo "}"                        >> %t/Inputs/module.map
23// RUN: echo "module SecondModule {"    >> %t/Inputs/module.map
24// RUN: echo "    header \"second.h\""  >> %t/Inputs/module.map
25// RUN: echo "}"                        >> %t/Inputs/module.map
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// expected-error@second.h:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
116// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
117auto function3 = valid;
118#endif
119}  // namespace Attributed
120
121namespace BlockPointer {
122#if defined(FIRST)
123void invalid1() {
124  void (^x)(int);
125}
126void invalid2() {
127  void (^x)(int);
128}
129void invalid3() {
130  void (^x)(int);
131}
132void invalid4() {
133  void (^x)(int);
134}
135void valid() {
136  void (^x1)(int);
137  int (^x2)(int);
138  void (^x3)(int, int);
139  void (^x4)(short);
140}
141#elif defined(SECOND)
142void invalid1() {
143  void (^x)();
144}
145void invalid2() {
146  void (^x)(int, int);
147}
148void invalid3() {
149  int (^x)(int);
150}
151void invalid4() {
152  void (^x)(float);
153}
154void valid() {
155  void (^x1)(int);
156  int (^x2)(int);
157  void (^x3)(int, int);
158  void (^x4)(short);
159}
160#else
161auto function1 = invalid1;
162// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
163// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
164auto function2 = invalid2;
165// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
166// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
167auto function3 = invalid3;
168// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
169// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
170auto function4 = invalid4;
171// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
172// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
173auto function5 = valid;
174#endif
175}  // namespace BlockPointer
176
177namespace ObjCObject {
178#if defined(FIRST)
179struct Invalid1 {
180  using T = Interface2<I1*>;
181};
182struct Invalid2 {
183  using T = Interface2<I1*>;
184};
185struct Invalid3 {
186  using T = Interface2<P1, P1>;
187};
188struct Invalid4 {
189  using T = Interface2<P1>;
190};
191struct Valid {
192  using T1 = Interface2<I1*>;
193  using T2 = Interface3<I1*>;
194  using T3 = Interface2<P1>;
195  using T4 = Interface3<P1, P2>;
196  using T5 = __kindof Interface2;
197};
198#elif defined(SECOND)
199struct Invalid1 {
200  using T = Interface3<I1*>;
201};
202struct Invalid2 {
203  using T = Interface2<I2*>;
204};
205struct Invalid3 {
206  using T = Interface2<P1>;
207};
208struct Invalid4 {
209  using T = Interface2<P2>;
210};
211struct Valid {
212  using T1 = Interface2<I1*>;
213  using T2 = Interface3<I1*>;
214  using T3 = Interface2<P1>;
215  using T4 = Interface3<P1, P2>;
216  using T5 = __kindof Interface2;
217};
218#else
219Invalid1 i1;
220// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}
221// expected-note@second.h:* {{declaration of 'T' does not match}}
222Invalid2 i2;
223// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}
224// expected-note@second.h:* {{declaration of 'T' does not match}}
225Invalid3 i3;
226// 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>'}}
227// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}
228Invalid4 i4;
229// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}
230// expected-note@second.h:* {{declaration of 'T' does not match}}
231Valid v;
232#endif
233}  // namespace VisitObjCObject
234}  // namespace Types
235
236#if defined(FIRST)
237@interface Interface4 <T : I1 *> {
238@public
239  T<P1> x;
240}
241@end
242@interface Interface5 <T : I1 *> {
243@public
244  T<P1> x;
245}
246@end
247@interface Interface6 <T1 : I1 *, T2 : I2 *> {
248@public
249  T1 x;
250}
251@end
252#elif defined(SECOND)
253@interface Interface4 <T : I1 *> {
254@public
255  T<P2> x;
256}
257@end
258@interface Interface5 <T : I1 *> {
259@public
260  T<P1, P2> x;
261}
262@end
263@interface Interface6 <T1 : I1 *, T2 : I2 *> {
264@public
265  T2 x;
266}
267@end
268#endif
269
270namespace Types {
271namespace ObjCTypeParam {
272#if defined(FIRST) || defined(SECOND)
273struct Invalid1 {
274  Interface4 *I;
275  decltype(I->x) x;
276};
277struct Invalid2 {
278  Interface5 *I;
279  decltype(I->x) x;
280};
281struct Invalid3 {
282  Interface6 *I;
283  decltype(I->x) x;
284};
285#else
286Invalid1 i1;
287// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}
288// expected-note@second.h:* {{declaration of 'x' does not match}}
289Invalid2 i2;
290// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}
291// expected-note@second.h:* {{declaration of 'x' does not match}}
292Invalid3 i3;
293// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}
294// expected-note@second.h:* {{declaration of 'x' does not match}}
295#endif
296
297}  // namespace ObjCTypeParam
298}  // namespace Types
299
300namespace CallMethods {
301#if defined(FIRST)
302void invalid1(EmptySelectorSlot *obj) {
303  [obj method:0];
304}
305void invalid2(EmptySelectorSlot *obj) {
306  [obj multiple:0 args:0 :0];
307}
308#elif defined(SECOND)
309void invalid1(EmptySelectorSlot *obj) {
310  [obj method:0 :0];
311}
312void invalid2(EmptySelectorSlot *obj) {
313  [obj multiple:0 :0 args:0];
314}
315#endif
316// expected-error@second.h:* {{'CallMethods::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
317// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
318
319// expected-error@second.h:* {{'CallMethods::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
320// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
321}  // namespace CallMethods
322
323// Keep macros contained to one file.
324#ifdef FIRST
325#undef FIRST
326#endif
327
328#ifdef SECOND
329#undef SECOND
330#endif
331