1 //Copyright (c) 2006-2009 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 UUID_618474C2DE1511DEB74A388C56D89593 7 #define UUID_618474C2DE1511DEB74A388C56D89593 8 9 #include <boost/config.hpp> 10 #ifdef BOOST_NO_EXCEPTIONS 11 #error This header requires exception handling to be enabled. 12 #endif 13 #include <boost/exception/exception.hpp> 14 #include <boost/exception/info.hpp> 15 #include <boost/exception/diagnostic_information.hpp> 16 #include <boost/exception/detail/clone_current_exception.hpp> 17 #include <boost/exception/detail/type_info.hpp> 18 #ifndef BOOST_NO_RTTI 19 #include <boost/core/demangle.hpp> 20 #endif 21 #include <boost/shared_ptr.hpp> 22 #include <stdexcept> 23 #include <new> 24 #include <ios> 25 #include <stdlib.h> 26 27 #if (__GNUC__*100+__GNUC_MINOR__>301) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 28 #pragma GCC system_header 29 #endif 30 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 31 #pragma warning(push,1) 32 #endif 33 34 namespace 35 boost 36 { 37 class exception_ptr; 38 BOOST_NORETURN void rethrow_exception( exception_ptr const & ); 39 exception_ptr current_exception(); 40 41 class 42 exception_ptr 43 { 44 typedef boost::shared_ptr<exception_detail::clone_base const> impl; 45 impl ptr_; 46 friend void rethrow_exception( exception_ptr const & ); 47 typedef exception_detail::clone_base const * (impl::*unspecified_bool_type)() const; 48 public: exception_ptr()49 exception_ptr() 50 { 51 } 52 explicit exception_ptr(impl const & ptr)53 exception_ptr( impl const & ptr ): 54 ptr_(ptr) 55 { 56 } 57 bool operator ==(exception_ptr const & other) const58 operator==( exception_ptr const & other ) const 59 { 60 return ptr_==other.ptr_; 61 } 62 bool operator !=(exception_ptr const & other) const63 operator!=( exception_ptr const & other ) const 64 { 65 return ptr_!=other.ptr_; 66 } operator unspecified_bool_type() const67 operator unspecified_bool_type() const 68 { 69 return ptr_?&impl::get:0; 70 } 71 }; 72 73 template <class T> 74 inline 75 exception_ptr copy_exception(T const & e)76 copy_exception( T const & e ) 77 { 78 try 79 { 80 throw enable_current_exception(e); 81 } 82 catch( 83 ... ) 84 { 85 return current_exception(); 86 } 87 } 88 89 #ifndef BOOST_NO_RTTI 90 typedef error_info<struct tag_original_exception_type,std::type_info const *> original_exception_type; 91 92 inline 93 std::string to_string(original_exception_type const & x)94 to_string( original_exception_type const & x ) 95 { 96 return core::demangle(x.value()->name()); 97 } 98 #endif 99 100 namespace 101 exception_detail 102 { 103 struct 104 bad_alloc_: 105 boost::exception, 106 std::bad_alloc 107 { ~bad_alloc_boost::exception_detail::bad_alloc_108 ~bad_alloc_() BOOST_NOEXCEPT_OR_NOTHROW { } 109 }; 110 111 struct 112 bad_exception_: 113 boost::exception, 114 std::bad_exception 115 { ~bad_exception_boost::exception_detail::bad_exception_116 ~bad_exception_() BOOST_NOEXCEPT_OR_NOTHROW { } 117 }; 118 119 template <class Exception> 120 exception_ptr get_static_exception_object()121 get_static_exception_object() 122 { 123 Exception ba; 124 exception_detail::clone_impl<Exception> c(ba); 125 #ifndef BOOST_EXCEPTION_DISABLE 126 c << 127 throw_function(BOOST_CURRENT_FUNCTION) << 128 throw_file(__FILE__) << 129 throw_line(__LINE__); 130 #endif 131 static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c))); 132 return ep; 133 } 134 135 template <class Exception> 136 struct 137 exception_ptr_static_exception_object 138 { 139 static exception_ptr const e; 140 }; 141 142 template <class Exception> 143 exception_ptr const 144 exception_ptr_static_exception_object<Exception>:: 145 e = get_static_exception_object<Exception>(); 146 } 147 148 #if defined(__GNUC__) 149 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 150 # pragma GCC visibility push (default) 151 # endif 152 #endif 153 class 154 unknown_exception: 155 public boost::exception, 156 public std::exception 157 { 158 public: 159 unknown_exception()160 unknown_exception() 161 { 162 } 163 164 explicit unknown_exception(std::exception const & e)165 unknown_exception( std::exception const & e ) 166 { 167 add_original_type(e); 168 } 169 170 explicit unknown_exception(boost::exception const & e)171 unknown_exception( boost::exception const & e ): 172 boost::exception(e) 173 { 174 add_original_type(e); 175 } 176 ~unknown_exception()177 ~unknown_exception() BOOST_NOEXCEPT_OR_NOTHROW 178 { 179 } 180 181 private: 182 183 template <class E> 184 void add_original_type(E const & e)185 add_original_type( E const & e ) 186 { 187 #ifndef BOOST_NO_RTTI 188 (*this) << original_exception_type(&typeid(e)); 189 #endif 190 } 191 }; 192 #if defined(__GNUC__) 193 # if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 194 # pragma GCC visibility pop 195 # endif 196 #endif 197 198 namespace 199 exception_detail 200 { 201 template <class T> 202 class 203 current_exception_std_exception_wrapper: 204 public T, 205 public boost::exception 206 { 207 public: 208 209 explicit current_exception_std_exception_wrapper(T const & e1)210 current_exception_std_exception_wrapper( T const & e1 ): 211 T(e1) 212 { 213 add_original_type(e1); 214 } 215 current_exception_std_exception_wrapper(T const & e1,boost::exception const & e2)216 current_exception_std_exception_wrapper( T const & e1, boost::exception const & e2 ): 217 T(e1), 218 boost::exception(e2) 219 { 220 add_original_type(e1); 221 } 222 ~current_exception_std_exception_wrapper()223 ~current_exception_std_exception_wrapper() BOOST_NOEXCEPT_OR_NOTHROW 224 { 225 } 226 227 private: 228 229 template <class E> 230 void add_original_type(E const & e)231 add_original_type( E const & e ) 232 { 233 #ifndef BOOST_NO_RTTI 234 (*this) << original_exception_type(&typeid(e)); 235 #endif 236 } 237 }; 238 239 #ifdef BOOST_NO_RTTI 240 template <class T> 241 boost::exception const * get_boost_exception(T const *)242 get_boost_exception( T const * ) 243 { 244 try 245 { 246 throw; 247 } 248 catch( 249 boost::exception & x ) 250 { 251 return &x; 252 } 253 catch(...) 254 { 255 return 0; 256 } 257 } 258 #else 259 template <class T> 260 boost::exception const * get_boost_exception(T const * x)261 get_boost_exception( T const * x ) 262 { 263 return dynamic_cast<boost::exception const *>(x); 264 } 265 #endif 266 267 template <class T> 268 inline 269 exception_ptr current_exception_std_exception(T const & e1)270 current_exception_std_exception( T const & e1 ) 271 { 272 if( boost::exception const * e2 = get_boost_exception(&e1) ) 273 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1,*e2)); 274 else 275 return boost::copy_exception(current_exception_std_exception_wrapper<T>(e1)); 276 } 277 278 inline 279 exception_ptr current_exception_unknown_exception()280 current_exception_unknown_exception() 281 { 282 return boost::copy_exception(unknown_exception()); 283 } 284 285 inline 286 exception_ptr current_exception_unknown_boost_exception(boost::exception const & e)287 current_exception_unknown_boost_exception( boost::exception const & e ) 288 { 289 return boost::copy_exception(unknown_exception(e)); 290 } 291 292 inline 293 exception_ptr current_exception_unknown_std_exception(std::exception const & e)294 current_exception_unknown_std_exception( std::exception const & e ) 295 { 296 if( boost::exception const * be = get_boost_exception(&e) ) 297 return current_exception_unknown_boost_exception(*be); 298 else 299 return boost::copy_exception(unknown_exception(e)); 300 } 301 302 inline 303 exception_ptr current_exception_impl()304 current_exception_impl() 305 { 306 exception_detail::clone_base const * e=0; 307 switch( 308 exception_detail::clone_current_exception(e) ) 309 { 310 case exception_detail::clone_current_exception_result:: 311 success: 312 { 313 BOOST_ASSERT(e!=0); 314 return exception_ptr(shared_ptr<exception_detail::clone_base const>(e)); 315 } 316 case exception_detail::clone_current_exception_result:: 317 bad_alloc: 318 { 319 BOOST_ASSERT(!e); 320 return exception_detail::exception_ptr_static_exception_object<bad_alloc_>::e; 321 } 322 case exception_detail::clone_current_exception_result:: 323 bad_exception: 324 { 325 BOOST_ASSERT(!e); 326 return exception_detail::exception_ptr_static_exception_object<bad_exception_>::e; 327 } 328 default: 329 BOOST_ASSERT(0); 330 case exception_detail::clone_current_exception_result:: 331 not_supported: 332 { 333 BOOST_ASSERT(!e); 334 try 335 { 336 throw; 337 } 338 catch( 339 exception_detail::clone_base & e ) 340 { 341 return exception_ptr(shared_ptr<exception_detail::clone_base const>(e.clone())); 342 } 343 catch( 344 std::domain_error & e ) 345 { 346 return exception_detail::current_exception_std_exception(e); 347 } 348 catch( 349 std::invalid_argument & e ) 350 { 351 return exception_detail::current_exception_std_exception(e); 352 } 353 catch( 354 std::length_error & e ) 355 { 356 return exception_detail::current_exception_std_exception(e); 357 } 358 catch( 359 std::out_of_range & e ) 360 { 361 return exception_detail::current_exception_std_exception(e); 362 } 363 catch( 364 std::logic_error & e ) 365 { 366 return exception_detail::current_exception_std_exception(e); 367 } 368 catch( 369 std::range_error & e ) 370 { 371 return exception_detail::current_exception_std_exception(e); 372 } 373 catch( 374 std::overflow_error & e ) 375 { 376 return exception_detail::current_exception_std_exception(e); 377 } 378 catch( 379 std::underflow_error & e ) 380 { 381 return exception_detail::current_exception_std_exception(e); 382 } 383 catch( 384 std::ios_base::failure & e ) 385 { 386 return exception_detail::current_exception_std_exception(e); 387 } 388 catch( 389 std::runtime_error & e ) 390 { 391 return exception_detail::current_exception_std_exception(e); 392 } 393 catch( 394 std::bad_alloc & e ) 395 { 396 return exception_detail::current_exception_std_exception(e); 397 } 398 #ifndef BOOST_NO_TYPEID 399 catch( 400 std::bad_cast & e ) 401 { 402 return exception_detail::current_exception_std_exception(e); 403 } 404 catch( 405 std::bad_typeid & e ) 406 { 407 return exception_detail::current_exception_std_exception(e); 408 } 409 #endif 410 catch( 411 std::bad_exception & e ) 412 { 413 return exception_detail::current_exception_std_exception(e); 414 } 415 catch( 416 std::exception & e ) 417 { 418 return exception_detail::current_exception_unknown_std_exception(e); 419 } 420 catch( 421 boost::exception & e ) 422 { 423 return exception_detail::current_exception_unknown_boost_exception(e); 424 } 425 catch( 426 ... ) 427 { 428 return exception_detail::current_exception_unknown_exception(); 429 } 430 } 431 } 432 } 433 } 434 435 inline 436 exception_ptr current_exception()437 current_exception() 438 { 439 exception_ptr ret; 440 try 441 { 442 ret=exception_detail::current_exception_impl(); 443 } 444 catch( 445 std::bad_alloc & ) 446 { 447 ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_alloc_>::e; 448 } 449 catch( 450 ... ) 451 { 452 ret=exception_detail::exception_ptr_static_exception_object<exception_detail::bad_exception_>::e; 453 } 454 BOOST_ASSERT(ret); 455 return ret; 456 } 457 458 BOOST_NORETURN 459 inline 460 void rethrow_exception(exception_ptr const & p)461 rethrow_exception( exception_ptr const & p ) 462 { 463 BOOST_ASSERT(p); 464 p.ptr_->rethrow(); 465 BOOST_ASSERT(0); 466 #if defined(UNDER_CE) 467 // some CE platforms don't define ::abort() 468 exit(-1); 469 #else 470 abort(); 471 #endif 472 } 473 474 inline 475 std::string diagnostic_information(exception_ptr const & p,bool verbose=true)476 diagnostic_information( exception_ptr const & p, bool verbose=true ) 477 { 478 if( p ) 479 try 480 { 481 rethrow_exception(p); 482 } 483 catch( 484 ... ) 485 { 486 return current_exception_diagnostic_information(verbose); 487 } 488 return "<empty>"; 489 } 490 491 inline 492 std::string to_string(exception_ptr const & p)493 to_string( exception_ptr const & p ) 494 { 495 std::string s='\n'+diagnostic_information(p); 496 std::string padding(" "); 497 std::string r; 498 bool f=false; 499 for( std::string::const_iterator i=s.begin(),e=s.end(); i!=e; ++i ) 500 { 501 if( f ) 502 r+=padding; 503 char c=*i; 504 r+=c; 505 f=(c=='\n'); 506 } 507 return r; 508 } 509 } 510 511 #if defined(_MSC_VER) && !defined(BOOST_EXCEPTION_ENABLE_WARNINGS) 512 #pragma warning(pop) 513 #endif 514 #endif 515