diff --git a/include/boost/exception/detail/error_info_base.hpp b/include/boost/exception/detail/error_info_base.hpp new file mode 100644 index 0000000..7953d13 --- /dev/null +++ b/include/boost/exception/detail/error_info_base.hpp @@ -0,0 +1,38 @@ +//Copyright (c) 2006-2008 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) + +#ifndef UUID_CE6983AC753411DDA764247956D89593 +#define UUID_CE6983AC753411DDA764247956D89593 + +#include +#include + +namespace +boost + { + namespace + exception_detail + { + class + error_info_base + { + public: + + virtual char const * tag_typeid_name() const = 0; + virtual std::string value_as_string() const = 0; + + protected: + +#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) +virtual //Disable bogus GCC warning. +#endif + ~error_info_base() + { + } + }; + } + } + +#endif diff --git a/include/boost/exception/detail/get_boost_exception.hpp b/include/boost/exception/detail/get_boost_exception.hpp new file mode 100644 index 0000000..d7bf6a0 --- /dev/null +++ b/include/boost/exception/detail/get_boost_exception.hpp @@ -0,0 +1,47 @@ +//Copyright (c) 2006-2008 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) + +#ifndef UUID_B9A8291074CA11DD94BFC77156D89593 +#define UUID_B9A8291074CA11DD94BFC77156D89593 + +#include + +namespace +boost + { + namespace + exception_detail + { +#ifdef BOOST_NO_RTTI + template + exception const * + get_boost_exception( T const * ) + { + try + { + throw; + } + catch( + exception & x ) + { + return &x; + } + catch(...) + { + return 0; + } + } +#else + template + exception const * + get_boost_exception( T const * x ) + { + return dynamic_cast(x); + } +#endif + } + } + +#endif diff --git a/include/boost/exception/detail/object_hex_dump.hpp b/include/boost/exception/detail/object_hex_dump.hpp index be728d2..5b15637 100644 --- a/include/boost/exception/detail/object_hex_dump.hpp +++ b/include/boost/exception/detail/object_hex_dump.hpp @@ -6,6 +6,7 @@ #ifndef UUID_6F463AC838DF11DDA3E6909F56D89593 #define UUID_6F463AC838DF11DDA3E6909F56D89593 +#include #include #include #include @@ -24,7 +25,7 @@ boost object_hex_dump( T const & x, size_t max_size=16 ) { std::ostringstream s; - s << "type: " << typeid(x).name() << ", size: " << sizeof(T) << ", dump: "; + s << "type: " << type_name() << ", size: " << sizeof(T) << ", dump: "; size_t n=sizeof(T)>max_size?max_size:sizeof(T); s.fill('0'); s.width(2); diff --git a/include/boost/exception/detail/type_info.hpp b/include/boost/exception/detail/type_info.hpp new file mode 100644 index 0000000..f6a1c93 --- /dev/null +++ b/include/boost/exception/detail/type_info.hpp @@ -0,0 +1,62 @@ +//Copyright (c) 2006-2008 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) + +#ifndef UUID_C3E1741C754311DDB2834CCA55D89593 +#define UUID_C3E1741C754311DDB2834CCA55D89593 + +#include +#include + +namespace +boost + { + template + inline + char const * + error_info_value() + { + return BOOST_CURRENT_FUNCTION; + } + + namespace + exception_detail + { + typedef detail::sp_typeinfo type_info_; + +#ifdef BOOST_NO_TYPEID + typedef type_info_ type_info_wrapper; +#else + struct + type_info_wrapper + { + type_info_ const * type; + + explicit + type_info_wrapper( type_info_ const & t ): + type(&t) + { + } + + bool + operator<( type_info_wrapper const & b ) const + { + return 0!=(type->before(*b.type)); + } + }; +#endif + + template + inline + char const * + type_name() + { + return error_info_value(); + } + } + } + +#define BOOST_EXCEPTION_STATIC_TYPEID(T) BOOST_SP_TYPEID(T) + +#endif diff --git a/include/boost/exception/diagnostic_information.hpp b/include/boost/exception/diagnostic_information.hpp index a456577..3a22a8f 100644 --- a/include/boost/exception/diagnostic_information.hpp +++ b/include/boost/exception/diagnostic_information.hpp @@ -6,7 +6,7 @@ #ifndef UUID_0552D49838DD11DD90146B8956D89593 #define UUID_0552D49838DD11DD90146B8956D89593 -#include +#include #include #include @@ -17,10 +17,16 @@ boost std::string diagnostic_information( std::exception const & x ) { - if( exception const * be = dynamic_cast(&x) ) + if( exception const * be = exception_detail::get_boost_exception(&x) ) return be->diagnostic_information(); else - return std::string("[ what: ") + x.what() + ", type: " + typeid(x).name() + " ]"; + return std::string("[ what: ") + x.what() + ", type: " +#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID) + "Unknown type deriving from std::exception" +#else + + typeid(x).name() + +#endif + " ]"; } } diff --git a/include/boost/exception/enable_current_exception.hpp b/include/boost/exception/enable_current_exception.hpp index 4c17fb0..d350b4d 100644 --- a/include/boost/exception/enable_current_exception.hpp +++ b/include/boost/exception/enable_current_exception.hpp @@ -18,6 +18,19 @@ boost namespace exception_detail { + inline + void + copy_boost_exception( exception * a, exception const * b ) + { + *a = *b; + } + + inline + void + copy_boost_exception( void *, void const * ) + { + } + class clone_base: public counted_base @@ -64,9 +77,7 @@ boost clone_impl( T const & x ): T(x) { - if( boost::exception * be1=dynamic_cast(this) ) - if( boost::exception const * be2=dynamic_cast(&x) ) - *be1 = *be2; + copy_boost_exception(this,&x); } private: @@ -91,9 +102,7 @@ boost T(x), count_(0) { - if( boost::exception * be1=dynamic_cast(this) ) - if( boost::exception const * be2=dynamic_cast(&x) ) - *be1 = *be2; + copy_boost_exception(this,&x); } private: diff --git a/include/boost/exception/exception.hpp b/include/boost/exception/exception.hpp index 4670481..8ea1d7e 100644 --- a/include/boost/exception/exception.hpp +++ b/include/boost/exception/exception.hpp @@ -6,7 +6,7 @@ #ifndef UUID_274DA366004E11DCB1DDFE2E56D89593 #define UUID_274DA366004E11DCB1DDFE2E56D89593 -#include +#include #include #include #include @@ -15,6 +15,8 @@ namespace boost { + class exception; + template class shared_ptr; @@ -27,21 +29,17 @@ boost error_info_container: public exception_detail::counted_base { - virtual char const * diagnostic_information( char const *, std::type_info const & ) const = 0; - virtual shared_ptr get( std::type_info const & ) const = 0; - virtual void set( shared_ptr const & ) = 0; + virtual char const * diagnostic_information( char const *, char const * ) const = 0; + virtual shared_ptr get( type_info_ const & ) const = 0; + virtual void set( shared_ptr const &, type_info_ const & ) = 0; }; + + template + shared_ptr get_data( exception const & ); + + void set_data( exception const *, shared_ptr const &, exception_detail::type_info_ const & ); } - template - class error_info; - - template - E const & operator<<( E const &, error_info const & ); - - template - shared_ptr get_error_info( E const & ); - class exception { @@ -71,14 +69,14 @@ boost if( data_ ) try { - char const * w = data_->diagnostic_information(std_what,typeid(*this)); - BOOST_ASSERT(0!=w); + char const * w = data_->diagnostic_information(std_what,dynamic_type_name()); + BOOST_ASSERT(w!=0); return w; } catch(...) { } - return std_what ? std_what : typeid(*this).name(); + return std_what ? std_what : dynamic_type_name(); } #if BOOST_WORKAROUND( BOOST_MSVC, BOOST_TESTED_AT(1500) ) @@ -96,14 +94,22 @@ boost private: - shared_ptr get( std::type_info const & ) const; - void set( shared_ptr const & ) const; + friend void exception_detail::set_data( exception const *, shared_ptr const &, exception_detail::type_info_ const & ); - template - friend E const & operator<<( E const &, error_info const & ); + template + friend shared_ptr exception_detail::get_data( exception const & ); - template - friend shared_ptr get_error_info( E const & ); + char const * + dynamic_type_name() const + { + return +#if defined(BOOST_NO_RTTI) || defined(BOOST_NO_TYPEID) + "Unknown type deriving from boost::exception" +#else + typeid(*this).name() +#endif + ; + } mutable intrusive_ptr data_; }; diff --git a/include/boost/exception/get_error_info.hpp b/include/boost/exception/get_error_info.hpp new file mode 100644 index 0000000..78d8eb4 --- /dev/null +++ b/include/boost/exception/get_error_info.hpp @@ -0,0 +1,49 @@ +//Copyright (c) 2006-2008 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) + +#ifndef UUID_1A590226753311DD9E4CCF6156D89593 +#define UUID_1A590226753311DD9E4CCF6156D89593 + +#include +#include +#include + +namespace +boost + { + namespace + exception_detail + { + template + inline + shared_ptr + get_data( exception const & x ) + { + if( x.data_ ) + if( shared_ptr eib = x.data_->get(BOOST_EXCEPTION_STATIC_TYPEID(ErrorInfo)) ) + { +#ifndef BOOST_NO_RTTI + BOOST_ASSERT( 0!=dynamic_cast(eib.get()) ); +#endif + ErrorInfo const * w = static_cast(eib.get()); + return shared_ptr(eib,&w->value()); + } + return shared_ptr(); + } + } + + template + inline + shared_ptr + get_error_info( E const & some_exception ) + { + if( exception const * x = exception_detail::get_boost_exception(&some_exception) ) + return exception_detail::get_data(*x); + else + return shared_ptr(); + } + } + +#endif diff --git a/include/boost/exception/info.hpp b/include/boost/exception/info.hpp index 4f8f69d..140827e 100644 --- a/include/boost/exception/info.hpp +++ b/include/boost/exception/info.hpp @@ -6,11 +6,10 @@ #ifndef UUID_8D22C4CA9CC811DCAA9133D256D89593 #define UUID_8D22C4CA9CC811DCAA9133D256D89593 -#include #include +#include #include #include -#include #include #include @@ -26,28 +25,6 @@ boost typedef error_info throw_file; typedef error_info throw_line; - namespace - exception_detail - { - class - error_info_base - { - public: - - virtual std::type_info const & tag_typeid() const = 0; - virtual std::string value_as_string() const = 0; - - protected: - -#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT(4) ) -virtual //Disable bogus GCC warning. -#endif - ~error_info_base() - { - } - }; - } - template class error_info: @@ -70,10 +47,10 @@ virtual //Disable bogus GCC warning. private: - std::type_info const & - tag_typeid() const + char const * + tag_typeid_name() const { - return typeid(type); + return exception_detail::type_name(); } std::string @@ -85,31 +62,6 @@ virtual //Disable bogus GCC warning. value_type const value_; }; - template - inline - E const & - operator<<( E const & x, error_info const & v ) - { - shared_ptr< error_info > p( new error_info(v) ); - x.set(p); - return x; - } - - template - inline - shared_ptr - get_error_info( E const & some_exception ) - { - if( exception const * x = dynamic_cast(&some_exception) ) - if( shared_ptr eib = x->get(typeid(ErrorInfo)) ) - { - BOOST_ASSERT( 0!=dynamic_cast(eib.get()) ); - ErrorInfo const * w = static_cast(eib.get()); - return shared_ptr(eib,&w->value()); - } - return shared_ptr(); - } - namespace exception_detail { @@ -128,30 +80,33 @@ virtual //Disable bogus GCC warning. { } - shared_ptr - get( std::type_info const & ti ) const + void + set( shared_ptr const & x, type_info_ const & typeid_ ) { - error_info_map::const_iterator i=info_.find(typeinfo(ti)); + BOOST_ASSERT(x); + info_[type_info_wrapper(typeid_)] = x; + what_.clear(); + } + + shared_ptr + get( type_info_ const & ti ) const + { + error_info_map::const_iterator i=info_.find(type_info_wrapper(ti)); if( info_.end()!=i ) { shared_ptr const & p = i->second; + #ifndef BOOST_NO_RTTI BOOST_ASSERT( typeid(*p)==ti ); + #endif return p; } return shared_ptr(); } - void - set( shared_ptr const & x ) - { - BOOST_ASSERT(x); - info_[typeinfo(typeid(*x))] = x; - what_.clear(); - } - char const * - diagnostic_information( char const * std_what, std::type_info const & exception_type ) const + diagnostic_information( char const * std_what, char const * exception_type_name ) const { + BOOST_ASSERT(exception_type_name!=0 && *exception_type_name ); if( what_.empty() ) { std::string tmp; @@ -161,13 +116,13 @@ virtual //Disable bogus GCC warning. tmp += '\n'; } tmp += "Dynamic exception type: "; - tmp += exception_type.name(); + tmp += exception_type_name; tmp += '\n'; for( error_info_map::const_iterator i=info_.begin(),end=info_.end(); i!=end; ++i ) { shared_ptr const & x = i->second; tmp += '['; - tmp += x->tag_typeid().name(); + tmp += x->tag_typeid_name(); tmp += "] = "; tmp += x->value_as_string(); tmp += '\n'; @@ -181,25 +136,7 @@ virtual //Disable bogus GCC warning. friend class exception; - struct - typeinfo - { - std::type_info const * type; - - explicit - typeinfo( std::type_info const & t ): - type(&t) - { - } - - bool - operator<( typeinfo const & b ) const - { - return 0!=(type->before(*b.type)); - } - }; - - typedef std::map< typeinfo, shared_ptr > error_info_map; + typedef std::map< type_info_wrapper, shared_ptr > error_info_map; error_info_map info_; mutable std::string what_; mutable int count_; @@ -217,27 +154,32 @@ virtual //Disable bogus GCC warning. delete this; } }; + + inline + void + set_data( exception const * e, shared_ptr const & x, exception_detail::type_info_ const & typeid_ ) + { + if( !e->data_ ) + e->data_ = intrusive_ptr(new exception_detail::error_info_container_impl); + e->data_->set(x,typeid_); + } + + inline + void + set_data( void const *, shared_ptr const &, exception_detail::type_info_ const & ) + { + } } + template inline - void - exception:: - set( shared_ptr const & x ) const + E const & + operator<<( E const & x, error_info const & v ) { - if( !data_ ) - data_ = intrusive_ptr(new exception_detail::error_info_container_impl); - data_->set(x); - } - - inline - shared_ptr - exception:: - get( std::type_info const & ti ) const - { - if( data_ ) - return data_->get(ti); - else - return shared_ptr(); + typedef error_info error_info_tag_t; + shared_ptr p( new error_info_tag_t(v) ); + exception_detail::set_data(&x,p,BOOST_EXCEPTION_STATIC_TYPEID(error_info_tag_t)); + return x; } } diff --git a/include/boost/exception_ptr.hpp b/include/boost/exception_ptr.hpp index f7f73bd..cb1d73e 100644 --- a/include/boost/exception_ptr.hpp +++ b/include/boost/exception_ptr.hpp @@ -7,7 +7,7 @@ #define UUID_FA5836A2CADA11DC8CD47C8555D89593 #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ boost exception_ptr current_exception_std_exception( T const & e1 ) { - if( boost::exception const * e2 = dynamic_cast(&e1) ) + if( boost::exception const * e2 = get_boost_exception(&e1) ) return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1,*e2))); else return exception_ptr(exception_detail::make_clone(current_exception_std_exception_wrapper(e1))); @@ -89,7 +89,7 @@ boost exception_ptr current_exception_unknown_std_exception( std::exception const & e ) { - if( boost::exception const * be = dynamic_cast(&e) ) + if( boost::exception const * be = get_boost_exception(&e) ) return exception_ptr(exception_detail::make_clone(unknown_exception(*be))); else return current_exception_unknown_exception(); diff --git a/include/boost/throw_exception.hpp b/include/boost/throw_exception.hpp index dc468f2..ae5ea5a 100644 --- a/include/boost/throw_exception.hpp +++ b/include/boost/throw_exception.hpp @@ -24,8 +24,8 @@ #include #include -#if !defined( BOOST_EXCEPTION_DISABLE ) && defined( BOOST_NO_TYPEID ) -# define BOOST_EXCEPTION_DISABLE +#if !defined( BOOST_EXCEPTION_DISABLE ) +#define BOOST_EXCEPTION_DISABLE #endif #if !defined( BOOST_EXCEPTION_DISABLE ) && defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, < 0x590 ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index ab465fe..d3463a6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -40,6 +40,7 @@ compile enable_current_exception_hpp_test.cpp ; compile enable_error_info_hpp_test.cpp ; compile error_info_hpp_test.cpp ; compile exception_hpp_test.cpp ; +compile get_error_info_hpp_test.cpp ; compile info_hpp_test.cpp ; compile info_tuple_hpp_test.cpp ; compile to_string_hpp_test.cpp ; diff --git a/test/boost_error_info_test.cpp b/test/boost_error_info_test.cpp index d919eb7..3b1b4ac 100644 --- a/test/boost_error_info_test.cpp +++ b/test/boost_error_info_test.cpp @@ -3,6 +3,7 @@ //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) +#include #include #include #include diff --git a/test/diagnostic_information_test.cpp b/test/diagnostic_information_test.cpp index 3dc1279..fe79ab6 100644 --- a/test/diagnostic_information_test.cpp +++ b/test/diagnostic_information_test.cpp @@ -7,7 +7,7 @@ #include #include -typedef boost::error_info tag_int; +typedef boost::error_info tag_int; struct error1: @@ -48,27 +48,65 @@ int main() { using namespace boost; + try { error1 x; BOOST_TEST(x.what()==std::string("error1")); + throw x; + } + catch( + std::exception & x ) + { std::string di=get_diagnostic_information(x); BOOST_TEST(di.find("type:")!=std::string::npos); BOOST_TEST(di.find("error1")!=std::string::npos); } + catch( + ... ) + { + BOOST_TEST(false); + } + try { error2 x; x << tag_int(42); BOOST_TEST(x.what()==std::string("error2")); + throw x; + } + catch( + std::exception & x ) + { std::string di=get_diagnostic_information(x); BOOST_TEST(di.find("type:")!=std::string::npos); +#ifndef BOOST_NO_RTTI BOOST_TEST(di.find("error2")!=std::string::npos); +#endif + BOOST_TEST(di.find("test_tag")!=std::string::npos); } + catch( + ... ) + { + BOOST_TEST(false); + } + try { error3 x; x << tag_int(1); + throw x; + } + catch( + boost::exception & x ) + { std::string w1 = x.diagnostic_information(); x << tag_int(2); std::string w2 = x.diagnostic_information(); BOOST_TEST( w1!=w2 ); + BOOST_TEST(w1.find("test_tag")!=std::string::npos); + BOOST_TEST(w2.find("test_tag")!=std::string::npos); + } + catch( + ... ) + { + BOOST_TEST(false); } return boost::report_errors(); } diff --git a/test/enable_error_info_test.cpp b/test/enable_error_info_test.cpp index 0d7c150..d7a94ac 100644 --- a/test/enable_error_info_test.cpp +++ b/test/enable_error_info_test.cpp @@ -4,6 +4,7 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "helper1.hpp" +#include #include #include #include diff --git a/test/errno_test.cpp b/test/errno_test.cpp index 7280068..1d060a8 100644 --- a/test/errno_test.cpp +++ b/test/errno_test.cpp @@ -3,6 +3,7 @@ //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) +#include #include #include #include diff --git a/test/error_info_test.cpp b/test/error_info_test.cpp index c61609a..51715c8 100644 --- a/test/error_info_test.cpp +++ b/test/error_info_test.cpp @@ -3,6 +3,7 @@ //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) +#include #include #include @@ -38,12 +39,20 @@ throws_on_copy void basic_test() { - test_exception x; - x << test_1(1) << test_2(2u) << test_3(3.14159f); - BOOST_TEST(*boost::get_error_info(x)==1); - BOOST_TEST(*boost::get_error_info(x)==2u); - BOOST_TEST(*boost::get_error_info(x)==3.14159f); - BOOST_TEST(!boost::get_error_info(x)); + try + { + test_exception x; + x << test_1(1) << test_2(2u) << test_3(3.14159f); + throw x; + } + catch( + test_exception & x ) + { + BOOST_TEST(*boost::get_error_info(x)==1); + BOOST_TEST(*boost::get_error_info(x)==2u); + BOOST_TEST(*boost::get_error_info(x)==3.14159f); + BOOST_TEST(!boost::get_error_info(x)); + } } void @@ -58,8 +67,8 @@ exception_safety_test() catch( test_exception & ) { + BOOST_TEST(!boost::get_error_info(x)); } - BOOST_TEST(!boost::get_error_info(x)); } void @@ -107,7 +116,9 @@ test_empty() catch( boost::exception & x ) { +#ifndef BOOST_NO_RTTI BOOST_TEST( dynamic_cast(&x) ); +#endif BOOST_TEST( !boost::get_error_info(x) ); } catch( @@ -124,7 +135,7 @@ test_empty() catch( test_exception & x ) { - BOOST_TEST( dynamic_cast(&x) ); + BOOST_TEST( boost::exception_detail::get_boost_exception(&x) ); } catch( ... ) diff --git a/test/get_error_info_hpp_test.cpp b/test/get_error_info_hpp_test.cpp new file mode 100644 index 0000000..a7ea56b --- /dev/null +++ b/test/get_error_info_hpp_test.cpp @@ -0,0 +1,6 @@ +//Copyright (c) 2006-2008 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) + +#include diff --git a/test/throw_exception_test.cpp b/test/throw_exception_test.cpp index 247575d..113f40a 100644 --- a/test/throw_exception_test.cpp +++ b/test/throw_exception_test.cpp @@ -4,6 +4,7 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "helper2.hpp" +#include #include #include #include diff --git a/test/unknown_exception_test.cpp b/test/unknown_exception_test.cpp index e493e90..96b525b 100644 --- a/test/unknown_exception_test.cpp +++ b/test/unknown_exception_test.cpp @@ -4,6 +4,7 @@ //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include +#include #include #include