Line data Source code
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/core/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 defined(__GNUC__) && __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 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 * 71 0 : get_boost_exception( exception const * e ) 72 : { 73 0 : return e; 74 : } 75 : 76 : inline 77 : exception const * 78 : get_boost_exception( ... ) 79 : { 80 : return 0; 81 : } 82 : 83 : inline 84 : std::exception const * 85 : get_std_exception( std::exception const * e ) 86 : { 87 : return e; 88 : } 89 : 90 : inline 91 : std::exception const * 92 0 : get_std_exception( ... ) 93 : { 94 0 : return 0; 95 : } 96 : 97 : inline 98 : char const * 99 0 : get_diagnostic_information( exception const & x, char const * header ) 100 : { 101 : #ifndef BOOST_NO_EXCEPTIONS 102 : try 103 : { 104 : #endif 105 0 : error_info_container * c=x.data_.get(); 106 0 : if( !c ) 107 0 : x.data_.adopt(c=new exception_detail::error_info_container_impl); 108 0 : char const * di=c->diagnostic_information(header); 109 0 : BOOST_ASSERT(di!=0); 110 0 : return di; 111 : #ifndef BOOST_NO_EXCEPTIONS 112 0 : } 113 : catch(...) 114 : { 115 0 : return 0; 116 0 : } 117 : #endif 118 0 : } 119 : 120 : inline 121 : std::string 122 0 : diagnostic_information_impl( boost::exception const * be, std::exception const * se, bool with_what, bool verbose ) 123 : { 124 0 : if( !be && !se ) 125 0 : return "Unknown exception."; 126 : #ifndef BOOST_NO_RTTI 127 0 : if( !be ) 128 0 : be=dynamic_cast<boost::exception const *>(se); 129 0 : if( !se ) 130 0 : se=dynamic_cast<std::exception const *>(be); 131 : #endif 132 0 : char const * wh=0; 133 0 : if( with_what && se ) 134 : { 135 0 : wh=se->what(); 136 0 : if( be && exception_detail::get_diagnostic_information(*be,0)==wh ) 137 0 : return wh; 138 0 : } 139 0 : std::ostringstream tmp; 140 0 : if( be && verbose ) 141 : { 142 0 : char const * const * f=get_error_info<throw_file>(*be); 143 0 : int const * l=get_error_info<throw_line>(*be); 144 0 : char const * const * fn=get_error_info<throw_function>(*be); 145 0 : if( !f && !l && !fn ) 146 0 : tmp << "Throw location unknown (consider using BOOST_THROW_EXCEPTION)\n"; 147 : else 148 : { 149 0 : if( f ) 150 : { 151 0 : tmp << *f; 152 0 : if( l ) 153 0 : tmp << '(' << *l << "): "; 154 0 : } 155 0 : tmp << "Throw in function "; 156 0 : if( fn ) 157 0 : tmp << *fn; 158 : else 159 0 : tmp << "(unknown)"; 160 0 : tmp << '\n'; 161 : } 162 0 : } 163 : #ifndef BOOST_NO_RTTI 164 0 : if ( verbose ) 165 0 : tmp << std::string("Dynamic exception type: ") << 166 0 : core::demangle((be?(BOOST_EXCEPTION_DYNAMIC_TYPEID(*be)):(BOOST_EXCEPTION_DYNAMIC_TYPEID(*se))).type_->name()) << '\n'; 167 : #endif 168 0 : if( with_what && se && verbose ) 169 0 : tmp << "std::exception::what: " << (wh ? wh : "(null)") << '\n'; 170 0 : if( be ) 171 0 : if( char const * s=exception_detail::get_diagnostic_information(*be,tmp.str().c_str()) ) 172 0 : if( *s ) 173 0 : return std::string(s); 174 0 : return tmp.str(); 175 0 : } 176 : } 177 : 178 : template <class T> 179 : std::string 180 0 : diagnostic_information( T const & e, bool verbose=true ) 181 : { 182 0 : 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 * 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