xref: /llvm-project/clang/test/Modules/compare-objc-protocol.m (revision a65d5309d5b73527efcbdec49a3ba9bba0fd873d)
1// RUN: rm -rf %t
2// RUN: split-file %s %t
3
4// Build first header file
5// RUN: echo "#define FIRST" >> %t/include/first.h
6// RUN: cat %t/test.m        >> %t/include/first.h
7// RUN: echo "#undef FIRST"  >> %t/include/first.h
8
9// Build second header file
10// RUN: echo "#define SECOND" >> %t/include/second.h
11// RUN: cat %t/test.m         >> %t/include/second.h
12// RUN: echo "#undef SECOND"  >> %t/include/second.h
13
14// Test that each header can compile
15// RUN: %clang_cc1 -fsyntax-only -x objective-c %t/include/first.h -fblocks -fobjc-arc
16// RUN: %clang_cc1 -fsyntax-only -x objective-c %t/include/second.h -fblocks -fobjc-arc
17
18// Run test
19// RUN: %clang_cc1 -I%t/include -verify %t/test.m -fblocks -fobjc-arc \
20// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
21
22// Run the same test with second.h being modular
23// RUN: cat %t/include/second.modulemap >> %t/include/module.modulemap
24// RUN: %clang_cc1 -I%t/include -verify %t/test.m -fblocks -fobjc-arc -DTEST_MODULAR=1 \
25// RUN:            -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules.cache
26
27// In non-modular case we ignore protocol redefinitions. But with modules
28// previous definition can come from a hidden [sub]module. And in this case we
29// allow a new definition if it is equivalent to the hidden one.
30//
31// This test case is to verify equivalence checks.
32
33//--- include/common.h
34#ifndef COMMON_H
35#define COMMON_H
36@protocol CommonProtocol @end
37@protocol ExtraProtocol @end
38#endif
39
40//--- include/first-empty.h
41//--- include/module.modulemap
42module Common {
43  header "common.h"
44  export *
45}
46module First {
47  module Empty {
48    header "first-empty.h"
49  }
50  module Hidden {
51    header "first.h"
52    export *
53  }
54}
55//--- include/second.modulemap
56module Second {
57  header "second.h"
58  export *
59}
60
61//--- test.m
62#if defined(FIRST) || defined(SECOND)
63# include "common.h"
64#endif
65
66#if !defined(FIRST) && !defined(SECOND)
67# include "first-empty.h"
68# include "second.h"
69#endif
70
71#if defined(FIRST)
72@protocol CompareForwardDeclaration1;
73@protocol CompareForwardDeclaration2<CommonProtocol> @end
74#elif defined(SECOND)
75@protocol CompareForwardDeclaration1<CommonProtocol> @end
76@protocol CompareForwardDeclaration2;
77#else
78id<CompareForwardDeclaration1> compareForwardDeclaration1;
79id<CompareForwardDeclaration2> compareForwardDeclaration2;
80#endif
81
82#if defined(FIRST)
83@protocol CompareMatchingConformingProtocols<CommonProtocol> @end
84@protocol ForwardProtocol;
85@protocol CompareMatchingConformingForwardProtocols<ForwardProtocol> @end
86
87@protocol CompareProtocolPresence1<CommonProtocol> @end
88@protocol CompareProtocolPresence2 @end
89
90@protocol CompareDifferentProtocols<CommonProtocol> @end
91@protocol CompareProtocolOrder<CommonProtocol, ExtraProtocol> @end
92#elif defined(SECOND)
93@protocol CompareMatchingConformingProtocols<CommonProtocol> @end
94@protocol ForwardProtocol @end
95@protocol CompareMatchingConformingForwardProtocols<ForwardProtocol> @end
96
97@protocol CompareProtocolPresence1 @end
98@protocol CompareProtocolPresence2<CommonProtocol> @end
99
100@protocol CompareDifferentProtocols<ExtraProtocol> @end
101@protocol CompareProtocolOrder<ExtraProtocol, CommonProtocol> @end
102#else
103id<CompareMatchingConformingProtocols> compareMatchingConformingProtocols;
104id<CompareMatchingConformingForwardProtocols> compareMatchingConformingForwardProtocols;
105
106id<CompareProtocolPresence1> compareProtocolPresence1;
107// expected-error@first.h:* {{'CompareProtocolPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 1 referenced protocol}}
108#ifdef TEST_MODULAR
109// expected-note@second.h:* {{but in 'Second' found 0 referenced protocols}}
110#else
111// expected-note@second.h:* {{but in definition here found 0 referenced protocols}}
112#endif
113id<CompareProtocolPresence2> compareProtocolPresence2;
114// expected-error@first.h:* {{'CompareProtocolPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 0 referenced protocols}}
115// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1 referenced protocol}}
116
117id<CompareDifferentProtocols> compareDifferentProtocols;
118// expected-error@first.h:* {{'CompareDifferentProtocols' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 1st referenced protocol with name 'CommonProtocol'}}
119// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with different name 'ExtraProtocol'}}
120id<CompareProtocolOrder> compareProtocolOrder;
121// expected-error@first.h:* {{'CompareProtocolOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 1st referenced protocol with name 'CommonProtocol'}}
122// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with different name 'ExtraProtocol'}}
123#endif
124
125#if defined(FIRST)
126@protocol CompareMatchingMethods
127- (float)matchingMethod:(int)arg;
128@end
129
130@protocol CompareMethodPresence1
131- (void)presenceMethod1;
132@end
133@protocol CompareMethodPresence2
134@end
135
136@protocol CompareMethodName
137- (void)methodNameA;
138@end
139
140@protocol CompareMethodArgCount
141- (void)methodArgCount:(int)arg0 :(int)arg1;
142@end
143@protocol CompareMethodArgName
144- (void)methodArgName:(int)argNameA;
145@end
146@protocol CompareMethodArgType
147- (void)methodArgType:(int)argType;
148@end
149
150@protocol CompareMethodReturnType
151- (int)methodReturnType;
152@end
153
154@protocol CompareMethodOrder
155- (void)methodOrderFirst;
156- (void)methodOrderSecond;
157@end
158
159@protocol CompareMethodClassInstance
160- (void)methodClassInstance;
161@end
162
163@protocol CompareMethodRequirednessExplicit
164@optional
165- (void)methodRequiredness;
166@end
167@protocol CompareMethodRequirednessDefault
168// @required is default
169- (void)methodRequiredness;
170@end
171#elif defined(SECOND)
172@protocol CompareMatchingMethods
173- (float)matchingMethod:(int)arg;
174@end
175
176@protocol CompareMethodPresence1
177@end
178@protocol CompareMethodPresence2
179- (void)presenceMethod2;
180@end
181
182@protocol CompareMethodName
183- (void)methodNameB;
184@end
185
186@protocol CompareMethodArgCount
187- (void)methodArgCount:(int)arg0;
188@end
189@protocol CompareMethodArgName
190- (void)methodArgName:(int)argNameB;
191@end
192@protocol CompareMethodArgType
193- (void)methodArgType:(float)argType;
194@end
195
196@protocol CompareMethodReturnType
197- (float)methodReturnType;
198@end
199
200@protocol CompareMethodOrder
201- (void)methodOrderSecond;
202- (void)methodOrderFirst;
203@end
204
205@protocol CompareMethodClassInstance
206+ (void)methodClassInstance;
207@end
208
209@protocol CompareMethodRequirednessExplicit
210@required
211- (void)methodRequiredness;
212@end
213@protocol CompareMethodRequirednessDefault
214@required
215- (void)methodRequiredness;
216@end
217#else
218id<CompareMatchingMethods> compareMatchingMethods; // no error
219id<CompareMethodPresence1> compareMethodPresence1;
220// expected-error@first.h:* {{'CompareMethodPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method}}
221// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found end of class}}
222id<CompareMethodPresence2> compareMethodPresence2;
223// expected-error@first.h:* {{'CompareMethodPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found end of class}}
224// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method}}
225id<CompareMethodName> compareMethodName;
226// expected-error@first.h:* {{'CompareMethodName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodNameA'}}
227// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found different method 'methodNameB'}}
228
229id<CompareMethodArgCount> compareMethodArgCount;
230// expected-error@first.h:* {{'CompareMethodArgCount' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodArgCount::' that has 2 parameters}}
231// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgCount:' that has 1 parameter}}
232id<CompareMethodArgName> compareMethodArgName;
233// expected-error@first.h:* {{'CompareMethodArgName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodArgName:' with 1st parameter named 'argNameA'}}
234// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgName:' with 1st parameter named 'argNameB'}}
235id<CompareMethodArgType> compareMethodArgType;
236// expected-error@first.h:* {{'CompareMethodArgType' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodArgType:' with 1st parameter of type 'int'}}
237// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgType:' with 1st parameter of type 'float'}}
238
239id<CompareMethodReturnType> compareMethodReturnType;
240// expected-error@first.h:* {{'CompareMethodReturnType' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodReturnType' with return type 'int'}}
241// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodReturnType' with different return type 'float'}}
242
243id<CompareMethodOrder> compareMethodOrder;
244// expected-error@first.h:* {{'CompareMethodOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodOrderFirst'}}
245// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found different method 'methodOrderSecond'}}
246id<CompareMethodClassInstance> compareMethodClassInstance;
247// expected-error@first.h:* {{'CompareMethodClassInstance' has different definitions in different modules; first difference is definition in module 'First.Hidden' found instance method 'methodClassInstance'}}
248// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodClassInstance' as class method}}
249
250id<CompareMethodRequirednessExplicit> compareMethodRequirednessExplicit;
251// expected-error@first.h:* {{'CompareMethodRequirednessExplicit' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 'optional' method control}}
252// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 'required' method control}}
253id<CompareMethodRequirednessDefault> compareMethodRequirednessDefault; // no error
254#endif
255
256#if defined(FIRST)
257@protocol CompareMatchingProperties
258@property int matchingPropName;
259@end
260
261@protocol ComparePropertyPresence1
262@property int propPresence1;
263@end
264@protocol ComparePropertyPresence2
265@end
266
267@protocol ComparePropertyName
268@property int propNameA;
269@end
270
271@protocol ComparePropertyType
272@property int propType;
273@end
274
275@protocol ComparePropertyOrder
276@property int propOrderX;
277@property int propOrderY;
278@end
279
280@protocol CompareMatchingPropertyAttributes
281@property (nonatomic, assign) int matchingProp;
282@end
283@protocol ComparePropertyAttributes
284@property (nonatomic) int propAttributes;
285@end
286// Edge cases.
287@protocol CompareFirstImplAttribute
288@property int firstImplAttribute;
289@end
290@protocol CompareLastImplAttribute
291// Cannot test with protocols 'direct' attribute because it's not allowed.
292@property (class) int lastImplAttribute;
293@end
294#elif defined(SECOND)
295@protocol CompareMatchingProperties
296@property int matchingPropName;
297@end
298
299@protocol ComparePropertyPresence1
300@end
301@protocol ComparePropertyPresence2
302@property int propPresence2;
303@end
304
305@protocol ComparePropertyName
306@property int propNameB;
307@end
308
309@protocol ComparePropertyType
310@property float propType;
311@end
312
313@protocol ComparePropertyOrder
314@property int propOrderY;
315@property int propOrderX;
316@end
317
318@protocol CompareMatchingPropertyAttributes
319@property (assign, nonatomic) int matchingProp;
320@end
321@protocol ComparePropertyAttributes
322@property (atomic) int propAttributes;
323@end
324// Edge cases.
325@protocol CompareFirstImplAttribute
326@property (readonly) int firstImplAttribute;
327@end
328@protocol CompareLastImplAttribute
329@property int lastImplAttribute;
330@end
331#else
332id<CompareMatchingProperties> compareMatchingProperties;
333id<ComparePropertyPresence1> comparePropertyPresence1;
334// expected-error@first.h:* {{'ComparePropertyPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property}}
335// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found end of class}}
336id<ComparePropertyPresence2> comparePropertyPresence2;
337// expected-error@first.h:* {{'ComparePropertyPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found end of class}}
338// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property}}
339id<ComparePropertyName> comparePropertyName;
340// expected-error@first.h:* {{'ComparePropertyName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propNameA'}}
341// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propNameB'}}
342id<ComparePropertyType> comparePropertyType;
343// expected-error@first.h:* {{'ComparePropertyType' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propType' with type 'int'}}
344// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propType' with type 'float'}}
345id<ComparePropertyOrder> comparePropertyOrder;
346// expected-error@first.h:* {{'ComparePropertyOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propOrderX'}}
347// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propOrderY'}}
348
349id<CompareMatchingPropertyAttributes> compareMatchingPropertyAttributes;
350id<ComparePropertyAttributes> comparePropertyAttributes;
351// expected-error@first.h:* {{'ComparePropertyAttributes' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propAttributes' with 'nonatomic' attribute}}
352// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propAttributes' with different 'nonatomic' attribute}}
353id<CompareFirstImplAttribute> compareFirstImplAttribute;
354// expected-error@first.h:* {{'CompareFirstImplAttribute' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'firstImplAttribute' with default 'readonly' attribute}}
355// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'firstImplAttribute' with different 'readonly' attribute}}
356id<CompareLastImplAttribute> compareLastImplAttribute;
357// expected-error@first.h:* {{'CompareLastImplAttribute' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'lastImplAttribute' with 'class' attribute}}
358// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'lastImplAttribute' with different 'class' attribute}}
359#endif
360