demangle.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #ifndef BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
  2. #define BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
  3. // Copyright 2018-2024 Emil Dotchevski and Reverge Studios, Inc.
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. // This file is based on boost::core::demangle
  7. //
  8. // Copyright 2014 Peter Dimov
  9. // Copyright 2014 Andrey Semashev
  10. //
  11. // Distributed under the Boost Software License, Version 1.0.
  12. // See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt
  14. #include <boost/leaf/config.hpp>
  15. #include <iosfwd>
  16. #include <cstdlib>
  17. #if BOOST_LEAF_CFG_DIAGNOSTICS
  18. // __has_include is currently supported by GCC and Clang. However GCC 4.9 may have issues and
  19. // returns 1 for 'defined( __has_include )', while '__has_include' is actually not supported:
  20. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63662
  21. #if defined(__has_include) && (!defined(__GNUC__) || defined(__clang__) || (__GNUC__ + 0) >= 5)
  22. # if __has_include(<cxxabi.h>)
  23. # define BOOST_LEAF_HAS_CXXABI_H
  24. # endif
  25. #elif defined(__GLIBCXX__) || defined(__GLIBCPP__)
  26. # define BOOST_LEAF_HAS_CXXABI_H
  27. #endif
  28. #if defined(BOOST_LEAF_HAS_CXXABI_H)
  29. # include <cxxabi.h>
  30. // For some architectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library
  31. // (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement
  32. // abi::__cxa_demangle(). We detect this implementation by checking the include guard here.
  33. # if defined(__GABIXX_CXXABI_H__)
  34. # undef BOOST_LEAF_HAS_CXXABI_H
  35. # endif
  36. #endif
  37. #endif
  38. namespace boost { namespace leaf {
  39. namespace detail
  40. {
  41. // The functions below are C++11 constexpr, but we use BOOST_LEAF_ALWAYS_INLINE to control object file
  42. // section count / template bleat. Evidently this makes a difference on gcc / windows at least.
  43. template <int S1, int S2, int I, bool = S1 >= S2>
  44. struct cpp11_prefix
  45. {
  46. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&)[S1], char const (&)[S2]) noexcept
  47. {
  48. return false;
  49. }
  50. };
  51. template <int S1, int S2, int I>
  52. struct cpp11_prefix<S1, S2, I, true>
  53. {
  54. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&str)[S1], char const (&prefix)[S2]) noexcept
  55. {
  56. return str[I] == prefix[I] && cpp11_prefix<S1, S2, I - 1>::check(str, prefix);
  57. }
  58. };
  59. template <int S1, int S2>
  60. struct cpp11_prefix<S1, S2, 0, true>
  61. {
  62. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&str)[S1], char const (&prefix)[S2]) noexcept
  63. {
  64. return str[0] == prefix[0];
  65. }
  66. };
  67. template <int S1, int S2>
  68. BOOST_LEAF_ALWAYS_INLINE constexpr int check_prefix(char const (&str)[S1], char const (&prefix)[S2]) noexcept
  69. {
  70. return cpp11_prefix<S1, S2, S2 - 2>::check(str, prefix) ? S2 - 1 : 0;
  71. }
  72. ////////////////////////////////////////
  73. template <int S1, int S2, int I1, int I2, bool = S1 >= S2>
  74. struct cpp11_suffix
  75. {
  76. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&)[S1], char const (&)[S2]) noexcept
  77. {
  78. return false;
  79. }
  80. };
  81. template <int S1, int S2, int I1, int I2>
  82. struct cpp11_suffix<S1, S2, I1, I2, true>
  83. {
  84. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&str)[S1], char const (&suffix)[S2]) noexcept
  85. {
  86. return str[I1] == suffix[I2] && cpp11_suffix<S1, S2, I1 - 1, I2 - 1>::check(str, suffix);
  87. }
  88. };
  89. template <int S1, int S2, int I1>
  90. struct cpp11_suffix<S1, S2, I1, 0, true>
  91. {
  92. BOOST_LEAF_ALWAYS_INLINE constexpr static bool check(char const (&str)[S1], char const (&suffix)[S2]) noexcept
  93. {
  94. return str[I1] == suffix[0];
  95. }
  96. };
  97. template <int S1, int S2>
  98. BOOST_LEAF_ALWAYS_INLINE constexpr int check_suffix(char const (&str)[S1], char const (&suffix)[S2]) noexcept
  99. {
  100. return cpp11_suffix<S1, S2, S1 - 2, S2 - 2>::check(str, suffix) ? S1 - S2 : 0;
  101. }
  102. }
  103. namespace n
  104. {
  105. struct r
  106. {
  107. char const * name;
  108. int len;
  109. r(char const * name, int len) noexcept:
  110. name(name),
  111. len(len)
  112. {
  113. }
  114. template <class CharT, class Traits>
  115. friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, r const & pn)
  116. {
  117. return os.write(pn.name, pn.len);
  118. }
  119. };
  120. template <class T>
  121. BOOST_LEAF_ALWAYS_INLINE r p()
  122. {
  123. // C++11 compile-time parsing of __PRETTY_FUNCTION__/__FUNCSIG__. The sizeof hacks are a
  124. // workaround for older GCC versions, where __PRETTY_FUNCTION__ is not constexpr, which triggers
  125. // compile errors when used in constexpr expressinos, yet evaluating a sizeof exrpession works.
  126. // We don't try to recognize the compiler based on compiler-specific macros. Any compiler/version
  127. // is supported as long as it uses one of the formats we recognize.
  128. // Unrecognized __PRETTY_FUNCTION__/__FUNCSIG__ formats will result in compiler diagnostics.
  129. // In that case, please file an issue on https://github.com/boostorg/leaf.
  130. #define BOOST_LEAF_P(P) (sizeof(char[1 + detail::check_prefix(BOOST_LEAF_PRETTY_FUNCTION, P)]) - 1)
  131. // clang style:
  132. int const p01 = BOOST_LEAF_P("r boost::leaf::n::p() [T = ");
  133. int const p02 = BOOST_LEAF_P("r __cdecl boost::leaf::n::p(void) [T = ");
  134. int const p03 = BOOST_LEAF_P("r __stdcall boost::leaf::n::p(void) [T = ");
  135. int const p04 = BOOST_LEAF_P("r __fastcall boost::leaf::n::p(void) [T = ");
  136. // old clang style:
  137. int const p05 = BOOST_LEAF_P("boost::leaf::n::r boost::leaf::n::p() [T = ");
  138. int const p06 = BOOST_LEAF_P("boost::leaf::n::r __cdecl boost::leaf::n::p(void) [T = ");
  139. int const p07 = BOOST_LEAF_P("boost::leaf::n::r __stdcall boost::leaf::n::p(void) [T = ");
  140. int const p08 = BOOST_LEAF_P("boost::leaf::n::r __fastcall boost::leaf::n::p(void) [T = ");
  141. // gcc style:
  142. int const p09 = BOOST_LEAF_P("boost::leaf::n::r boost::leaf::n::p() [with T = ");
  143. int const p10 = BOOST_LEAF_P("boost::leaf::n::r __cdecl boost::leaf::n::p() [with T = ");
  144. int const p11 = BOOST_LEAF_P("boost::leaf::n::r __stdcall boost::leaf::n::p() [with T = ");
  145. int const p12 = BOOST_LEAF_P("boost::leaf::n::r __fastcall boost::leaf::n::p() [with T = ");
  146. // msvc style, struct:
  147. int const p13 = BOOST_LEAF_P("struct boost::leaf::n::r __cdecl boost::leaf::n::p<struct ");
  148. int const p14 = BOOST_LEAF_P("struct boost::leaf::n::r __stdcall boost::leaf::n::p<struct ");
  149. int const p15 = BOOST_LEAF_P("struct boost::leaf::n::r __fastcall boost::leaf::n::p<struct ");
  150. // msvc style, class:
  151. int const p16 = BOOST_LEAF_P("struct boost::leaf::n::r __cdecl boost::leaf::n::p<class ");
  152. int const p17 = BOOST_LEAF_P("struct boost::leaf::n::r __stdcall boost::leaf::n::p<class ");
  153. int const p18 = BOOST_LEAF_P("struct boost::leaf::n::r __fastcall boost::leaf::n::p<class ");
  154. // msvc style, enum:
  155. int const p19 = BOOST_LEAF_P("struct boost::leaf::n::r __cdecl boost::leaf::n::p<enum ");
  156. int const p20 = BOOST_LEAF_P("struct boost::leaf::n::r __stdcall boost::leaf::n::p<enum ");
  157. int const p21 = BOOST_LEAF_P("struct boost::leaf::n::r __fastcall boost::leaf::n::p<enum ");
  158. // msvc style, built-in type:
  159. int const p22 = BOOST_LEAF_P("struct boost::leaf::n::r __cdecl boost::leaf::n::p<");
  160. int const p23 = BOOST_LEAF_P("struct boost::leaf::n::r __stdcall boost::leaf::n::p<");
  161. int const p24 = BOOST_LEAF_P("struct boost::leaf::n::r __fastcall boost::leaf::n::p<");
  162. #undef BOOST_LEAF_P
  163. #define BOOST_LEAF_S(S) (sizeof(char[1 + detail::check_suffix(BOOST_LEAF_PRETTY_FUNCTION, S)]) - 1)
  164. // clang/gcc style:
  165. int const s01 = BOOST_LEAF_S("]");
  166. // msvc style:
  167. int const s02 = BOOST_LEAF_S(">(void)");
  168. #undef BOOST_LEAF_S
  169. char static_assert_unrecognized_pretty_function_format_please_file_github_issue[sizeof(
  170. char[
  171. (s01 && (1 == (!!p01 + !!p02 + !!p03 + !!p04 + !!p05 + !!p06 + !!p07 + !!p08 + !!p09 + !!p10 + !!p11 + !!p12)))
  172. ||
  173. (s02 && (1 == (!!p13 + !!p14 + !!p15 + !!p16 + !!p17 + !!p18 + !!p19 + !!p20 + !!p21)))
  174. ||
  175. (s02 && (1 == (!!p22 + !!p23 + !!p24)))
  176. ]
  177. ) * 2 - 1];
  178. (void) static_assert_unrecognized_pretty_function_format_please_file_github_issue;
  179. if( int const p = sizeof(char[1 + !!s01 * (p01 + p02 + p03 + p04 + p05 + p06 + p07 + p08 + p09 + p10 + p11 + p12)]) - 1 )
  180. return { BOOST_LEAF_PRETTY_FUNCTION + p, s01 - p };
  181. if( int const p = sizeof(char[1 + !!s02 * (p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20 + p21)]) - 1 )
  182. return { BOOST_LEAF_PRETTY_FUNCTION + p, s02 - p };
  183. int const p = sizeof(char[1 + !!s02 * (p22 + p23 + p24)]) - 1; // p is not zero, we've static asserted the hell out of it
  184. return { BOOST_LEAF_PRETTY_FUNCTION + p, s02 - p };
  185. }
  186. }
  187. using parsed = n::r;
  188. template <class T>
  189. parsed parse()
  190. {
  191. return n::p<T>();
  192. }
  193. } }
  194. ////////////////////////////////////////
  195. namespace boost { namespace leaf {
  196. namespace detail
  197. {
  198. template <class CharT, class Traits>
  199. std::ostream & demangle_and_print(std::basic_ostream<CharT, Traits> & os, char const * mangled_name)
  200. {
  201. BOOST_LEAF_ASSERT(mangled_name);
  202. #if defined(BOOST_LEAF_CFG_DIAGNOSTICS) && defined(BOOST_LEAF_HAS_CXXABI_H)
  203. struct raii
  204. {
  205. char * demangled_name;
  206. raii(char const * mangled_name) noexcept
  207. {
  208. int status = 0;
  209. demangled_name = abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status);
  210. }
  211. ~raii() noexcept
  212. {
  213. std::free(demangled_name);
  214. }
  215. } d(mangled_name);
  216. if( d.demangled_name )
  217. return os << d.demangled_name;
  218. #endif
  219. return os << mangled_name;
  220. }
  221. }
  222. } }
  223. #endif // BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED