Add boost::throw_exception overload taking a boost::source_location; use it in BOOST_THROW_EXCEPTION

This commit is contained in:
Peter Dimov
2019-11-25 19:17:47 +02:00
parent 43a57d518c
commit dad5cb4ed3
3 changed files with 160 additions and 108 deletions

View File

@ -473,51 +473,6 @@ boost
{ {
return exception_detail::clone_impl<T>(x); return exception_detail::clone_impl<T>(x);
} }
template <class T>
struct
BOOST_SYMBOL_VISIBLE
wrapexcept:
public exception_detail::clone_impl<typename exception_detail::enable_error_info_return_type<T>::type>
{
typedef exception_detail::clone_impl<typename exception_detail::enable_error_info_return_type<T>::type> base_type;
public:
explicit
wrapexcept( typename exception_detail::enable_error_info_return_type<T>::type const & x ):
base_type( x )
{
}
~wrapexcept() BOOST_NOEXCEPT_OR_NOTHROW
{
}
};
namespace
exception_detail
{
template <class T>
struct
remove_error_info_injector
{
typedef T type;
};
template <class T>
struct
remove_error_info_injector< error_info_injector<T> >
{
typedef T type;
};
template <class T>
inline
wrapexcept<typename remove_error_info_injector<T>::type>
enable_both( T const & x )
{
return wrapexcept<typename remove_error_info_injector<T>::type>( enable_error_info( x ) );
}
}
} }
#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)

View File

