1 //Copyright (c) 2006-2010 Emil Dotchevski and Reverge Studios, Inc. 2 3 //Distributed under the Boost Software License, Version 1.0. (See accompanying 4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 5 6 #ifndef BOOST_EXCEPTION_0552D49838DD11DD90146B8956D89593 7 #define BOOST_EXCEPTION_0552D49838DD11DD90146B8956D89593 8 9 #include <boost/config.hpp> 10 #include <boost/exception/get_error_info.hpp> 11 #include <boost/exception/info.hpp> 12 #include <boost/utility/enable_if.hpp> 13 #ifndef BOOST_NO_RTTI 14 #include <boost/core/demangle.hpp> 15 #endif 16 #include <exception> 17 #include <sstream> 18 #include <string> 19 #ifndef BOOST_NO_EXCEPTIONS 20 #include <boost/exception/current_exception_cast.hpp> 21 #endif 22 23 #ifndef BOOST_EXCEPTION_ENABLE_WARNINGS 24 #if __GNUC__*100+__GNUC_MINOR__>301 25 #pragma GCC system_header 26 #endif 27 #ifdef __clang__ 28 #pragma clang system_header 29 #endif 30 #ifdef _MSC_VER 31 #pragma warning(push,1) 32 #endif 33 #endif 34 35 #ifndef BOOST_NO_EXCEPTIONS 36 namespace 37 boost 38 { 39 namespace 40 exception_detail 41 { 42 std::string diagnostic_information_impl( boost::exception const *, std::exception const *, bool, bool ); 43 } 44 45 inline 46 std::string current_exception_diagnostic_information(bool verbose=true)47 current_exception_diagnostic_information( bool verbose=true) 48 { 49 boost::exception const * be=current_exception_cast<boost::exception const>(); 50 std::exception const * se=current_exception_cast<std::exception const>(); 51 if( be || se ) 52 return exception_detail::diagnostic_information_impl(be,se,true,verbose); 53 #if defined(__GLIBCXX__) && __cplusplus >= 201103L && !defined(BOOST_NO_RTTI) 54 else if (auto* p=std::current_exception().__cxa_exception_type()) 55 return "Dynamic exception type: "+boost::core::demangle(p->name()); 56 #endif 57 else 58 return "No diagnostic information available."; 59 } 60 } 61 #endif 62 63 namespace 64 boost 65 { 66 namespace 67 exception_detail 68 { 69 inline 70 exception const * get_boost_exception(exception const * e)71 get_boost_exception( exception const * e ) 72 { 73 return e; 74 } 75 76 inline 77 exception const * get_boost_exception(...)78 get_boost_exception( ... ) 79 { 80 return 0; 81 } 82 83 inline 84 std::exception const * get_std_exception(std::exception const * e)85 get_std_exception( std::exception const * e ) 86 { 87 return e; 88 } 89 90 inline 91 std::exception const * get_std_exception(...)92 get_std_exception( ... ) 93 { 94 return 0; 95 } 96 97 inline 98 char const * get_diagnostic_information(exception const & x,char const * header)99 get_diagnostic_information( exception const & x, char const * header ) 100 { 101 #ifndef BOOST_NO_EXCEPTIONS 102 try 103 { 104 #endif 105 error_info_container * c=x.data_.get(); 106 if( !c ) 107 x.data_.adopt(c=new exception_detail::error_info_container_impl); 108 char const * di=c->diagnostic_information(header); 109 BOOST_ASSERT(di!=0); 110 return di; 111 #ifndef BOOST_NO_EXCEPTIONS 112 } 113 catch(...) 114 { 115 return 0; 116 } 117 #endif 118 } 119 120 inline 121 std::string diagnostic_information_impl(boost::exception const * be,std::exception const * se,bool with_what,bool verbose)122 diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what, bool verbose ) 123 { 124 if( !be && !se ) 125 return "Unknown exception."; 126 #ifndef BOOST_NO_RTTI 127 if( !be ) 128 be=dynamic_cast<boost::exception const *>(se); 129 if( !se ) 130 se=dynamic_cast<std::exception const *>(be); 131 #endif 132 char const * wh=0; 133 if( with_what && se ) 134 { 135 wh=se->what(); 136 if( be && exception_detail::get_diagnostic_information(*be,0)==wh ) 137 return wh; 138 } 139 std::ostringstream tmp; 140 if( be && verbose ) 141 { 142 char const * const * f=get_error_info<throw_file>(*be); 143 int const * l=get_error_info<throw_line>(*be); 144 char const * const * fn=get_error_info<throw_function>(*be); 145 if( !f && !l && !fn ) 146 tmp << "Throw location unknown (consider using BOOST_THROW_EXCEPTION)\n"; 147 else 148 { 149 if( f ) 150 { 151 tmp << *f; 152 if( int const * l=get_error_info<throw_line>(*be) ) 153 tmp << '(' << *l << "): "; 154 } 155 tmp << "Throw in function "; 156 if( char const * const * fn=get_error_info<throw_function>(*be) ) 157 tmp << *fn; 158 else 159 tmp << "(unknown)"; 160 tmp << '\n'; 161 } 162 } 163 #ifndef BOOST_NO_RTTI 164 if ( verbose ) 165 tmp << std::string("Dynamic exception type: ") << 166 core::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n'; 167 #endif 168 if( with_what && se && verbose ) 169 tmp << "std::exception::what: " << (wh ? wh : "(null)") << '\n'; 170 if( be ) 171 if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) ) 172 if( *s ) 173 return std::string(s); 174 return tmp.str(); 175 } 176 } 177 178 template <class T> 179 std::string diagnostic_information(T const & e,bool verbose=true)180 diagnostic_information( T const & e, bool verbose=true ) 181 { 182 return exception_detail::diagnostic_information_impl(exception_detail::get_boost_exception(&e),exception_detail::get_std_exception(&e),true,verbose); 183 } 184 185 inline 186 char const * diagnostic_information_what(exception const & e,bool verbose=true)187 diagnostic_information_what( exception const & e, bool verbose=true ) BOOST_NOEXCEPT_OR_NOTHROW 188 { 189 char const * w=0; 190 #ifndef BOOST_NO_EXCEPTIONS 191 try 192 { 193 #endif 194 (void) exception_detail::diagnostic_information_impl(&e,0,false,verbose); 195 if( char const * di=exception_detail::get_diagnostic_information(e,0) ) 196 return di; 197 else 198 return "Failed to produce boost::diagnostic_information_what()"; 199 #ifndef BOOST_NO_EXCEPTIONS 200 } 201 catch( 202 ... ) 203 { 204 } 205 #endif 206 return w; 207 } 208 } 209 210 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 211 #pragma warning(pop) 212 #endif 213 #endif 214