]> git.lyx.org Git - lyx.git/blob - 3rdparty/boost/boost/type_index/detail/compile_time_type_info.hpp
Update to boost 1.72
[lyx.git] / 3rdparty / boost / boost / type_index / detail / compile_time_type_info.hpp
1 //
2 // Copyright (c) 2012-2019 Antony Polukhin.
3 //
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8
9 #ifndef BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
10 #define BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP
11
12 /// \file compile_time_type_info.hpp
13 /// \brief Contains helper macros and implementation details of boost::typeindex::ctti_type_index.
14 /// Not intended for inclusion from user's code.
15
16 #include <cstring>
17 #include <boost/config.hpp>
18 #include <boost/static_assert.hpp>
19 #include <boost/type_traits/integral_constant.hpp>
20
21 #ifdef BOOST_HAS_PRAGMA_ONCE
22 # pragma once
23 #endif
24
25 /// @cond
26 #if defined(__has_builtin)
27 #if __has_builtin(__builtin_constant_p)
28 #define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
29 #endif
30 #if __has_builtin(__builtin_strcmp)
31 #define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
32 #endif
33 #elif defined(__GNUC__)
34 #define BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(x) __builtin_constant_p(x)
35 #define BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(str1, str2) __builtin_strcmp(str1, str2)
36 #endif
37
38 #define BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(begin_skip, end_skip, runtime_skip, runtime_skip_until)   \
39     namespace boost { namespace typeindex { namespace detail {                                                  \
40         BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_begin  = begin_skip;                               \
41         BOOST_STATIC_CONSTEXPR std::size_t ctti_skip_size_at_end    = end_skip;                                 \
42         BOOST_STATIC_CONSTEXPR bool ctti_skip_more_at_runtime       = runtime_skip;                             \
43         BOOST_STATIC_CONSTEXPR char ctti_skip_until_runtime[]       = runtime_skip_until;                       \
44     }}} /* namespace boost::typeindex::detail */                                                                \
45     /**/
46 /// @endcond
47
48
49 #if defined(BOOST_TYPE_INDEX_DOXYGEN_INVOKED)
50     /* Nothing to document. All the macro docs are moved to <boost/type_index.hpp> */
51 #elif defined(BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING)
52 #   include <boost/preprocessor/facilities/expand.hpp>
53     BOOST_PP_EXPAND( BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING )
54 #elif defined(_MSC_VER) && !defined(__clang__) && defined (BOOST_NO_CXX11_NOEXCEPT)
55     // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void)") - 1
56     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 10, false, "")
57 #elif defined(_MSC_VER) && !defined(__clang__) && !defined (BOOST_NO_CXX11_NOEXCEPT)
58     // sizeof("const char *__cdecl boost::detail::ctti<") - 1, sizeof(">::n(void) noexcept") - 1
59     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(40, 19, false, "")
60 #elif defined(__clang__) && defined(__APPLE__)
61     // Someone made __clang_major__ equal to LLVM version rather than compiler version
62     // on APPLE platform.
63     //
64     // Using less efficient solution because there is no good way to detect real version of Clang.
65     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "???????????>::n() [T = int"
66     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
67 #elif defined(__clang__) && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ == 0))
68     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof(">::n()") - 1
69     // note: checked on 3.0
70     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 6, false, "")
71 #elif defined(__clang__) && (__clang_major__ >= 4 || (__clang_major__ == 3 && __clang_minor__ > 0))
72     // sizeof("static const char *boost::detail::ctti<") - 1, sizeof("]") - 1, true, "int>::n() [T = int"
73     // note: checked on 3.1, 3.4
74     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(39, 1, true, "T = ")
75 #elif defined(__EDG__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
76     // sizeof("static cha boost::detail::ctti<T>::s() [with I = 40U, T = ") - 1, sizeof("]") - 1
77     // note: checked on 4.14
78     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(58, 1, false, "")
79 #elif defined(__EDG__) && defined(BOOST_NO_CXX14_CONSTEXPR)
80     // sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
81     // note: checked on 4.14
82     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
83 #elif defined(__GNUC__) && (__GNUC__ < 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
84     // sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0u; T = ") - 1, sizeof("]") - 1
85     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(81, 1, false, "")
86 #elif defined(__GNUC__) && (__GNUC__ >= 7) && !defined(BOOST_NO_CXX14_CONSTEXPR)
87     // sizeof("static constexpr char boost::detail::ctti<T>::s() [with unsigned int I = 0; T = ") - 1, sizeof("]") - 1
88     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(80, 1, false, "")
89 #elif defined(__GNUC__) && defined(BOOST_NO_CXX14_CONSTEXPR)
90     // sizeof("static const char* boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
91     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
92 #elif defined(__ghs__)
93     // sizeof("static const char *boost::detail::ctti<T>::n() [with T = ") - 1, sizeof("]") - 1
94     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(57, 1, false, "")
95 #else
96     // Deafult code for other platforms... Just skip nothing!
97     BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS(0, 0, false, "")
98 #endif
99
100 #undef BOOST_TYPE_INDEX_REGISTER_CTTI_PARSING_PARAMS
101
102 namespace boost { namespace typeindex { namespace detail {
103     template <bool Condition>
104     BOOST_CXX14_CONSTEXPR inline void assert_compile_time_legths() BOOST_NOEXCEPT {
105         BOOST_STATIC_ASSERT_MSG(
106             Condition,
107             "TypeIndex library is misconfigured for your compiler. "
108             "Please define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct values. See section "
109             "'RTTI emulation limitations' of the documentation for more information."
110         );
111     }
112
113     template <class T>
114     BOOST_CXX14_CONSTEXPR inline void failed_to_get_function_name() BOOST_NOEXCEPT {
115         BOOST_STATIC_ASSERT_MSG(
116             sizeof(T) && false,
117             "TypeIndex library could not detect your compiler. "
118             "Please make the BOOST_TYPE_INDEX_FUNCTION_SIGNATURE macro use "
119             "correct compiler macro for getting the whole function name. "
120             "Define BOOST_TYPE_INDEX_CTTI_USER_DEFINED_PARSING to correct value after that."
121         );
122     }
123
124 #if defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
125     BOOST_CXX14_CONSTEXPR BOOST_FORCEINLINE bool is_constant_string(const char* str) BOOST_NOEXCEPT {
126         while (BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT(*str)) {
127             if (*str == '\0')
128                 return true;
129             ++str;
130         }
131         return false;
132     }
133 #endif // defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT)
134
135     template <unsigned int ArrayLength>
136     BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::false_type) BOOST_NOEXCEPT {
137         return begin;
138     }
139
140     template<class ForwardIterator1, class ForwardIterator2>
141     BOOST_CXX14_CONSTEXPR inline ForwardIterator1 constexpr_search(
142         ForwardIterator1 first1,
143         ForwardIterator1 last1,
144         ForwardIterator2 first2,
145         ForwardIterator2 last2) BOOST_NOEXCEPT
146     {
147         if (first2 == last2) {
148             return first1;  // specified in C++11
149         }
150
151         while (first1 != last1) {
152             ForwardIterator1 it1 = first1;
153             ForwardIterator2 it2 = first2;
154
155             while (*it1 == *it2) {
156                 ++it1;
157                 ++it2;
158                 if (it2 == last2) return first1;
159                 if (it1 == last1) return last1;
160             }
161
162             ++first1;
163         }
164
165         return last1;
166     }
167
168     BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp_loop(const char *v1, const char *v2) BOOST_NOEXCEPT {
169         while (*v1 != '\0' && *v1 == *v2) {
170             ++v1;
171             ++v2;
172         }
173
174         return static_cast<int>(*v1) - *v2;
175     }
176
177     BOOST_CXX14_CONSTEXPR inline int constexpr_strcmp(const char *v1, const char *v2) BOOST_NOEXCEPT {
178 #if !defined(BOOST_NO_CXX14_CONSTEXPR) && defined(BOOST_TYPE_INDEX_DETAIL_IS_CONSTANT) && defined(BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP)
179         if (boost::typeindex::detail::is_constant_string(v1) && boost::typeindex::detail::is_constant_string(v2))
180             return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
181         return BOOST_TYPE_INDEX_DETAIL_BUILTIN_STRCMP(v1, v2);
182 #elif !defined(BOOST_NO_CXX14_CONSTEXPR)
183         return boost::typeindex::detail::constexpr_strcmp_loop(v1, v2);
184 #else
185         return std::strcmp(v1, v2);
186 #endif
187     }
188
189     template <unsigned int ArrayLength>
190     BOOST_CXX14_CONSTEXPR inline const char* skip_begining_runtime(const char* begin, boost::true_type) BOOST_NOEXCEPT {
191         const char* const it = constexpr_search(
192             begin, begin + ArrayLength,
193             ctti_skip_until_runtime, ctti_skip_until_runtime + sizeof(ctti_skip_until_runtime) - 1
194         );
195         return (it == begin + ArrayLength ? begin : it + sizeof(ctti_skip_until_runtime) - 1);
196     }
197
198     template <unsigned int ArrayLength>
199     BOOST_CXX14_CONSTEXPR inline const char* skip_begining(const char* begin) BOOST_NOEXCEPT {
200         assert_compile_time_legths<(ArrayLength > ctti_skip_size_at_begin + ctti_skip_size_at_end)>();
201         return skip_begining_runtime<ArrayLength - ctti_skip_size_at_begin>(
202             begin + ctti_skip_size_at_begin,
203             boost::integral_constant<bool, ctti_skip_more_at_runtime>()
204         );
205     }
206
207 #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
208     template <unsigned int... I>
209     struct index_seq {};
210
211     template <typename Left, typename Right>
212     struct make_index_sequence_join;
213
214     template <unsigned int... Left, unsigned int... Right>
215     struct make_index_sequence_join<index_seq<Left...>, index_seq<Right...> > {
216         typedef index_seq<Left..., Right...> type;
217     };
218
219     template <unsigned int C, unsigned int D>
220     struct make_index_seq_impl {
221         typedef typename make_index_sequence_join<
222             typename make_index_seq_impl<C, D / 2>::type,
223             typename make_index_seq_impl<C + D / 2, (D + 1) / 2>::type
224         >::type type;
225     };
226
227     template <unsigned int C>
228     struct make_index_seq_impl<C, 0> {
229         typedef index_seq<> type;
230     };
231
232     template <unsigned int C>
233     struct make_index_seq_impl<C, 1> {
234         typedef index_seq<C> type;
235     };
236
237     template <char... C>
238     struct cstring {
239         static constexpr unsigned int size_ = sizeof...(C);
240         static constexpr char data_[size_] = { C... };
241     };
242
243     template <char... C>
244     constexpr char cstring<C...>::data_[];
245 #endif
246
247 }}} // namespace boost::typeindex::detail
248
249 namespace boost { namespace detail {
250
251 /// Noncopyable type_info that does not require RTTI.
252 /// CTTI == Compile Time Type Info.
253 /// This name must be as short as possible, to avoid code bloat
254 template <class T>
255 struct ctti {
256
257 #if !defined(__clang__) && defined(__GNUC__) && !defined(BOOST_NO_CXX14_CONSTEXPR)
258     //helper functions
259     template <unsigned int I>
260     constexpr static char s() BOOST_NOEXCEPT { // step
261         constexpr unsigned int offset =
262                   (I >= 10u      ? 1u : 0u)
263                 + (I >= 100u     ? 1u : 0u)
264                 + (I >= 1000u    ? 1u : 0u)
265                 + (I >= 10000u   ? 1u : 0u)
266                 + (I >= 100000u  ? 1u : 0u)
267                 + (I >= 1000000u ? 1u : 0u)
268         ;
269
270     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
271         return BOOST_TYPE_INDEX_FUNCTION_SIGNATURE[I + offset];
272     #elif defined(__FUNCSIG__)
273         return __FUNCSIG__[I + offset];
274     #else
275         return __PRETTY_FUNCTION__[I + offset];
276     #endif
277     }
278
279     template <unsigned int ...Indexes>
280     constexpr static const char* impl(::boost::typeindex::detail::index_seq<Indexes...> ) BOOST_NOEXCEPT {
281         return ::boost::typeindex::detail::cstring<s<Indexes>()...>::data_;
282     }
283
284     template <unsigned int D = 0> // `D` means `Dummy`
285     constexpr static const char* n() BOOST_NOEXCEPT {
286     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
287         constexpr unsigned int size = sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
288     #elif defined(__FUNCSIG__)
289         constexpr unsigned int size = sizeof(__FUNCSIG__);
290     #elif defined(__PRETTY_FUNCTION__) \
291                     || defined(__GNUC__) \
292                     || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
293                     || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
294                     || (defined(__ICC) && (__ICC >= 600)) \
295                     || defined(__ghs__) \
296                     || defined(__DMC__)
297         constexpr unsigned int size = sizeof(__PRETTY_FUNCTION__);
298     #else
299         boost::typeindex::detail::failed_to_get_function_name<T>();
300     #endif
301
302         boost::typeindex::detail::assert_compile_time_legths<
303             (size > boost::typeindex::detail::ctti_skip_size_at_begin + boost::typeindex::detail::ctti_skip_size_at_end + sizeof("const *") - 1)
304         >();
305         static_assert(!boost::typeindex::detail::ctti_skip_more_at_runtime, "Skipping for GCC in C++14 mode is unsupported");
306
307         typedef typename boost::typeindex::detail::make_index_seq_impl<
308             boost::typeindex::detail::ctti_skip_size_at_begin,
309             size - sizeof("const *") + 1 - boost::typeindex::detail::ctti_skip_size_at_begin
310         >::type idx_seq;
311         return impl(idx_seq());
312     }
313 #else
314     /// Returns raw name. Must be as short, as possible, to avoid code bloat
315     BOOST_CXX14_CONSTEXPR static const char* n() BOOST_NOEXCEPT {
316     #if defined(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE)
317         return boost::typeindex::detail::skip_begining< sizeof(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE) >(BOOST_TYPE_INDEX_FUNCTION_SIGNATURE);
318     #elif defined(__FUNCSIG__)
319         return boost::typeindex::detail::skip_begining< sizeof(__FUNCSIG__) >(__FUNCSIG__);
320     #elif defined(__PRETTY_FUNCTION__) \
321                 || defined(__GNUC__) \
322                 || (defined(__SUNPRO_CC) && (__SUNPRO_CC >= 0x5130)) \
323                 || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) \
324                 || (defined(__ICC) && (__ICC >= 600)) \
325                 || defined(__ghs__) \
326                 || defined(__DMC__) \
327                 || defined(__clang__)
328         return boost::typeindex::detail::skip_begining< sizeof(__PRETTY_FUNCTION__) >(__PRETTY_FUNCTION__);
329     #else
330         boost::typeindex::detail::failed_to_get_function_name<T>();
331         return "";
332     #endif
333     }
334 #endif
335 };
336
337 }} // namespace boost::detail
338
339 #endif // BOOST_TYPE_INDEX_DETAIL_COMPILE_TIME_TYPE_INFO_HPP