xref: /llvm-project/clang/test/Modules/pr64091.cpp (revision 7c1d9b15eee3a34678addab2bab66f3020ac0753)
1 // RUN: rm -rf %t
2 // RUN: mkdir %t
3 // RUN: split-file %s %t
4 //
5 // RUN: cd %t
6 //
7 // RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=c \
8 // RUN:     -fmodule-map-file=c.cppmap -xc++ c.cppmap -emit-module -o c.pcm
9 // RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=a \
10 // RUN:     -fmodule-map-file=a.cppmap -fmodule-map-file=c.cppmap -xc++ a.cppmap \
11 // RUN:     -emit-module -o a.pcm
12 // RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=b \
13 // RUN:     -fmodule-map-file=b.cppmap -fmodule-map-file=c.cppmap -xc++ b.cppmap \
14 // RUN:     -emit-module -o b.pcm
15 // RUN: %clang_cc1 -fmodules -fno-implicit-modules -fmodule-name=test \
16 // RUN:     -fmodule-map-file=test.cppmap -fmodule-map-file=a.cppmap \
17 // RUN:     -fmodule-map-file=b.cppmap -fmodule-file=a.pcm -fmodule-file=b.pcm -xc++ \
18 // RUN:     test.cc -emit-llvm -o - | FileCheck test.cc
19 
20 //--- a.cppmap
21 module "a" {
22   export *
23   module "a.h" {
24     export *
25     header "a.h"
26   }
27   use "c"
28 }
29 
30 //--- b.cppmap
31 module "b" {
32   export *
33   module "b.h" {
34     export *
35     header "b.h"
36   }
37   use "c"
38 }
39 
40 //--- c.cppmap
41 module "c" {
42   export *
43   module "c1.h" {
44     export *
45     textual header "c1.h"
46   }
47   module "c2.h" {
48     export *
49     textual header "c2.h"
50   }
51   module "c3.h" {
52     export *
53     textual header "c3.h"
54   }
55 }
56 
57 //--- test.cppmap
58 module "test" {
59   export *
60   use "a"
61   use "b"
62 }
63 
64 //--- a.h
65 #ifndef A_H_
66 #define A_H_
67 
68 #include "c1.h"
69 
70 namespace q {
71 template <typename T,
72           typename std::enable_if<::p::P<T>::value>::type>
73 class X {};
74 }  // namespace q
75 
76 #include "c3.h"
77 
78 #endif  // A_H_
79 
80 //--- b.h
81 #ifndef B_H_
82 #define B_H_
83 
84 #include "c2.h"
85 
86 #endif  // B_H_
87 
88 //--- c1.h
89 #ifndef C1_H_
90 #define C1_H_
91 
92 namespace std {
93 template <class _Tp, _Tp __v>
94 struct integral_constant {
95   static constexpr const _Tp value = __v;
96   typedef _Tp value_type;
97   typedef integral_constant type;
98   constexpr operator value_type() const noexcept { return value; }
99   constexpr value_type operator()() const noexcept { return value; }
100 };
101 
102 template <class _Tp, _Tp __v>
103 constexpr const _Tp integral_constant<_Tp, __v>::value;
104 
105 typedef integral_constant<bool, true> true_type;
106 typedef integral_constant<bool, false> false_type;
107 
108 template <bool, class _Tp = void>
109 struct enable_if {};
110 template <class _Tp>
111 struct enable_if<true, _Tp> {
112   typedef _Tp type;
113 };
114 }  // namespace std
115 
116 namespace p {
117 template <typename T>
118 struct P : ::std::false_type {};
119 }
120 
121 #endif  // C1_H_
122 
123 //--- c2.h
124 #ifndef C2_H_
125 #define C2_H_
126 
127 #include "c3.h"
128 
129 enum E {};
130 namespace p {
131 template <>
132 struct P<E> : std::true_type {};
133 }  // namespace proto2
134 
f(::util::EnumErrorSpace<E>)135 inline void f(::util::EnumErrorSpace<E>) {}
136 
137 #endif  // C2_H_
138 
139 //--- c3.h
140 #ifndef C3_H_
141 #define C3_H_
142 
143 #include "c1.h"
144 
145 namespace util {
146 
147 template <typename T>
148 class ErrorSpaceImpl;
149 
150 class ErrorSpace {
151  protected:
152   template <bool* addr>
153   struct OdrUse {
OdrUseutil::ErrorSpace::OdrUse154     constexpr OdrUse() : b(*addr) {}
155     bool& b;
156   };
157   template <typename T>
158   struct Registerer {
159     static bool register_token;
160     static constexpr OdrUse<&register_token> kRegisterTokenUse{};
161   };
162 
163  private:
164   template <typename T>
GetBase()165   static const ErrorSpace* GetBase() {
166     return 0;
167   }
168 
Register(const ErrorSpace * (* space)())169   static bool Register(const ErrorSpace* (*space)()) { return true; }
170 };
171 
172 template <typename T>
173 bool ErrorSpace::Registerer<T>::register_token =
174     Register(&ErrorSpace::GetBase<T>);
175 
176 template <typename T>
177 class ErrorSpaceImpl : public ErrorSpace {
178  private:
179   static constexpr Registerer<ErrorSpaceImpl> kRegisterer{};
180 };
181 
182 template <typename T, typename = typename std::enable_if<p::P<T>::value>::type>
183 class EnumErrorSpace : public ErrorSpaceImpl<EnumErrorSpace<T>> {};
184 
185 }  // namespace util
186 #endif // C3_H_
187 
188 //--- test.cc
189 #include "a.h"
190 #include "b.h"
191 
main(int,char **)192 int main(int, char**) {}
193 
194 // CHECK-NOT: error
195