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