1
- // Copyright (c) 2022 The Pybind Development Team.
2
- // All rights reserved. Use of this source code is governed by a
3
- // BSD-style license that can be found in the LICENSE file.
4
1
/*
5
2
pybind11/detail/descr.h: Helper type for concatenating type signatures at compile time
6
3
@@ -23,106 +20,21 @@ PYBIND11_NAMESPACE_BEGIN(detail)
23
20
# define PYBIND11_DESCR_CONSTEXPR const
24
21
#endif
25
22
26
- // struct src_loc below is to support type_caster_odr_guard.h
27
- // (see https://github.com/pybind/pybind11/pull/4022).
28
- // The ODR guard creates ODR violations itself (see WARNING below & in type_caster_odr_guard.h),
29
- // but is currently the only tool available.
30
- // The ODR is useful to know *for sure* what is safe and what is not, but that is only a
31
- // subset of what actually works in practice, in a specific environment. The implementation
32
- // here exploits the gray area (similar to a white hat hacker).
33
- // The dedicated test_type_caster_odr_guard_1, test_type_caster_odr_guard_2 pair of unit tests
34
- // passes reliably on almost all platforms that meet the compiler requirements (C++17, C++20),
35
- // except one (gcc 9.4.0 debug build).
36
- // In the pybind11 unit tests we want to test the ODR guard in as many environments as possible,
37
- // but it is NOT recommended to enable the guard in regular builds, production, or
38
- // debug. The guard is meant to be used similar to a sanitizer, to check for type_caster ODR
39
- // violations in binaries that are otherwise already fully tested and assumed to be healthy.
40
- //
41
- // * MSVC 2017 does not support __builtin_FILE(), __builtin_LINE().
42
- // * MSVC 193732825 C++17 windows-2020 is failing for unknown reasons.
43
- // * Intel 2021.6.0.20220226 (g++ 9.4 mode) __builtin_LINE() is unreliable
44
- // (line numbers vary between translation units).
45
- #if defined(PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD_IF_AVAILABLE) \
46
- && !defined(PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD) && defined(PYBIND11_CPP17) \
47
- && !defined(__INTEL_COMPILER) \
48
- && (!defined(_MSC_VER) \
49
- || (_MSC_VER >= 1920 /* MSVC 2019 or newer */ \
50
- && (_MSC_FULL_VER < 193732825 || _MSC_FULL_VER > 193732826 \
51
- || defined(PYBIND11_CPP20))))
52
- # define PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD
53
- #endif
54
-
55
- #if defined(PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD)
56
-
57
- // Not using std::source_location because:
58
- // 1. "It is unspecified whether the copy/move constructors and the copy/move
59
- // assignment operators of source_location are trivial and/or constexpr."
60
- // (https://en.cppreference.com/w/cpp/utility/source_location).
61
- // 2. A matching no-op stub is needed (below) to avoid code duplication.
62
- struct src_loc {
63
- const char *file;
64
- unsigned line;
65
-
66
- constexpr src_loc (const char *file, unsigned line) : file(file), line(line) {}
67
-
68
- static constexpr src_loc here (const char *file = __builtin_FILE(),
69
- unsigned line = __builtin_LINE()) {
70
- return src_loc (file, line);
71
- }
72
-
73
- constexpr src_loc if_known_or (const src_loc &other) const {
74
- if (file != nullptr ) {
75
- return *this ;
76
- }
77
- return other;
78
- }
79
- };
80
-
81
- #else
82
-
83
- // No-op stub, to avoid code duplication, expected to be optimized out completely.
84
- struct src_loc {
85
- constexpr src_loc (const char *, unsigned ) {}
86
-
87
- static constexpr src_loc here (const char * = nullptr , unsigned = 0 ) {
88
- return src_loc (nullptr , 0 );
89
- }
90
-
91
- constexpr src_loc if_known_or (const src_loc &) const { return *this ; }
92
- };
93
-
94
- #endif
95
-
96
- #if defined(PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD)
97
- namespace { // WARNING: This creates an ODR violation in the ODR guard itself,
98
- // but we do not have any alternative at the moment.
99
- // The ODR violation here is a difference in constexpr between multiple TUs.
100
- // All definitions have the same data layout, the only difference is the
101
- // text const char* pointee (the pointees are identical in value),
102
- // src_loc const char* file pointee (the pointees are different in value),
103
- // src_loc unsigned line value.
104
- // See also: Comment above; WARNING in type_caster_odr_guard.h
105
- #endif
106
-
107
23
/* Concatenate type signatures at compile time */
108
24
template <size_t N, typename ... Ts>
109
25
struct descr {
110
26
char text[N + 1 ]{' \0 ' };
111
- const src_loc sloc;
112
27
113
- explicit constexpr descr (src_loc sloc) : sloc(sloc) {}
28
+ constexpr descr () = default;
114
29
// NOLINTNEXTLINE(google-explicit-constructor)
115
- constexpr descr (char const (&s)[N + 1], src_loc sloc = src_loc::here())
116
- : descr(s, make_index_sequence<N>(), sloc) {}
30
+ constexpr descr (char const (&s)[N + 1]) : descr(s, make_index_sequence<N>()) {}
117
31
118
32
template <size_t ... Is>
119
- constexpr descr (char const (&s)[N + 1], index_sequence<Is...>, src_loc sloc = src_loc::here())
120
- : text{s[Is]..., ' \0 ' }, sloc(sloc) {}
33
+ constexpr descr (char const (&s)[N + 1], index_sequence<Is...>) : text{s[Is]..., ' \0 ' } {}
121
34
122
35
template <typename ... Chars>
123
36
// NOLINTNEXTLINE(google-explicit-constructor)
124
- constexpr descr (src_loc sloc, char c, Chars... cs)
125
- : text{c, static_cast <char >(cs)..., ' \0 ' }, sloc(sloc) {}
37
+ constexpr descr (char c, Chars... cs) : text{c, static_cast <char >(cs)..., ' \0 ' } {}
126
38
127
39
static constexpr std::array<const std::type_info *, sizeof ...(Ts) + 1> types() {
128
40
return {{&typeid (Ts)..., nullptr }};
@@ -135,8 +47,7 @@ constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a,
135
47
index_sequence<Is1...>,
136
48
index_sequence<Is2...>) {
137
49
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100 (b);
138
- return descr<N1 + N2, Ts1..., Ts2...>{
139
- a.sloc .if_known_or (b.sloc ), a.text [Is1]..., b.text [Is2]...};
50
+ return {a.text [Is1]..., b.text [Is2]...};
140
51
}
141
52
142
53
template <size_t N1, size_t N2, typename ... Ts1, typename ... Ts2>
@@ -146,33 +57,27 @@ constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a,
146
57
}
147
58
148
59
template <size_t N>
149
- constexpr descr<N - 1 > const_name (char const (&text)[N], src_loc sloc = src_loc::here()) {
150
- return descr<N - 1 >(text, sloc);
151
- }
152
- constexpr descr<0 > const_name (char const (&)[1], src_loc sloc = src_loc::here()) {
153
- return descr<0 >(sloc);
60
+ constexpr descr<N - 1 > const_name (char const (&text)[N]) {
61
+ return descr<N - 1 >(text);
154
62
}
63
+ constexpr descr<0 > const_name (char const (&)[1]) { return {}; }
155
64
156
65
template <size_t Rem, size_t ... Digits>
157
66
struct int_to_str : int_to_str<Rem / 10 , Rem % 10 , Digits...> {};
158
67
template <size_t ... Digits>
159
68
struct int_to_str <0 , Digits...> {
160
69
// WARNING: This only works with C++17 or higher.
161
- // src_loc not tracked (not needed in this situation, at least at the moment).
162
- static constexpr auto digits
163
- = descr<sizeof ...(Digits)>(src_loc{nullptr , 0 }, (' 0' + Digits)...);
70
+ static constexpr auto digits = descr<sizeof ...(Digits)>((' 0' + Digits)...);
164
71
};
165
72
166
73
// Ternary description (like std::conditional)
167
74
template <bool B, size_t N1, size_t N2>
168
- constexpr enable_if_t <B, descr<N1 - 1 >>
169
- const_name (char const (&text1)[N1], char const (&)[N2], src_loc sloc = src_loc::here()) {
170
- return const_name (text1, sloc);
75
+ constexpr enable_if_t <B, descr<N1 - 1 >> const_name (char const (&text1)[N1], char const (&)[N2]) {
76
+ return const_name (text1);
171
77
}
172
78
template <bool B, size_t N1, size_t N2>
173
- constexpr enable_if_t <!B, descr<N2 - 1 >>
174
- const_name (char const (&)[N1], char const (&text2)[N2], src_loc sloc = src_loc::here()) {
175
- return const_name (text2, sloc);
79
+ constexpr enable_if_t <!B, descr<N2 - 1 >> const_name (char const (&)[N1], char const (&text2)[N2]) {
80
+ return const_name (text2);
176
81
}
177
82
178
83
template <bool B, typename T1, typename T2>
@@ -186,13 +91,12 @@ constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) {
186
91
187
92
template <size_t Size>
188
93
auto constexpr const_name () -> remove_cv_t<decltype(int_to_str<Size / 10 , Size % 10 >::digits)> {
189
- // src_loc not tracked (not needed in this situation, at least at the moment).
190
94
return int_to_str<Size / 10 , Size % 10 >::digits;
191
95
}
192
96
193
97
template <typename Type>
194
- constexpr descr<1 , Type> const_name (src_loc sloc = src_loc::here() ) {
195
- return {sloc, ' %' };
98
+ constexpr descr<1 , Type> const_name () {
99
+ return {' %' };
196
100
}
197
101
198
102
// If "_" is defined as a macro, py::detail::_ cannot be provided.
@@ -202,18 +106,16 @@ constexpr descr<1, Type> const_name(src_loc sloc = src_loc::here()) {
202
106
#ifndef _
203
107
# define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
204
108
template <size_t N>
205
- constexpr descr<N - 1 > _ (char const (&text)[N], src_loc sloc = src_loc::here() ) {
206
- return const_name<N>(text, sloc );
109
+ constexpr descr<N - 1 > _ (char const (&text)[N]) {
110
+ return const_name<N>(text);
207
111
}
208
112
template <bool B, size_t N1, size_t N2>
209
- constexpr enable_if_t <B, descr<N1 - 1 >>
210
- _ (char const (&text1)[N1], char const (&text2)[N2], src_loc sloc = src_loc::here()) {
211
- return const_name<B, N1, N2>(text1, text2, sloc);
113
+ constexpr enable_if_t <B, descr<N1 - 1 >> _ (char const (&text1)[N1], char const (&text2)[N2]) {
114
+ return const_name<B, N1, N2>(text1, text2);
212
115
}
213
116
template <bool B, size_t N1, size_t N2>
214
- constexpr enable_if_t <!B, descr<N2 - 1 >>
215
- _ (char const (&text1)[N1], char const (&text2)[N2], src_loc sloc = src_loc::here()) {
216
- return const_name<B, N1, N2>(text1, text2, sloc);
117
+ constexpr enable_if_t <!B, descr<N2 - 1 >> _ (char const (&text1)[N1], char const (&text2)[N2]) {
118
+ return const_name<B, N1, N2>(text1, text2);
217
119
}
218
120
template <bool B, typename T1, typename T2>
219
121
constexpr enable_if_t <B, T1> _ (const T1 &d1, const T2 &d2) {
@@ -226,16 +128,15 @@ constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) {
226
128
227
129
template <size_t Size>
228
130
auto constexpr _ () -> remove_cv_t<decltype(int_to_str<Size / 10 , Size % 10 >::digits)> {
229
- // src_loc not tracked (not needed in this situation, at least at the moment).
230
131
return const_name<Size>();
231
132
}
232
133
template <typename Type>
233
- constexpr descr<1 , Type> _ (src_loc sloc = src_loc::here() ) {
234
- return const_name<Type>(sloc );
134
+ constexpr descr<1 , Type> _ () {
135
+ return const_name<Type>();
235
136
}
236
137
#endif // #ifndef _
237
138
238
- constexpr descr<0 > concat (src_loc sloc = src_loc::here()) { return descr< 0 >{sloc }; }
139
+ constexpr descr<0 > concat () { return { }; }
239
140
240
141
template <size_t N, typename ... Ts>
241
142
constexpr descr<N, Ts...> concat (const descr<N, Ts...> &descr) {
@@ -246,8 +147,7 @@ constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
246
147
template <size_t N1, size_t N2, typename ... Ts1, typename ... Ts2>
247
148
constexpr descr<N1 + N2 + 2 , Ts1..., Ts2...> operator ,(const descr<N1, Ts1...> &a,
248
149
const descr<N2, Ts2...> &b) {
249
- // Ensure that src_loc of existing descr is used.
250
- return a + const_name (" , " , src_loc{nullptr , 0 }) + b;
150
+ return a + const_name (" , " ) + b;
251
151
}
252
152
253
153
template <size_t N, typename ... Ts, typename ... Args>
@@ -259,20 +159,14 @@ template <size_t N, typename... Ts, typename... Args>
259
159
constexpr auto concat (const descr<N, Ts...> &d,
260
160
const Args &...args) -> decltype(std::declval<descr<N + 2 , Ts...>>()
261
161
+ concat(args...)) {
262
- // Ensure that src_loc of existing descr is used.
263
- return d + const_name (" , " , src_loc{nullptr , 0 }) + concat (args...);
162
+ return d + const_name (" , " ) + concat (args...);
264
163
}
265
164
#endif
266
165
267
166
template <size_t N, typename ... Ts>
268
167
constexpr descr<N + 2 , Ts...> type_descr (const descr<N, Ts...> &descr) {
269
- // Ensure that src_loc of existing descr is used.
270
- return const_name (" {" , src_loc{nullptr , 0 }) + descr + const_name (" }" );
168
+ return const_name (" {" ) + descr + const_name (" }" );
271
169
}
272
170
273
- #if defined(PYBIND11_ENABLE_TYPE_CASTER_ODR_GUARD)
274
- } // namespace
275
- #endif
276
-
277
171
PYBIND11_NAMESPACE_END (detail)
278
172
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
0 commit comments