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 c++ -std=c++11 -fblocks %t/Inputs/first.h |
17 | // RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++11 -fblocks %t/Inputs/second.h |
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 \ |
29 | // RUN: -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs \ |
30 | // RUN: -verify %s -std=c++11 -fblocks |
31 | |
32 | #if !defined(FIRST) && !defined(SECOND) |
33 | #include "first.h" |
34 | #include "second.h" |
35 | #endif |
36 | |
37 | // Used for testing |
38 | #if defined(FIRST) |
39 | #define ACCESS public: |
40 | #elif defined(SECOND) |
41 | #define ACCESS private: |
42 | #endif |
43 | |
44 | // TODO: S1 and S2 should generate errors. |
45 | namespace Blocks { |
46 | #if defined(FIRST) |
47 | struct S1 { |
48 | void (^block)(int x) = ^(int x) { }; |
49 | }; |
50 | #elif defined(SECOND) |
51 | struct S1 { |
52 | void (^block)(int x) = ^(int y) { }; |
53 | }; |
54 | #else |
55 | S1 s1; |
56 | #endif |
57 | |
58 | #if defined(FIRST) |
59 | struct S2 { |
60 | int (^block)(int x) = ^(int x) { return x + 1; }; |
61 | }; |
62 | #elif defined(SECOND) |
63 | struct S2 { |
64 | int (^block)(int x) = ^(int x) { return x; }; |
65 | }; |
66 | #else |
67 | S2 s2; |
68 | #endif |
69 | |
70 | #if defined(FIRST) |
71 | struct S3 { |
72 | void run(int (^block)(int x)); |
73 | }; |
74 | #elif defined(SECOND) |
75 | struct S3 { |
76 | void run(int (^block)(int x, int y)); |
77 | }; |
78 | #else |
79 | S3 s3; |
80 | // expected-error@first.h:* {{'Blocks::S3::run' from module 'FirstModule' is not present in definition of 'Blocks::S3' in module 'SecondModule'}} |
81 | // expected-note@second.h:* {{declaration of 'run' does not match}} |
82 | #endif |
83 | |
84 | #define DECLS \ |
85 | int (^block)(int x) = ^(int x) { return x + x; }; \ |
86 | void run(int (^block)(int x, int y)); |
87 | |
88 | #if defined(FIRST) || defined(SECOND) |
89 | struct Valid1 { |
90 | DECLS |
91 | }; |
92 | #else |
93 | Valid1 v1; |
94 | #endif |
95 | |
96 | #if defined(FIRST) || defined(SECOND) |
97 | struct Invalid1 { |
98 | DECLS |
99 | ACCESS |
100 | }; |
101 | #else |
102 | Invalid1 i1; |
103 | // expected-error@second.h:* {{'Blocks::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} |
104 | // expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} |
105 | #endif |
106 | |
107 | #undef DECLS |
108 | } |
109 | |
110 | // Keep macros contained to one file. |
111 | #ifdef FIRST |
112 | #undef FIRST |
113 | #endif |
114 | |
115 | #ifdef SECOND |
116 | #undef SECOND |
117 | #endif |
118 | |
119 | #ifdef ACCESS |
120 | #undef ACCESS |
121 | #endif |
122 | |