From dad5cb4ed377b18e7989079b19823dae1dba137d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 25 Nov 2019 19:17:47 +0200 Subject: [PATCH] Add boost::throw_exception overload taking a boost::source_location; use it in BOOST_THROW_EXCEPTION --- include/boost/exception/exception.hpp | 45 ------- include/boost/throw_exception.hpp | 179 ++++++++++++++++++-------- test/throw_exception_test4.cpp | 44 ++++++- 3 files changed, 160 insertions(+), 108 deletions(-) diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp index 5fe3009..07e1245 100644 --- a/include/boost/exception/exception.hpp +++ b/include/boost/exception/exception.hpp @@ -473,51 +473,6 @@ boost { return exception_detail::clone_impl(x); } - - template - struct - BOOST_SYMBOL_VISIBLE - wrapexcept: - public exception_detail::clone_impl::type> - { - typedef exception_detail::clone_impl::type> base_type; - public: - explicit - wrapexcept( typename exception_detail::enable_error_info_return_type::type const & x ): - base_type( x ) - { - } - - ~wrapexcept() BOOST_NOEXCEPT_OR_NOTHROW - { - } - }; - - namespace - exception_detail - { - template - struct - remove_error_info_injector - { - typedef T type; - }; - - template - struct - remove_error_info_injector< error_info_injector > - { - typedef T type; - }; - - template - inline - wrapexcept::type> - enable_both( T const & x ) - { - return wrapexcept::type>( enable_error_info( x ) ); - } - } } #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) diff --git a/include/boost/throw_exception.hpp b/include/boost/throw_exception.hpp index cd77ead..5a0e50c 100644 --- a/include/boost/throw_exception.hpp +++ b/include/boost/throw_exception.hpp @@ -10,94 +10,159 @@ // // 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. // // Distributed 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) // -// http://www.boost.org/libs/utility/throw_exception.html +// http://www.boost.org/libs/throw_exception // +#include #include -#include +#include #include #if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x593) ) # define BOOST_EXCEPTION_DISABLE #endif -#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1310 ) -# define BOOST_EXCEPTION_DISABLE -#endif +namespace boost +{ -#if !defined( BOOST_EXCEPTION_DISABLE ) -# include -#if !defined(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION) -# include -# 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 +// All boost exceptions are required to derive from std::exception, +// to ensure compatibility with BOOST_NO_EXCEPTIONS. -#if defined(__GNUC__) && (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) -#pragma GCC system_header -#endif -#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) -#pragma warning(push,1) -#endif +inline void throw_exception_assert_compatibility( std::exception const & ) {} + +} // namespace boost + +#if defined( BOOST_NO_EXCEPTIONS ) 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, 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 BOOST_NORETURN inline void throw_exception( E const & e ) { - //All boost exceptions are required to derive from std::exception, - //to ensure compatibility with BOOST_NO_EXCEPTIONS. - throw_exception_assert_compatibility(e); - -#ifndef BOOST_EXCEPTION_DISABLE - throw exception_detail::enable_both( e ); -#else + throw_exception_assert_compatibility( e ); throw e; -#endif } -#endif +template 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 + +namespace boost +{ + +// boost::wrapexcept + +namespace detail +{ + +typedef char (&wrapexcept_s1)[ 1 ]; +typedef char (&wrapexcept_s2)[ 2 ]; + +template wrapexcept_s1 wrapexcept_is_convertible( T* ); +template wrapexcept_s2 wrapexcept_is_convertible( void* ); + +template( static_cast< E* >( 0 ) ) ) > struct wrapexcept_add_base; + +template struct wrapexcept_add_base +{ + struct type {}; +}; + +template struct wrapexcept_add_base +{ + typedef B type; +}; + +} // namespace detail + +template struct BOOST_SYMBOL_VISIBLE wrapexcept: + public detail::wrapexcept_add_base::type, + public E, + public detail::wrapexcept_add_base::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 BOOST_NORETURN inline void throw_exception( E const & e ) +{ + throw_exception_assert_compatibility( e ); + throw wrapexcept( e ); +} + +template BOOST_NORETURN inline void throw_exception( E const & e, boost::source_location const & loc ) +{ + throw_exception_assert_compatibility( e ); + throw wrapexcept( e, loc ); +} -#if !defined( BOOST_EXCEPTION_DISABLE ) - namespace - exception_detail - { - template - 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 -#if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) -#pragma warning(pop) -#endif #endif + +// BOOST_THROW_EXCEPTION + +#define BOOST_THROW_EXCEPTION(x) ::boost::throw_exception(x, BOOST_CURRENT_LOCATION) + +#endif // #ifndef UUID_AA15E74A856F11E08B8D93F24824019B diff --git a/test/throw_exception_test4.cpp b/test/throw_exception_test4.cpp index 5b8e303..07cd4ae 100644 --- a/test/throw_exception_test4.cpp +++ b/test/throw_exception_test4.cpp @@ -25,10 +25,26 @@ int main() } catch( boost::exception const & x ) { - int const * line = boost::get_error_info( x ); + { + char const * const * file = boost::get_error_info( x ); - BOOST_TEST( line != 0 ); - BOOST_TEST_EQ( *line, 24 ); + BOOST_TEST( file != 0 ); + BOOST_TEST_CSTR_EQ( *file, __FILE__ ); + } + + { + int const * line = boost::get_error_info( x ); + + BOOST_TEST( line != 0 ); + BOOST_TEST_EQ( *line, 24 ); + } + + { + char const * const * function = boost::get_error_info( x ); + + BOOST_TEST( function != 0 ); + BOOST_TEST_CSTR_EQ( *function, BOOST_CURRENT_FUNCTION ); + } } try @@ -37,10 +53,26 @@ int main() } catch( boost::exception const & x ) { - int const * line = boost::get_error_info( x ); + { + char const * const * file = boost::get_error_info( x ); - BOOST_TEST( line != 0 ); - BOOST_TEST_EQ( *line, 36 ); + BOOST_TEST( file != 0 ); + BOOST_TEST_CSTR_EQ( *file, __FILE__ ); + } + + { + int const * line = boost::get_error_info( x ); + + BOOST_TEST( line != 0 ); + BOOST_TEST_EQ( *line, 52 ); + } + + { + char const * const * function = boost::get_error_info( x ); + + BOOST_TEST( function != 0 ); + BOOST_TEST_CSTR_EQ( *function, BOOST_CURRENT_FUNCTION ); + } } return boost::report_errors();