@ -10,94 +10,159 @@
// //
// boost/throw_exception.hpp // boost/throw_exception.hpp
// //
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002, 2018, 2019 Peter Dimov
// Copyright (c) 2008-2009 Emil Dotchevski and Reverge Studios, Inc. // Copyright (c) 2008-2009 Emil Dotchevski and Reverge Studios, Inc.
// //
// Distributed under the Boost Software License, Version 1.0. (See // Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at // accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
// //
// http://www.boost.org/libs/utility/throw_exception.html // http://www.boost.org/libs/throw_exception
// //
#include <boost/assert/source_location.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/config/workaround.hpp>
#include <exception> #include <exception>
#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x593) ) #if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x593) )
# define BOOST_EXCEPTION_DISABLE # define BOOST_EXCEPTION_DISABLE
#endif #endif
#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1310 ) namespace boost
# define BOOST_EXCEPTION_DISABLE {
#endif
#if !defined( BOOST_EXCEPTION_DISABLE ) // All boost exceptions are required to derive from std::exception,
# include <boost/exception/exception.hpp> // to ensure compatibility with BOOST_NO_EXCEPTIONS.
#if !defined(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION)
# include <boost/current_function.hpp>
# define BOOST_THROW_EXCEPTION_CURRENT_FUNCTION BOOST_CURRENT_FUNCTION
#endif
# define BOOST_THROW_EXCEPTION(x) ::boost::exception_detail::throw_exception_(x,BOOST_THROW_EXCEPTION_CURRENT_FUNCTION,__FILE__,__LINE__)
#else
# define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x)
#endif
#if defined(__GNUC__) && (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) inline void throw_exception_assert_compatibility( std::exception const & ) {}
#pragma GCC system_header
#endif } // namespace boost
#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma warning(push,1) #if defined( BOOST_NO_EXCEPTIONS )
#endif
namespace boost namespace boost
{ {
#ifdef BOOST_NO_EXCEPTIONS
BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
BOOST_NORETURN void throw_exception( std::exception const & e, boost::source_location const & loc ); // user defined
#else } // namespace boost
inline void throw_exception_assert_compatibility( std::exception const & ) { } #elif defined( BOOST_EXCEPTION_DISABLE )
namespace boost
{
template<class E> BOOST_NORETURN inline void throw_exception( E const & e ) template<class E> BOOST_NORETURN inline void throw_exception( E const & e )
{ {
//All boost exceptions are required to derive from std::exception, throw_exception_assert_compatibility( e );
//to ensure compatibility with BOOST_NO_EXCEPTIONS.
throw_exception_assert_compatibility(e);
#ifndef BOOST_EXCEPTION_DISABLE
throw exception_detail::enable_both( e );
#else
throw e; throw e;
#endif
} }
#endif template<class E> BOOST_NORETURN inline void throw_exception( E const & e, boost::source_location const & )
{
throw_exception_assert_compatibility( e );
throw e;
}
} // namespace boost
#else // !defined( BOOST_NO_EXCEPTIONS ) && !defined( BOOST_EXCEPTION_DISABLE )
#include <boost/exception/exception.hpp>
namespace boost
{
// boost::wrapexcept<E>
namespace detail
{
typedef char (&wrapexcept_s1)[ 1 ];
typedef char (&wrapexcept_s2)[ 2 ];
template<class T> wrapexcept_s1 wrapexcept_is_convertible( T* );
template<class T> wrapexcept_s2 wrapexcept_is_convertible( void* );
template<class E, class B, int I = sizeof( wrapexcept_is_convertible<B>( static_cast< E* >( 0 ) ) ) > struct wrapexcept_add_base;
template<class E, class B> struct wrapexcept_add_base<E, B, 1>
{
struct type {};
};
template<class E, class B> struct wrapexcept_add_base<E, B, 2>
{
typedef B type;
};
} // namespace detail
template<class E> struct BOOST_SYMBOL_VISIBLE wrapexcept:
public detail::wrapexcept_add_base<E, boost::exception_detail::clone_base>::type,
public E,
public detail::wrapexcept_add_base<E, boost::exception>::type
{
private:
struct deleter
{
wrapexcept * p_;
~deleter() { delete p_; }
};
public:
explicit wrapexcept( E const & e ): E( e )
{
}
explicit wrapexcept( E const & e, boost::source_location const & loc ): E( e )
{
set_info( *this, throw_file( loc.file_name() ) );
set_info( *this, throw_line( loc.line() ) );
set_info( *this, throw_function( loc.function_name() ) );
}
virtual boost::exception_detail::clone_base const * clone() const
{
wrapexcept * p = new wrapexcept( *this );
deleter del = { p };
boost::exception_detail::copy_boost_exception( p, this );
del.p_ = 0;
return p;
}
virtual void rethrow() const
{
throw *this;
}
};
// boost::throw_exception
template<class E> BOOST_NORETURN inline void throw_exception( E const & e )
{
throw_exception_assert_compatibility( e );
throw wrapexcept<E>( e );
}
template<class E> BOOST_NORETURN inline void throw_exception( E const & e, boost::source_location const & loc )
{
throw_exception_assert_compatibility( e );
throw wrapexcept<E>( e, loc );
}
#if !defined( BOOST_EXCEPTION_DISABLE )
namespace
exception_detail
{
template <class E>
BOOST_NORETURN
void
throw_exception_( E const & x, char const * current_function, char const * file, int line )
{
boost::throw_exception(
set_info(
set_info(
set_info(
enable_error_info(x),
throw_function(current_function)),
throw_file(file)),
throw_line(line)));
}
}
#endif
} // namespace boost } // namespace boost
#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS)
#pragma warning(pop)
#endif
#endif #endif
// BOOST_THROW_EXCEPTION
#define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x, BOOST_CURRENT_LOCATION)
#endif // #ifndef UUID_AA15E74A856F11E08B8D93F24824019B

View File

@ -24,6 +24,14 @@ int main()
BOOST_THROW_EXCEPTION( my_exception() ); BOOST_THROW_EXCEPTION( my_exception() );
} }
catch( boost::exception const & x ) catch( boost::exception const & x )
{
{
char const * const * file = boost::get_error_info<boost::throw_file>( x );
BOOST_TEST( file != 0 );
BOOST_TEST_CSTR_EQ( *file, __FILE__ );
}
{ {
int const * line = boost::get_error_info<boost::throw_line>( x ); int const * line = boost::get_error_info<boost::throw_line>( x );
@ -31,16 +39,40 @@ int main()
BOOST_TEST_EQ( *line, 24 ); BOOST_TEST_EQ( *line, 24 );
} }
{
char const * const * function = boost::get_error_info<boost::throw_function>( x );
BOOST_TEST( function != 0 );
BOOST_TEST_CSTR_EQ( *function, BOOST_CURRENT_FUNCTION );
}
}
try try
{ {
BOOST_THROW_EXCEPTION( my_exception2() ); BOOST_THROW_EXCEPTION( my_exception2() );
} }
catch( boost::exception const & x ) catch( boost::exception const & x )
{
{
char const * const * file = boost::get_error_info<boost::throw_file>( x );
BOOST_TEST( file != 0 );
BOOST_TEST_CSTR_EQ( *file, __FILE__ );
}
{ {
int const * line = boost::get_error_info<boost::throw_line>( x ); int const * line = boost::get_error_info<boost::throw_line>( x );
BOOST_TEST( line != 0 ); BOOST_TEST( line != 0 );
BOOST_TEST_EQ( *line, 36 ); BOOST_TEST_EQ( *line, 52 );
}
{
char const * const * function = boost::get_error_info<boost::throw_function>( x );
BOOST_TEST( function != 0 );
BOOST_TEST_CSTR_EQ( *function, BOOST_CURRENT_FUNCTION );
}
} }
return boost::report_errors(); return boost::report_errors();