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// Test that we don't accept different class definitions with the same name 28// from multiple modules but detect mismatches and provide actionable 29// diagnostic. 30 31//--- include/common.h 32#ifndef COMMON_H 33#define COMMON_H 34@interface NSObject @end 35@protocol CommonProtocol @end 36@protocol ExtraProtocol @end 37#endif 38 39//--- include/first-empty.h 40//--- include/module.modulemap 41module First { 42 module Empty { 43 header "first-empty.h" 44 } 45 module Hidden { 46 header "first.h" 47 export * 48 } 49} 50 51//--- include/second.modulemap 52module Second { 53 header "second.h" 54 export * 55} 56 57//--- test.m 58#if defined(FIRST) || defined(SECOND) 59# include "common.h" 60#endif 61 62#if !defined(FIRST) && !defined(SECOND) 63# include "first-empty.h" 64# include "second.h" 65#endif 66 67#if defined(FIRST) 68@class CompareForwardDeclaration1; 69@interface CompareForwardDeclaration2: NSObject @end 70#elif defined(SECOND) 71@interface CompareForwardDeclaration1: NSObject @end 72@class CompareForwardDeclaration2; 73#else 74CompareForwardDeclaration1 *compareForwardDeclaration1; 75CompareForwardDeclaration2 *compareForwardDeclaration2; 76#endif 77 78#if defined(FIRST) 79@interface CompareMatchingSuperclass: NSObject @end 80 81@interface CompareSuperclassPresence1: NSObject @end 82@interface CompareSuperclassPresence2 @end 83 84@interface CompareDifferentSuperclass: NSObject @end 85#elif defined(SECOND) 86@interface CompareMatchingSuperclass: NSObject @end 87 88@interface CompareSuperclassPresence1 @end 89@interface CompareSuperclassPresence2: NSObject @end 90 91@interface DifferentSuperclass: NSObject @end 92@interface CompareDifferentSuperclass: DifferentSuperclass @end 93#else 94CompareMatchingSuperclass *compareMatchingSuperclass; 95CompareSuperclassPresence1 *compareSuperclassPresence1; 96// expected-error@first.h:* {{'CompareSuperclassPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found super class with type 'NSObject'}} 97// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found no super class}} 98CompareSuperclassPresence2 *compareSuperclassPresence2; 99// expected-error@first.h:* {{'CompareSuperclassPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found no super class}} 100// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found super class with type 'NSObject'}} 101CompareDifferentSuperclass *compareDifferentSuperclass; 102// expected-error@first.h:* {{'CompareDifferentSuperclass' has different definitions in different modules; first difference is definition in module 'First.Hidden' found super class with type 'NSObject'}} 103// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found super class with type 'DifferentSuperclass'}} 104#endif 105 106#if defined(FIRST) 107@interface CompareMatchingConformingProtocols: NSObject<CommonProtocol> @end 108@protocol ForwardProtocol; 109@interface CompareMatchingConformingForwardProtocols: NSObject<ForwardProtocol> @end 110 111@interface CompareProtocolPresence1: NSObject<CommonProtocol> @end 112@interface CompareProtocolPresence2: NSObject @end 113 114@interface CompareDifferentProtocols: NSObject<CommonProtocol> @end 115@interface CompareProtocolOrder: NSObject<CommonProtocol, ExtraProtocol> @end 116#elif defined(SECOND) 117@interface CompareMatchingConformingProtocols: NSObject<CommonProtocol> @end 118@protocol ForwardProtocol @end 119@interface CompareMatchingConformingForwardProtocols: NSObject<ForwardProtocol> @end 120 121@interface CompareProtocolPresence1: NSObject @end 122@interface CompareProtocolPresence2: NSObject<CommonProtocol> @end 123 124@interface CompareDifferentProtocols: NSObject<ExtraProtocol> @end 125@interface CompareProtocolOrder: NSObject<ExtraProtocol, CommonProtocol> @end 126#else 127CompareMatchingConformingProtocols *compareMatchingConformingProtocols; 128CompareMatchingConformingForwardProtocols *compareMatchingConformingForwardProtocols; 129 130CompareProtocolPresence1 *compareProtocolPresence1; 131// expected-error@first.h:* {{'CompareProtocolPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 1 referenced protocol}} 132// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 0 referenced protocols}} 133CompareProtocolPresence2 *compareProtocolPresence2; 134// expected-error@first.h:* {{'CompareProtocolPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found 0 referenced protocols}} 135// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1 referenced protocol}} 136 137CompareDifferentProtocols *compareDifferentProtocols; 138// 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'}} 139// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with different name 'ExtraProtocol'}} 140CompareProtocolOrder *compareProtocolOrder; 141// 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'}} 142// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found 1st referenced protocol with different name 'ExtraProtocol'}} 143#endif 144 145#if defined(FIRST) 146@interface CompareMatchingIVars: NSObject { int ivarName; } @end 147 148@interface CompareIVarPresence1: NSObject @end 149@interface CompareIVarPresence2: NSObject { int ivarPresence2; } @end 150 151@interface CompareIVarName: NSObject { int ivarName; } @end 152@interface CompareIVarType: NSObject { int ivarType; } @end 153@interface CompareIVarOrder: NSObject { 154 int ivarNameInt; 155 float ivarNameFloat; 156} 157@end 158 159@interface CompareIVarVisibilityExplicit: NSObject { 160@public 161 int ivarVisibility; 162} 163@end 164@interface CompareIVarVisibilityDefault: NSObject { 165 int ivarVisibilityDefault; 166} 167@end 168#elif defined(SECOND) 169@interface CompareMatchingIVars: NSObject { int ivarName; } @end 170 171@interface CompareIVarPresence1: NSObject { int ivarPresence1; } @end 172@interface CompareIVarPresence2: NSObject @end 173 174@interface CompareIVarName: NSObject { int differentIvarName; } @end 175@interface CompareIVarType: NSObject { float ivarType; } @end 176@interface CompareIVarOrder: NSObject { 177 float ivarNameFloat; 178 int ivarNameInt; 179} 180@end 181 182@interface CompareIVarVisibilityExplicit: NSObject { 183@private 184 int ivarVisibility; 185} 186@end 187@interface CompareIVarVisibilityDefault: NSObject { 188@public 189 int ivarVisibilityDefault; 190} 191@end 192#else 193CompareMatchingIVars *compareMatchingIVars; 194 195CompareIVarPresence1 *compareIVarPresence1; 196#ifdef TEST_MODULAR 197// expected-error@second.h:* {{'CompareIVarPresence1::ivarPresence1' from module 'Second' is not present in definition of 'CompareIVarPresence1' in module 'First.Hidden'}} 198// expected-note@first.h:* {{definition has no member 'ivarPresence1'}} 199#else 200// expected-error@first.h:* {{'CompareIVarPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found end of class}} 201// expected-note@second.h:* {{but in definition here found instance variable}} 202#endif 203CompareIVarPresence2 *compareIVarPresence2; 204// expected-error@first.h:* {{'CompareIVarPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found instance variable}} 205// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found end of class}} 206 207CompareIVarName *compareIVarName; 208#ifdef TEST_MODULAR 209// expected-error@second.h:* {{'CompareIVarName::differentIvarName' from module 'Second' is not present in definition of 'CompareIVarName' in module 'First.Hidden'}} 210// expected-note@first.h:* {{definition has no member 'differentIvarName'}} 211#else 212// expected-error@first.h:* {{'CompareIVarName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'ivarName'}} 213// expected-note@second.h:* {{but in definition here found field 'differentIvarName'}} 214#endif 215CompareIVarType *compareIVarType; 216#ifdef TEST_MODULAR 217// expected-error@second.h:* {{'CompareIVarType::ivarType' from module 'Second' is not present in definition of 'CompareIVarType' in module 'First.Hidden'}} 218// expected-note@first.h:* {{declaration of 'ivarType' does not match}} 219#else 220// expected-error@first.h:* {{'CompareIVarType' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'ivarType' with type 'int'}} 221// expected-note@second.h:* {{but in definition here found field 'ivarType' with type 'float'}} 222#endif 223CompareIVarOrder *compareIVarOrder; 224// expected-error@first.h:* {{'CompareIVarOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found field 'ivarNameInt'}} 225// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found field 'ivarNameFloat'}} 226 227CompareIVarVisibilityExplicit *compareIVarVisibilityExplicit; 228// expected-error@first.h:* {{'CompareIVarVisibilityExplicit' has different definitions in different modules; first difference is definition in module 'First.Hidden' found instance variable 'ivarVisibility' access control is @public}} 229// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found instance variable 'ivarVisibility' access control is @private}} 230CompareIVarVisibilityDefault *compareIVarVisibilityDefault; 231// expected-error@first.h:* {{'CompareIVarVisibilityDefault' has different definitions in different modules; first difference is definition in module 'First.Hidden' found instance variable 'ivarVisibilityDefault' access control is @protected}} 232// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found instance variable 'ivarVisibilityDefault' access control is @public}} 233#endif 234 235#if defined(FIRST) 236@interface CompareMatchingMethods: NSObject 237- (float)matchingMethod:(int)arg; 238@end 239 240@interface CompareMethodPresence1: NSObject 241- (void)presenceMethod1; 242@end 243@interface CompareMethodPresence2: NSObject 244@end 245 246@interface CompareMethodName: NSObject 247- (void)methodNameA; 248@end 249 250@interface CompareMethodArgCount: NSObject 251- (void)methodArgCount:(int)arg0 :(int)arg1; 252@end 253@interface CompareMethodArgName: NSObject 254- (void)methodArgName:(int)argNameA; 255@end 256@interface CompareMethodArgType: NSObject 257- (void)methodArgType:(int)argType; 258@end 259 260@interface CompareMethodReturnType: NSObject 261- (int)methodReturnType; 262@end 263 264@interface CompareMethodOrder: NSObject 265- (void)methodOrderFirst; 266- (void)methodOrderSecond; 267@end 268 269@interface CompareMethodClassInstance: NSObject 270+ (void)methodClassInstance; 271@end 272#elif defined(SECOND) 273@interface CompareMatchingMethods: NSObject 274- (float)matchingMethod:(int)arg; 275@end 276 277@interface CompareMethodPresence1: NSObject 278@end 279@interface CompareMethodPresence2: NSObject 280- (void)presenceMethod2; 281@end 282 283@interface CompareMethodName: NSObject 284- (void)methodNameB; 285@end 286 287@interface CompareMethodArgCount: NSObject 288- (void)methodArgCount:(int)arg0; 289@end 290@interface CompareMethodArgName: NSObject 291- (void)methodArgName:(int)argNameB; 292@end 293@interface CompareMethodArgType: NSObject 294- (void)methodArgType:(float)argType; 295@end 296 297@interface CompareMethodReturnType: NSObject 298- (float)methodReturnType; 299@end 300 301@interface CompareMethodOrder: NSObject 302- (void)methodOrderSecond; 303- (void)methodOrderFirst; 304@end 305 306@interface CompareMethodClassInstance: NSObject 307- (void)methodClassInstance; 308@end 309#else 310CompareMatchingMethods *compareMatchingMethods; 311CompareMethodPresence1 *compareMethodPresence1; 312// expected-error@first.h:* {{'CompareMethodPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method}} 313// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found end of class}} 314CompareMethodPresence2 *compareMethodPresence2; 315// expected-error@first.h:* {{'CompareMethodPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found end of class}} 316// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method}} 317CompareMethodName *compareMethodName; 318// expected-error@first.h:* {{'CompareMethodName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodNameA'}} 319// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found different method 'methodNameB'}} 320 321CompareMethodArgCount *compareMethodArgCount; 322// 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}} 323// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgCount:' that has 1 parameter}} 324CompareMethodArgName *compareMethodArgName; 325// 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'}} 326// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgName:' with 1st parameter named 'argNameB'}} 327CompareMethodArgType *compareMethodArgType; 328// 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'}} 329// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodArgType:' with 1st parameter of type 'float'}} 330 331CompareMethodReturnType *compareMethodReturnType; 332// 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'}} 333// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodReturnType' with different return type 'float'}} 334 335CompareMethodOrder *compareMethodOrder; 336// expected-error@first.h:* {{'CompareMethodOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found method 'methodOrderFirst'}} 337// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found different method 'methodOrderSecond'}} 338CompareMethodClassInstance *compareMethodClassInstance; 339// expected-error@first.h:* {{'CompareMethodClassInstance' has different definitions in different modules; first difference is definition in module 'First.Hidden' found class method 'methodClassInstance'}} 340// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found method 'methodClassInstance' as instance method}} 341#endif 342 343#if defined(FIRST) 344@interface CompareMatchingProperties: NSObject 345@property int matchingPropName; 346@end 347 348@interface ComparePropertyPresence1: NSObject 349@property int propPresence1; 350@end 351@interface ComparePropertyPresence2: NSObject 352@end 353 354@interface ComparePropertyName: NSObject 355@property int propNameA; 356@end 357 358@interface ComparePropertyType: NSObject 359@property int propType; 360@end 361 362@interface ComparePropertyOrder: NSObject 363@property int propOrderX; 364@property int propOrderY; 365@end 366 367@interface CompareMatchingPropertyAttributes: NSObject 368@property (nonatomic, assign) int matchingProp; 369@end 370@interface ComparePropertyAttributes: NSObject 371@property (readonly) int propAttributes; 372@end 373// Edge cases. 374@interface CompareFirstImplAttribute: NSObject 375@property int firstImplAttribute; 376@end 377@interface CompareLastImplAttribute: NSObject 378@property (direct) int lastImplAttribute; 379@end 380#elif defined(SECOND) 381@interface CompareMatchingProperties: NSObject 382@property int matchingPropName; 383@end 384 385@interface ComparePropertyPresence1: NSObject 386@end 387@interface ComparePropertyPresence2: NSObject 388@property int propPresence2; 389@end 390 391@interface ComparePropertyName: NSObject 392@property int propNameB; 393@end 394 395@interface ComparePropertyType: NSObject 396@property float propType; 397@end 398 399@interface ComparePropertyOrder: NSObject 400@property int propOrderY; 401@property int propOrderX; 402@end 403 404@interface CompareMatchingPropertyAttributes: NSObject 405@property (assign, nonatomic) int matchingProp; 406@end 407@interface ComparePropertyAttributes: NSObject 408@property (readwrite) int propAttributes; 409@end 410// Edge cases. 411@interface CompareFirstImplAttribute: NSObject 412@property (readonly) int firstImplAttribute; 413@end 414@interface CompareLastImplAttribute: NSObject 415@property int lastImplAttribute; 416@end 417#else 418CompareMatchingProperties *compareMatchingProperties; 419ComparePropertyPresence1 *comparePropertyPresence1; 420// expected-error@first.h:* {{'ComparePropertyPresence1' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property}} 421// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found end of class}} 422ComparePropertyPresence2 *comparePropertyPresence2; 423// expected-error@first.h:* {{'ComparePropertyPresence2' has different definitions in different modules; first difference is definition in module 'First.Hidden' found end of class}} 424// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property}} 425 426ComparePropertyName *comparePropertyName; 427// expected-error@first.h:* {{'ComparePropertyName' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propNameA'}} 428// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propNameB'}} 429ComparePropertyType *comparePropertyType; 430// 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'}} 431// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propType' with type 'float'}} 432ComparePropertyOrder *comparePropertyOrder; 433// expected-error@first.h:* {{'ComparePropertyOrder' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propOrderX'}} 434// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propOrderY'}} 435 436CompareMatchingPropertyAttributes *compareMatchingPropertyAttributes; 437ComparePropertyAttributes *comparePropertyAttributes; 438// expected-error@first.h:* {{'ComparePropertyAttributes' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'propAttributes' with 'readonly' attribute}} 439// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'propAttributes' with different 'readonly' attribute}} 440CompareFirstImplAttribute *compareFirstImplAttribute; 441// 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}} 442// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'firstImplAttribute' with different 'readonly' attribute}} 443CompareLastImplAttribute *compareLastImplAttribute; 444// expected-error@first.h:* {{'CompareLastImplAttribute' has different definitions in different modules; first difference is definition in module 'First.Hidden' found property 'lastImplAttribute' with 'direct' attribute}} 445// expected-note-re@second.h:* {{but in {{'Second'|definition here}} found property 'lastImplAttribute' with different 'direct' attribute}} 446#endif 447 448#if defined(FIRST) 449@interface CompareMatchingCategories: NSObject @end 450@interface CompareMatchingCategories(Matching) 451- (int)testMethod; 452@end 453 454@interface CompareMismatchingCategories1: NSObject @end 455@interface CompareMismatchingCategories1(Category1) 456- (void)presentMethod; 457@end 458@interface CompareMismatchingCategories2: NSObject @end 459@interface CompareMismatchingCategories2(Category2) 460@end 461 462@interface CompareDifferentCategoryNames: NSObject @end 463@interface CompareDifferentCategoryNames(CategoryFirst) 464- (void)firstMethod:(int)x; 465@end 466#elif defined(SECOND) 467@interface CompareMatchingCategories: NSObject @end 468@interface CompareMatchingCategories(Matching) 469- (int)testMethod; 470@end 471 472@interface CompareMismatchingCategories1: NSObject @end 473@interface CompareMismatchingCategories1(Category1) 474@end 475@interface CompareMismatchingCategories2: NSObject @end 476@interface CompareMismatchingCategories2(Category2) 477- (void)presentMethod; 478@end 479 480@interface CompareDifferentCategoryNames: NSObject @end 481@interface CompareDifferentCategoryNames(CategorySecond) 482- (void)secondMethod; 483@end 484#else 485CompareMatchingCategories *compareMatchingCategories; // no diagnostic 486CompareMismatchingCategories1 *compareMismatchingCategories1; 487#ifdef TEST_MODULAR 488// expected-warning@second.h:* {{duplicate definition of category 'Category1' on interface 'CompareMismatchingCategories1'}} 489// expected-note@first.h:* {{previous definition is here}} 490#endif 491CompareMismatchingCategories2 *compareMismatchingCategories2; 492#ifdef TEST_MODULAR 493// expected-warning@second.h:* {{duplicate definition of category 'Category2' on interface 'CompareMismatchingCategories2'}} 494// expected-note@first.h:* {{previous definition is here}} 495#endif 496CompareDifferentCategoryNames *compareDifferentCategoryNames; // no diagnostic 497#endif 498