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