diff --git a/include/boost/python/type_id.hpp b/include/boost/python/type_id.hpp index 10b8fba6..d4fb852b 100755 --- a/include/boost/python/type_id.hpp +++ b/include/boost/python/type_id.hpp @@ -35,6 +35,13 @@ namespace boost { namespace python { # define BOOST_PYTHON_TYPE_ID_NAME # endif +#ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE +// Runtime detection of broken cxxabi::__cxa_demangle versions, +// to avoid #ifdef clutter. +bool cxxabi_cxa_demangle_is_broken(); +#define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN +#endif + // type ids which represent the same information as std::type_info // (i.e. the top-level reference and cv-qualifiers are stripped), but // which works across shared libraries. diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index 3fc64a6f..b0afee45 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -18,7 +18,6 @@ # include #endif - # ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE # if defined(__GNUC__) && __GNUC__ >= 3 @@ -78,6 +77,21 @@ namespace }; } +bool cxxabi_cxa_demangle_is_broken() +{ + static bool was_tested = false; + static bool is_broken = false; + if (!was_tested) { + int status; + free_mem keeper(cxxabi::__cxa_demangle("b", 0, 0, &status)); + was_tested = true; + if (status == -2 || strcmp(keeper.p, "bool") != 0) { + is_broken = true; + } + } + return is_broken; +} + namespace detail { BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled) @@ -115,6 +129,44 @@ namespace detail ? mangled : keeper.p; + // Ult Mundane, 2005 Aug 17 + // Contributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + // The __cxa_demangle function is supposed to translate + // builtin types from their one-character mangled names, + // but it doesn't in gcc 3.3.5 and gcc 3.4.x. + if (cxxabi_cxa_demangle_is_broken() + && status == -2 && strlen(mangled) == 1) + { + // list from + // http://www.codesourcery.com/cxx-abi/abi.html + switch (mangled[0]) + { + case 'v': demangled = "void"; break; + case 'w': demangled = "wchar_t"; break; + case 'b': demangled = "bool"; break; + case 'c': demangled = "char"; break; + case 'a': demangled = "signed char"; break; + case 'h': demangled = "unsigned char"; break; + case 's': demangled = "short"; break; + case 't': demangled = "unsigned short"; break; + case 'i': demangled = "int"; break; + case 'j': demangled = "unsigned int"; break; + case 'l': demangled = "long"; break; + case 'm': demangled = "unsigned long"; break; + case 'x': demangled = "long long"; break; + case 'y': demangled = "unsigned long long"; break; + case 'n': demangled = "__int128"; break; + case 'o': demangled = "unsigned __int128"; break; + case 'f': demangled = "float"; break; + case 'd': demangled = "double"; break; + case 'e': demangled = "long double"; break; + case 'g': demangled = "__float128"; break; + case 'z': demangled = "..."; break; + } + } + p = demangler.insert(p, std::make_pair(mangled, demangled)); keeper.p = 0; }