forked from boostorg/core
Added low level tools for demangling. Requested by Boost.TypeIndex author.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
[/
|
[/
|
||||||
Copyright 2014 Peter Dimov
|
Copyright 2014 Peter Dimov
|
||||||
|
Copyright 2014 Andrey Semashev
|
||||||
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
Distributed under the Boost Software License, Version 1.0.
|
||||||
|
|
||||||
@@ -18,30 +19,48 @@
|
|||||||
|
|
||||||
[section Header <boost/core/demangle.hpp>]
|
[section Header <boost/core/demangle.hpp>]
|
||||||
|
|
||||||
The header `<boost/core/demangle.hpp>` defines the function
|
The header `<boost/core/demangle.hpp>` defines several tools for undecorating
|
||||||
`boost::core::demangle`. It takes a mangled string such as
|
symbol names.
|
||||||
those returned by `typeid(T).name()` on certain implementations
|
|
||||||
such as `g++`, and returns its demangled, human-readable, form.
|
|
||||||
|
|
||||||
[section Synopsis]
|
[section Synopsis]
|
||||||
|
|
||||||
``
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
std::string demangle( char const * name );
|
std::string demangle( char const * name );
|
||||||
|
|
||||||
|
char const * demangle_alloc( char const * name ) noexcept;
|
||||||
|
void demangle_free( char const * demangled_name ) noexcept;
|
||||||
|
|
||||||
|
class scoped_demangled_name
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit scoped_demangled_name( char const * name ) noexcept;
|
||||||
|
~scoped_demangled_name() noexcept;
|
||||||
|
char const * get() const noexcept;
|
||||||
|
|
||||||
|
scoped_demangled_name( scoped_demangled_name const& ) = delete;
|
||||||
|
scoped_demangled_name& operator= ( scoped_demangled_name const& ) = delete;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
``
|
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
[section Conventional interface]
|
||||||
|
|
||||||
|
The function `boost::core::demangle` is the conventional
|
||||||
|
way to obtain demangled symbol name. It takes a mangled string such as
|
||||||
|
those returned by `typeid(T).name()` on certain implementations
|
||||||
|
such as `g++`, and returns its demangled, human-readable, form. In case if
|
||||||
|
demangling fails (e.g. if `name` cannot be interpreted as a mangled name)
|
||||||
|
the function returns `name`.
|
||||||
|
|
||||||
[section Example]
|
[section Example]
|
||||||
|
|
||||||
``
|
|
||||||
#include <boost/core/demangle.hpp>
|
#include <boost/core/demangle.hpp>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -57,7 +76,50 @@ int main()
|
|||||||
std::cout << name << std::endl; // prints 1XIiE
|
std::cout << name << std::endl; // prints 1XIiE
|
||||||
std::cout << boost::core::demangle( name ) << std::endl; // prints X<int>
|
std::cout << boost::core::demangle( name ) << std::endl; // prints X<int>
|
||||||
}
|
}
|
||||||
``
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
|
[section Low level interface]
|
||||||
|
|
||||||
|
In some cases more low level interface may be desirable. For example:
|
||||||
|
|
||||||
|
* Assuming that symbol demangling may fail, the user wants to be able to handle such errors.
|
||||||
|
* The user needs to post-process the demangled name (e.g. remove common namespaces), and
|
||||||
|
allocating a temporary string with the complete demangled name is significant overhead.
|
||||||
|
|
||||||
|
The function `boost::core::demangle_alloc` performs name demangling and returns a pointer
|
||||||
|
to a string with the demangled name, if succeeded, or `nullptr` otherwise. The returned pointer
|
||||||
|
must be passed to `boost::core::demangle_free` to reclaim resources. Note that on some platforms
|
||||||
|
the pointer returned by `boost::core::demangle_alloc` may refer to the string denoted by `name`,
|
||||||
|
so this string must be kept immutable for the whole life time of the returned pointer.
|
||||||
|
|
||||||
|
The `boost::core::scoped_demangled_name` class is a scope guard that automates the calls to
|
||||||
|
`boost::core::demangle_alloc` (on its construction) and `boost::core::demangle_free` (on destruction).
|
||||||
|
The string with the demangled name can be obtained with its `get` method. Note that this method may
|
||||||
|
return `nullptr` if demangling failed.
|
||||||
|
|
||||||
|
[section Example]
|
||||||
|
|
||||||
|
#include <boost/core/demangle.hpp>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
template<class T> struct X
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char const * name = typeid( X<int> ).name();
|
||||||
|
boost::core::scoped_demangled_name demangled( name );
|
||||||
|
|
||||||
|
std::cout << name << std::endl; // prints 1XIiE
|
||||||
|
std::cout << (demangled.get() ? demangled.get() : "[unknown]") << std::endl; // prints X<int>
|
||||||
|
}
|
||||||
|
|
||||||
|
[endsect]
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
@@ -67,7 +129,7 @@ int main()
|
|||||||
|
|
||||||
The implementation of `core::demangle` was taken from
|
The implementation of `core::demangle` was taken from
|
||||||
`boost/exception/detail/type_info.hpp`, which in turn was adapted
|
`boost/exception/detail/type_info.hpp`, which in turn was adapted
|
||||||
from `boost/units/detail/utility.hpp`.
|
from `boost/units/detail/utility.hpp` and `boost/log/utility/type_info_wrapper.hpp`.
|
||||||
|
|
||||||
[endsect]
|
[endsect]
|
||||||
|
|
||||||
|
@@ -1,15 +1,10 @@
|
|||||||
#ifndef BOOST_CORE_DEMANGLE_HPP_INCLUDED
|
#ifndef BOOST_CORE_DEMANGLE_HPP_INCLUDED
|
||||||
#define BOOST_CORE_DEMANGLE_HPP_INCLUDED
|
#define BOOST_CORE_DEMANGLE_HPP_INCLUDED
|
||||||
|
|
||||||
// MS compatible compilers support #pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
|
||||||
# pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// core::demangle
|
// core::demangle
|
||||||
//
|
//
|
||||||
// Copyright 2014 Peter Dimov
|
// Copyright 2014 Peter Dimov
|
||||||
|
// Copyright 2014 Andrey Semashev
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
// See accompanying file LICENSE_1_0.txt or copy at
|
// See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@@ -18,6 +13,10 @@
|
|||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#if defined(BOOST_HAS_PRAGMA_ONCE)
|
||||||
|
# pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined( __clang__ ) && defined( __has_include )
|
#if defined( __clang__ ) && defined( __has_include )
|
||||||
# if __has_include(<cxxabi.h>)
|
# if __has_include(<cxxabi.h>)
|
||||||
# define BOOST_CORE_HAS_CXXABI_H
|
# define BOOST_CORE_HAS_CXXABI_H
|
||||||
@@ -38,34 +37,56 @@ namespace boost
|
|||||||
namespace core
|
namespace core
|
||||||
{
|
{
|
||||||
|
|
||||||
|
char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT;
|
||||||
|
void demangle_free( char const * name ) BOOST_NOEXCEPT;
|
||||||
|
|
||||||
|
class scoped_demangled_name
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char const * m_p;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit scoped_demangled_name( char const * name ) BOOST_NOEXCEPT :
|
||||||
|
m_p( demangle_alloc( name ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~scoped_demangled_name() BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
demangle_free( m_p );
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * get() const BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
return m_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_DELETED_FUNCTION(scoped_demangled_name( scoped_demangled_name const& ))
|
||||||
|
BOOST_DELETED_FUNCTION(scoped_demangled_name& operator= ( scoped_demangled_name const& ))
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined( BOOST_CORE_HAS_CXXABI_H )
|
#if defined( BOOST_CORE_HAS_CXXABI_H )
|
||||||
|
|
||||||
// lifted from boost/exception/detail/type_info.hpp
|
inline char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
std::size_t size = 0;
|
||||||
|
return abi::__cxa_demangle( name, NULL, &size, &status );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void demangle_free( char const * name ) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
std::free( const_cast< char* >( name ) );
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string demangle( char const * name )
|
inline std::string demangle( char const * name )
|
||||||
{
|
{
|
||||||
struct auto_free
|
scoped_demangled_name demangled_name( name );
|
||||||
|
char const * const p = demangled_name.get();
|
||||||
|
if( p )
|
||||||
{
|
{
|
||||||
explicit auto_free( char * ptr ): p( ptr )
|
return p;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~auto_free()
|
|
||||||
{
|
|
||||||
std::free( p );
|
|
||||||
}
|
|
||||||
|
|
||||||
char * p;
|
|
||||||
};
|
|
||||||
|
|
||||||
int status = 0;
|
|
||||||
std::size_t size = 0;
|
|
||||||
|
|
||||||
auto_free demangled( abi::__cxa_demangle( name, NULL, &size, &status ) );
|
|
||||||
|
|
||||||
if( demangled.p )
|
|
||||||
{
|
|
||||||
return demangled.p;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -75,6 +96,15 @@ inline std::string demangle( char const * name )
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
inline char const * demangle_alloc( char const * name ) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void demangle_free( char const * ) BOOST_NOEXCEPT
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
inline std::string demangle( char const * name )
|
inline std::string demangle( char const * name )
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
// Trivial test for core::demangle
|
// Trivial test for core::demangle
|
||||||
//
|
//
|
||||||
// Copyright (c) 2014 Peter Dimov
|
// Copyright (c) 2014 Peter Dimov
|
||||||
|
// Copyright (c) 2014 Andrey Semashev
|
||||||
//
|
//
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
// See accompanying file LICENSE_1_0.txt or copy at
|
// See accompanying file LICENSE_1_0.txt or copy at
|
||||||
@@ -15,9 +16,46 @@ template<class T1, class T2> struct Y1
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
void test_demangle()
|
||||||
{
|
{
|
||||||
typedef Y1<int, long> T;
|
typedef Y1<int, long> T;
|
||||||
std::cout << boost::core::demangle( typeid( T ).name() );
|
std::cout << boost::core::demangle( typeid( T ).name() ) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_demangle_alloc()
|
||||||
|
{
|
||||||
|
typedef Y1<int, long> T;
|
||||||
|
const char* p = boost::core::demangle_alloc( typeid( T ).name() );
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
std::cout << p << std::endl;
|
||||||
|
boost::core::demangle_free(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "[demangling failed]" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_scoped_demangled_name()
|
||||||
|
{
|
||||||
|
typedef Y1<int, long> T;
|
||||||
|
boost::core::scoped_demangled_name demangled_name( typeid( T ).name() );
|
||||||
|
const char* p = demangled_name.get();
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
std::cout << p << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "[demangling failed]" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_demangle();
|
||||||
|
test_demangle_alloc();
|
||||||
|
test_scoped_demangled_name();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user