demangle.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #ifndef BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
  2. #define BOOST_LEAF_DETAIL_DEMANGLE_HPP_INCLUDED
  3. // Copyright 2018-2023 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 <cstring>
  16. namespace boost { namespace leaf {
  17. namespace leaf_detail
  18. {
  19. template <int N>
  20. BOOST_LEAF_CONSTEXPR inline char const * check_prefix( char const * t, char const (&prefix)[N] )
  21. {
  22. return std::strncmp(t,prefix,sizeof(prefix)-1)==0 ? t+sizeof(prefix)-1 : t;
  23. }
  24. }
  25. template <class Name>
  26. inline char const * type()
  27. {
  28. using leaf_detail::check_prefix;
  29. char const * t =
  30. #ifdef __FUNCSIG__
  31. __FUNCSIG__;
  32. #else
  33. __PRETTY_FUNCTION__;
  34. #endif
  35. #if defined(__clang__)
  36. BOOST_LEAF_ASSERT(check_prefix(t,"const char *boost::leaf::type() ")==t+32);
  37. return t+32;
  38. #elif defined(__GNUC__)
  39. BOOST_LEAF_ASSERT(check_prefix(t,"const char* boost::leaf::type() ")==t+32);
  40. return t+32;
  41. #else
  42. char const * clang_style = check_prefix(t,"const char *boost::leaf::type() ");
  43. if( clang_style!=t )
  44. return clang_style;
  45. char const * gcc_style = check_prefix(t,"const char* boost::leaf::type() ");
  46. if( gcc_style!=t )
  47. return gcc_style;
  48. #endif
  49. return t;
  50. }
  51. } }
  52. ////////////////////////////////////////
  53. // __has_include is currently supported by GCC and Clang. However GCC 4.9 may have issues and
  54. // returns 1 for 'defined( __has_include )', while '__has_include' is actually not supported:
  55. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63662
  56. #if defined(__has_include) && (!defined(__GNUC__) || defined(__clang__) || (__GNUC__ + 0) >= 5)
  57. # if __has_include(<cxxabi.h>)
  58. # define BOOST_LEAF_HAS_CXXABI_H
  59. # endif
  60. #elif defined( __GLIBCXX__ ) || defined( __GLIBCPP__ )
  61. # define BOOST_LEAF_HAS_CXXABI_H
  62. #endif
  63. #if defined( BOOST_LEAF_HAS_CXXABI_H )
  64. # include <cxxabi.h>
  65. // For some archtectures (mips, mips64, x86, x86_64) cxxabi.h in Android NDK is implemented by gabi++ library
  66. // (https://android.googlesource.com/platform/ndk/+/master/sources/cxx-stl/gabi++/), which does not implement
  67. // abi::__cxa_demangle(). We detect this implementation by checking the include guard here.
  68. # if defined( __GABIXX_CXXABI_H__ )
  69. # undef BOOST_LEAF_HAS_CXXABI_H
  70. # else
  71. # include <cstdlib>
  72. # include <cstddef>
  73. # endif
  74. #endif
  75. #if BOOST_LEAF_CFG_STD_STRING
  76. #include <string>
  77. namespace boost { namespace leaf {
  78. namespace leaf_detail
  79. {
  80. inline char const * demangle_alloc( char const * name ) noexcept;
  81. inline void demangle_free( char const * name ) noexcept;
  82. class scoped_demangled_name
  83. {
  84. private:
  85. char const * m_p;
  86. public:
  87. explicit scoped_demangled_name( char const * name ) noexcept :
  88. m_p( demangle_alloc( name ) )
  89. {
  90. }
  91. ~scoped_demangled_name() noexcept
  92. {
  93. demangle_free( m_p );
  94. }
  95. char const * get() const noexcept
  96. {
  97. return m_p;
  98. }
  99. scoped_demangled_name( scoped_demangled_name const& ) = delete;
  100. scoped_demangled_name& operator= ( scoped_demangled_name const& ) = delete;
  101. };
  102. #ifdef BOOST_LEAF_HAS_CXXABI_H
  103. inline char const * demangle_alloc( char const * name ) noexcept
  104. {
  105. int status = 0;
  106. std::size_t size = 0;
  107. return abi::__cxa_demangle( name, NULL, &size, &status );
  108. }
  109. inline void demangle_free( char const * name ) noexcept
  110. {
  111. std::free( const_cast< char* >( name ) );
  112. }
  113. inline std::string demangle( char const * name )
  114. {
  115. scoped_demangled_name demangled_name( name );
  116. char const * p = demangled_name.get();
  117. if( !p )
  118. p = name;
  119. return p;
  120. }
  121. #else
  122. inline char const * demangle_alloc( char const * name ) noexcept
  123. {
  124. return name;
  125. }
  126. inline void demangle_free( char const * ) noexcept
  127. {
  128. }
  129. inline char const * demangle( char const * name )
  130. {
  131. return name;
  132. }
  133. #endif
  134. }
  135. } }
  136. #else
  137. namespace boost { namespace leaf {
  138. namespace leaf_detail
  139. {
  140. inline char const * demangle( char const * name )
  141. {
  142. return name;
  143. }
  144. }
  145. } }
  146. #endif
  147. #ifdef BOOST_LEAF_HAS_CXXABI_H
  148. # undef BOOST_LEAF_HAS_CXXABI_H
  149. #endif
  150. #endif