diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp index 4c768ee..ca8d833 100644 --- a/include/boost/exception/exception.hpp +++ b/include/boost/exception/exception.hpp @@ -6,6 +6,7 @@ #ifndef BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 #define BOOST_EXCEPTION_274DA366004E11DCB1DDFE2E56D89593 +#include #include #include @@ -107,6 +108,7 @@ boost typedef error_info throw_function; typedef error_info throw_file; typedef error_info throw_line; + typedef error_info throw_column; template <> class @@ -150,6 +152,20 @@ boost } }; + template <> + class + error_info + { + public: + typedef int value_type; + value_type v_; + explicit + error_info( value_type v ): + v_(v) + { + } + }; + class BOOST_SYMBOL_VISIBLE exception; @@ -189,6 +205,9 @@ boost template <> struct get_info; + template <> + struct get_info; + template struct set_info_rv; @@ -201,6 +220,9 @@ boost template <> struct set_info_rv; + template <> + struct set_info_rv; + char const * get_diagnostic_information( exception const &, char const * ); void copy_boost_exception( exception *, exception const * ); @@ -216,6 +238,11 @@ boost template E const & set_info( E const &, throw_line const & ); + + template + E const & set_info( E const &, throw_column const & ); + + boost::source_location get_exception_throw_location( exception const & ); } class @@ -233,7 +260,8 @@ boost exception(): throw_function_(0), throw_file_(0), - throw_line_(-1) + throw_line_(-1), + throw_column_(-1) { } @@ -244,7 +272,8 @@ boost data_(x.data_), throw_function_(x.throw_function_), throw_file_(x.throw_file_), - throw_line_(x.throw_line_) + throw_line_(x.throw_line_), + throw_column_(x.throw_column_) { } #endif @@ -269,27 +298,35 @@ boost template friend E const & exception_detail::set_info( E const &, throw_line const & ); + template + friend E const & exception_detail::set_info( E const &, throw_column const & ); + template friend E const & exception_detail::set_info( E const &, error_info const & ); friend char const * exception_detail::get_diagnostic_information( exception const &, char const * ); + friend boost::source_location exception_detail::get_exception_throw_location( exception const & ); + template friend struct exception_detail::get_info; friend struct exception_detail::get_info; friend struct exception_detail::get_info; friend struct exception_detail::get_info; + friend struct exception_detail::get_info; template friend struct exception_detail::set_info_rv; friend struct exception_detail::set_info_rv; friend struct exception_detail::set_info_rv; friend struct exception_detail::set_info_rv; + friend struct exception_detail::set_info_rv; friend void exception_detail::copy_boost_exception( exception *, exception const * ); #endif mutable exception_detail::refcount_ptr data_; mutable char const * throw_function_; mutable char const * throw_file_; mutable int throw_line_; + mutable int throw_column_; }; inline @@ -324,6 +361,42 @@ boost x.throw_line_=y.v_; return x; } + + template + E const & + set_info( E const & x, throw_column const & y ) + { + x.throw_column_=y.v_; + return x; + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + + template <> + struct + set_info_rv + { + template + static + E const & + set( E const & x, throw_column && y ) + { + x.throw_column_=y.v_; + return x; + } + }; + +#endif + + inline boost::source_location get_exception_throw_location( exception const & x ) + { + return boost::source_location( + x.throw_file_? x.throw_file_: "", + x.throw_line_ >= 0? x.throw_line_: 0, + x.throw_function_? x.throw_function_: "", + x.throw_column_ >= 0? x.throw_column_: 0 + ); + } } //////////////////////////////////////////////////////////////////////// @@ -423,6 +496,7 @@ boost a->throw_file_ = b->throw_file_; a->throw_line_ = b->throw_line_; a->throw_function_ = b->throw_function_; + a->throw_column_ = b->throw_column_; a->data_ = data; } diff --git a/include/boost/throw_exception.hpp b/include/boost/throw_exception.hpp index f832e16..77d806e 100644 --- a/include/boost/throw_exception.hpp +++ b/include/boost/throw_exception.hpp @@ -106,6 +106,7 @@ public: set_info( *this, throw_file( loc.file_name() ) ); set_info( *this, throw_line( loc.line() ) ); set_info( *this, throw_function( loc.function_name() ) ); + set_info( *this, throw_column( loc.column() ) ); } virtual boost::exception_detail::clone_base const * clone() const BOOST_OVERRIDE @@ -256,8 +257,18 @@ template boost::source_location get_throw_location( E const & e ) #else - detail::throw_location const* p = dynamic_cast< detail::throw_location const* >( &e ); - return p? p->location_: boost::source_location(); + if( detail::throw_location const* pl = dynamic_cast< detail::throw_location const* >( &e ) ) + { + return pl->location_; + } + else if( boost::exception const* px = dynamic_cast< boost::exception const* >( &e ) ) + { + return exception_detail::get_exception_throw_location( *px ); + } + else + { + return boost::source_location(); + } #endif } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ca4ef0a..40cfe1d 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -49,6 +49,7 @@ run make_exception_ptr_nx_test2.cpp : : : off ; run throw_with_location_test.cpp ; run throw_with_location_test2.cpp ; run throw_with_location_test3.cpp ; +run throw_with_location_test4.cpp ; run throw_with_location_nx_test.cpp : : : off ; diff --git a/test/throw_with_location_test4.cpp b/test/throw_with_location_test4.cpp new file mode 100644 index 0000000..d2a1f76 --- /dev/null +++ b/test/throw_with_location_test4.cpp @@ -0,0 +1,41 @@ +// Copyright 2022 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +#if defined(_MSC_VER) +# pragma warning(disable: 4702) // unreachable code +#endif + +class my_exception: public std::exception +{ +}; + +int main() +{ + boost::source_location location = BOOST_CURRENT_LOCATION; + + try + { + boost::throw_exception( my_exception(), location ); + + BOOST_ERROR( "boost::throw_exception failed to throw" ); + } + catch( std::exception const & x ) + { + boost::source_location loc = boost::get_throw_location( x ); + + BOOST_TEST_CSTR_EQ( loc.file_name(), location.file_name() ); + BOOST_TEST_CSTR_EQ( loc.function_name(), location.function_name() ); + BOOST_TEST_EQ( loc.line(), location.line() ); + BOOST_TEST_EQ( loc.column(), location.column() ); + } + catch( ... ) + { + BOOST_ERROR( "boost::throw_exception failed to throw std::exception" ); + } + + return boost::report_errors(); +}