xref: /llvm-project/clang/test/Modules/odr_hash-gnu.cpp (revision a171d248ca34b8b6f8de11d42a83ad981285963a)
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=gnu++11 %t/Inputs/first.h
17 // RUN: %clang_cc1 -fsyntax-only -x c++ -std=gnu++11 %t/Inputs/second.h
18 
19 // Build module map file
20 // RUN: echo "module FirstModule {"     >> %t/Inputs/module.modulemap
21 // RUN: echo "    header \"first.h\""   >> %t/Inputs/module.modulemap
22 // RUN: echo "}"                        >> %t/Inputs/module.modulemap
23 // RUN: echo "module SecondModule {"    >> %t/Inputs/module.modulemap
24 // RUN: echo "    header \"second.h\""  >> %t/Inputs/module.modulemap
25 // RUN: echo "}"                        >> %t/Inputs/module.modulemap
26 
27 // Run test
28 // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/cache -x c++ -I%t/Inputs -verify %s -std=gnu++11
29 
30 #if !defined(FIRST) && !defined(SECOND)
31 #include "first.h"
32 #include "second.h"
33 #endif
34 
35 namespace Types {
36 namespace TypeOfExpr {
37 #if defined(FIRST)
38 struct Invalid1 {
39   typeof(1 + 2) x;
40 };
41 double global;
42 struct Invalid2 {
43   typeof(global) x;
44 };
45 struct Valid {
46   typeof(3) x;
47   typeof(x) y;
48   typeof(Valid*) self;
49 };
50 #elif defined(SECOND)
51 struct Invalid1 {
52   typeof(3) x;
53 };
54 int global;
55 struct Invalid2 {
56   typeof(global) x;
57 };
58 struct Valid {
59   typeof(3) x;
60   typeof(x) y;
61   typeof(Valid*) self;
62 };
63 #else
64 Invalid1 i1;
65 // expected-error@first.h:* {{'Types::TypeOfExpr::Invalid1' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof (1 + 2)' (aka 'int')}}
66 // expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof (3)' (aka 'int')}}
67 Invalid2 i2;
68 
69 Valid v;
70 
71 // FIXME: We should diagnose the different definitions of `global`.
72 #endif
73 }  // namespace TypeOfExpr
74 
75 namespace TypeOf {
76 #if defined(FIRST)
77 struct Invalid1 {
78   typeof(int) x;
79 };
80 struct Invalid2 {
81   typeof(int) x;
82 };
83 using T = int;
84 struct Invalid3 {
85   typeof(T) x;
86 };
87 struct Valid {
88   typeof(int) x;
89   using T = typeof(double);
90   typeof(T) y;
91 };
92 #elif defined(SECOND)
93 struct Invalid1 {
94   typeof(double) x;
95 };
96 using I = int;
97 struct Invalid2 {
98   typeof(I) x;
99 };
100 using T = short;
101 struct Invalid3 {
102   typeof(T) x;
103 };
104 struct Valid {
105   typeof(int) x;
106   using T = typeof(double);
107   typeof(T) y;
108 };
109 #else
110 Invalid1 i1;
111 // expected-error@second.h:* {{'Types::TypeOf::Invalid1::x' from module 'SecondModule' is not present in definition of 'Types::TypeOf::Invalid1' in module 'FirstModule'}}
112 // expected-note@first.h:* {{declaration of 'x' does not match}}
113 Invalid2 i2;
114 // expected-error@first.h:* {{'Types::TypeOf::Invalid2' has different definitions in different modules; first difference is definition in module 'FirstModule' found field 'x' with type 'typeof(int)' (aka 'int')}}
115 // expected-note@second.h:* {{but in 'SecondModule' found field 'x' with type 'typeof(I)' (aka 'int')}}
116 Invalid3 i3;
117 
118 // FIXME: We should reject the `Invalid3` due to the inconsistent definition of `T`.
119 
120 Valid v;
121 #endif
122 }  // namespace TypeOf
123 }  // namespace Types
124 
125 // Keep macros contained to one file.
126 #ifdef FIRST
127 #undef FIRST
128 #endif
129 
130 #ifdef SECOND
131 #undef SECOND
132 #endif
133