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