332 lines · plain
1// Clear and create directories2// RUN: rm -rf %t3// RUN: mkdir %t4// RUN: mkdir %t/cache5// RUN: mkdir %t/Inputs6 7// Build first header file8// RUN: echo "#define FIRST" >> %t/Inputs/first.h9// RUN: cat %s >> %t/Inputs/first.h10 11// Build second header file12// RUN: echo "#define SECOND" >> %t/Inputs/second.h13// RUN: cat %s >> %t/Inputs/second.h14 15// Test that each header can compile16// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/first.h -fblocks -fobjc-arc17// RUN: %clang_cc1 -fsyntax-only -x objective-c++ %t/Inputs/second.h -fblocks -fobjc-arc18 19// Build module map file20// RUN: echo "module FirstModule {" >> %t/Inputs/module.modulemap21// RUN: echo " header \"first.h\"" >> %t/Inputs/module.modulemap22// RUN: echo "}" >> %t/Inputs/module.modulemap23// RUN: echo "module SecondModule {" >> %t/Inputs/module.modulemap24// RUN: echo " header \"second.h\"" >> %t/Inputs/module.modulemap25// RUN: echo "}" >> %t/Inputs/module.modulemap26 27// Run test28// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x objective-c++ -I%t/Inputs -verify %s -fblocks -fobjc-arc29 30#if !defined(FIRST) && !defined(SECOND)31#include "first.h"32#include "second.h"33#endif34 35#if defined(FIRST) || defined(SECOND)36@protocol P137@end38 39@protocol P240@end41 42@interface I143@end44 45@interface I2 : I146@end47 48@interface Interface1 <T : I1 *> {49@public50 T<P1> x;51}52@end53 54@interface Interface2 <T : I1 *>55@end56 57@interface Interface3 <T : I1 *>58@end59 60@interface EmptySelectorSlot61- (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@end67 68#endif69 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#else83S 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#endif87 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#else111auto 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 116auto function3 = valid;117#endif118} // namespace Attributed119 120namespace BlockPointer {121#if defined(FIRST)122void invalid1() {123 void (^x)(int);124}125void invalid2() {126 void (^x)(int);127}128void invalid3() {129 void (^x)(int);130}131void invalid4() {132 void (^x)(int);133}134void valid() {135 void (^x1)(int);136 int (^x2)(int);137 void (^x3)(int, int);138 void (^x4)(short);139}140#elif defined(SECOND)141void invalid1() {142 void (^x)();143}144void invalid2() {145 void (^x)(int, int);146}147void invalid3() {148 int (^x)(int);149}150void invalid4() {151 void (^x)(float);152}153void valid() {154 void (^x1)(int);155 int (^x2)(int);156 void (^x3)(int, int);157 void (^x4)(short);158}159#else160auto function1 = invalid1;161// expected-error@second.h:* {{'Types::BlockPointer::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}162// expected-note@first.h:* {{but in 'FirstModule' found a different body}}163auto function2 = invalid2;164// expected-error@second.h:* {{'Types::BlockPointer::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}165// expected-note@first.h:* {{but in 'FirstModule' found a different body}}166auto function3 = invalid3;167// expected-error@second.h:* {{'Types::BlockPointer::invalid3' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}168// expected-note@first.h:* {{but in 'FirstModule' found a different body}}169auto function4 = invalid4;170// expected-error@second.h:* {{'Types::BlockPointer::invalid4' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}171// expected-note@first.h:* {{but in 'FirstModule' found a different body}}172auto function5 = valid;173#endif174} // namespace BlockPointer175 176namespace ObjCObject {177#if defined(FIRST)178struct Invalid1 {179 using T = Interface2<I1*>;180};181struct Invalid2 {182 using T = Interface2<I1*>;183};184struct Invalid3 {185 using T = Interface2<P1, P1>;186};187struct Invalid4 {188 using T = Interface2<P1>;189};190struct Valid {191 using T1 = Interface2<I1*>;192 using T2 = Interface3<I1*>;193 using T3 = Interface2<P1>;194 using T4 = Interface3<P1, P2>;195 using T5 = __kindof Interface2;196};197#elif defined(SECOND)198struct Invalid1 {199 using T = Interface3<I1*>;200};201struct Invalid2 {202 using T = Interface2<I2*>;203};204struct Invalid3 {205 using T = Interface2<P1>;206};207struct Invalid4 {208 using T = Interface2<P2>;209};210struct Valid {211 using T1 = Interface2<I1*>;212 using T2 = Interface3<I1*>;213 using T3 = Interface2<P1>;214 using T4 = Interface3<P1, P2>;215 using T5 = __kindof Interface2;216};217#else218Invalid1 i1;219// expected-error@first.h:* {{'Types::ObjCObject::Invalid1::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid1' in module 'SecondModule'}}220// expected-note@second.h:* {{declaration of 'T' does not match}}221Invalid2 i2;222// expected-error@first.h:* {{'Types::ObjCObject::Invalid2::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid2' in module 'SecondModule'}}223// expected-note@second.h:* {{declaration of 'T' does not match}}224Invalid3 i3;225// 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>'}}226// expected-note@first.h:* {{but in 'FirstModule' found type alias 'T' with different underlying type 'Interface2<P1,P1>'}}227Invalid4 i4;228// expected-error@first.h:* {{'Types::ObjCObject::Invalid4::T' from module 'FirstModule' is not present in definition of 'Types::ObjCObject::Invalid4' in module 'SecondModule'}}229// expected-note@second.h:* {{declaration of 'T' does not match}}230Valid v;231#endif232} // namespace VisitObjCObject233} // namespace Types234 235#if defined(FIRST)236@interface Interface4 <T : I1 *> {237@public238 T<P1> x;239}240@end241@interface Interface5 <T : I1 *> {242@public243 T<P1> y;244}245@end246@interface Interface6 <T1 : I1 *, T2 : I2 *> {247@public248 T1 z;249}250@end251#elif defined(SECOND)252@interface Interface4 <T : I1 *> {253@public254 T<P2> x;255}256@end257@interface Interface5 <T : I1 *> {258@public259 T<P1, P2> y;260}261@end262@interface Interface6 <T1 : I1 *, T2 : I2 *> {263@public264 T2 z;265}266@end267#else268 269#endif270 271namespace Types {272namespace ObjCTypeParam {273#if defined(FIRST) || defined(SECOND)274struct Invalid1 {275 Interface4 *I;276 decltype(I->x) x;277};278struct Invalid2 {279 Interface5 *I;280 decltype(I->y) y;281};282struct Invalid3 {283 Interface6 *I;284 decltype(I->z) z;285};286#else287Invalid1 i1;288 289Invalid2 i2;290 291Invalid3 i3;292 293// FIXME: We should reject to merge these structs and diagnose for the294// different definitions for Interface4/Interface5/Interface6.295 296#endif297 298} // namespace ObjCTypeParam299} // namespace Types300 301namespace CallMethods {302#if defined(FIRST)303void invalid1(EmptySelectorSlot *obj) {304 [obj method:0];305}306void invalid2(EmptySelectorSlot *obj) {307 [obj multiple:0 args:0 :0];308}309#elif defined(SECOND)310void invalid1(EmptySelectorSlot *obj) {311 [obj method:0 :0];312}313void invalid2(EmptySelectorSlot *obj) {314 [obj multiple:0 :0 args:0];315}316#endif317// expected-error@second.h:* {{'CallMethods::invalid1' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}318// expected-note@first.h:* {{but in 'FirstModule' found a different body}}319 320// expected-error@second.h:* {{'CallMethods::invalid2' has different definitions in different modules; definition in module 'SecondModule' first difference is function body}}321// expected-note@first.h:* {{but in 'FirstModule' found a different body}}322} // namespace CallMethods323 324// Keep macros contained to one file.325#ifdef FIRST326#undef FIRST327#endif328 329#ifdef SECOND330#undef SECOND331#endif332