Clang Project

clang_source_code/test/Modules/odr_hash.mm
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#endif
61
62#if defined(FIRST)
63struct S {
64  Interface1 *I;
65  decltype(I->x) x;
66  int y;
67};
68#elif defined(SECOND)
69struct S {
70  Interface1 *I;
71  decltype(I->x) x;
72  bool y;
73};
74#else
75S s;
76// expected-error@second.h:* {{'S::y' from module 'SecondModule' is not present in definition of 'S' in module 'FirstModule'}}
77// expected-note@first.h:* {{declaration of 'y' does not match}}
78#endif
79
80namespace Types {
81namespace Attributed {
82#if defined(FIRST)
83void invalid1() {
84  static double __attribute((objc_gc(strong))) *x;
85}
86void invalid2() {
87  static int __attribute((objc_gc(strong))) *x;
88}
89void valid() {
90  static int __attribute((objc_gc(strong))) *x;
91}
92#elif defined(SECOND)
93void invalid1() {
94  static int __attribute((objc_gc(strong))) *x;
95}
96void invalid2() {
97  static int __attribute((objc_gc(weak))) *x;
98}
99void valid() {
100  static int __attribute((objc_gc(strong))) *x;
101}
102#else
103auto function1 = invalid1;
104// expected-error@second.h:* {{Types::Attributed::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
105// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
106auto function2 = invalid2;
107// expected-error@second.h:* {{'Types::Attributed::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
108// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
109auto function3 = valid;
110#endif
111}  // namespace Attributed
112
113namespace BlockPointer {
114#if defined(FIRST)
115void invalid1() {
116  void (^x)(int);
117}
118void invalid2() {
119  void (^x)(int);
120}
121void invalid3() {
122  void (^x)(int);
123}
124void invalid4() {
125  void (^x)(int);
126}
127void valid() {
128  void (^x1)(int);
129  int (^x2)(int);
130  void (^x3)(int, int);
131  void (^x4)(short);
132}
133#elif defined(SECOND)
134void invalid1() {
135  void (^x)();
136}
137void invalid2() {
138  void (^x)(int, int);
139}
140void invalid3() {
141  int (^x)(int);
142}
143void invalid4() {
144  void (^x)(float);
145}
146void valid() {
147  void (^x1)(int);
148  int (^x2)(int);
149  void (^x3)(int, int);
150  void (^x4)(short);
151}
152#else
153auto function1 = invalid1;
154// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
155// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
156auto function2 = invalid2;
157// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
158// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
159auto function3 = invalid3;
160// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
161// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
162auto function4 = invalid4;
163// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}
164// expected-note@first.h:* {{but in 'FirstModule' found a different body}}
165auto function5 = valid;
166#endif
167}  // namespace BlockPointer
168
169namespace ObjCObject {
170#if defined(FIRST)
171struct Invalid1 {
172  using T = Interface2<I1*>;
173};
174struct Invalid2 {
175  using T = Interface2<I1*>;
176};
177struct Invalid3 {
178  using T = Interface2<P1, P1>;
179};
180struct Invalid4 {
181  using T = Interface2<P1>;
182};
183struct Valid {
184  using T1 = Interface2<I1*>;
185  using T2 = Interface3<I1*>;
186  using T3 = Interface2<P1>;
187  using T4 = Interface3<P1, P2>;
188  using T5 = __kindof Interface2;
189};
190#elif defined(SECOND)
191struct Invalid1 {
192  using T = Interface3<I1*>;
193};
194struct Invalid2 {
195  using T = Interface2<I2*>;
196};
197struct Invalid3 {
198  using T = Interface2<P1>;
199};
200struct Invalid4 {
201  using T = Interface2<P2>;
202};
203struct Valid {
204  using T1 = Interface2<I1*>;
205  using T2 = Interface3<I1*>;
206  using T3 = Interface2<P1>;
207  using T4 = Interface3<P1, P2>;
208  using T5 = __kindof Interface2;
209};
210#else
211Invalid1 i1;
212// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}
213// expected-note@second.h:* {{declaration of 'T' does not match}}
214Invalid2 i2;
215// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}
216// expected-note@second.h:* {{declaration of 'T' does not match}}
217Invalid3 i3;
218// 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>'}}
219// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}
220Invalid4 i4;
221// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}
222// expected-note@second.h:* {{declaration of 'T' does not match}}
223Valid v;
224#endif
225}  // namespace VisitObjCObject
226}  // namespace Types
227
228#if defined(FIRST)
229@interface Interface4 <T : I1 *> {
230@public
231  T<P1> x;
232}
233@end
234@interface Interface5 <T : I1 *> {
235@public
236  T<P1> x;
237}
238@end
239@interface Interface6 <T1 : I1 *, T2 : I2 *> {
240@public
241  T1 x;
242}
243@end
244#elif defined(SECOND)
245@interface Interface4 <T : I1 *> {
246@public
247  T<P2> x;
248}
249@end
250@interface Interface5 <T : I1 *> {
251@public
252  T<P1, P2> x;
253}
254@end
255@interface Interface6 <T1 : I1 *, T2 : I2 *> {
256@public
257  T2 x;
258}
259@end
260#endif
261
262namespace Types {
263namespace ObjCTypeParam {
264#if defined(FIRST) || defined(SECOND)
265struct Invalid1 {
266  Interface4 *I;
267  decltype(I->x) x;
268};
269struct Invalid2 {
270  Interface5 *I;
271  decltype(I->x) x;
272};
273struct Invalid3 {
274  Interface6 *I;
275  decltype(I->x) x;
276};
277#else
278Invalid1 i1;
279// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid1::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid1' in module 'SecondModule'}}
280// expected-note@second.h:* {{declaration of 'x' does not match}}
281Invalid2 i2;
282// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid2::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid2' in module 'SecondModule'}}
283// expected-note@second.h:* {{declaration of 'x' does not match}}
284Invalid3 i3;
285// expected-error@first.h:* {{'Types::ObjCTypeParam::Invalid3::x' from module 'FirstModule' is not present in definition of 'Types::ObjCTypeParam::Invalid3' in module 'SecondModule'}}
286// expected-note@second.h:* {{declaration of 'x' does not match}}
287#endif
288
289}  // namespace ObjCTypeParam
290}  // namespace Types
291
292// Keep macros contained to one file.
293#ifdef FIRST
294#undef FIRST
295#endif
296
297#ifdef SECOND
298#undef SECOND
299#endif
300