Line data Source code
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 0 : 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: 49 : exception_ptr() 50 : { 51 : } 52 : explicit 53 0 : exception_ptr( impl const & ptr ): 54 0 : ptr_(ptr) 55 : { 56 : } 57 : bool 58 : operator==( exception_ptr const & other ) const 59 : { 60 : return ptr_==other.ptr_; 61 : } 62 : bool 63 : operator!=( exception_ptr const & other ) const 64 : { 65 : return ptr_!=other.ptr_; 66 : } 67 0 : operator unspecified_bool_type() const 68 : { 69 0 : return ptr_?&impl::get:0; 70 : } 71 : }; 72 : 73 : template <class T> 74 : inline 75 : exception_ptr 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 94 0 : to_string( original_exception_type const & x ) 95 : { 96 0 : return core::demangle(x.value()->name()); 97 : } 98 : #endif 99 : 100 : namespace 101 : exception_detail 102 : { 103 : struct 104 0 : bad_alloc_: 105 : boost::exception, 106 : std::bad_alloc 107 : { 108 0 : ~bad_alloc_() BOOST_NOEXCEPT_OR_NOTHROW { } 109 : }; 110 : 111 : struct 112 0 : bad_exception_: 113 : boost::exception, 114 : std::bad_exception 115 : { 116 0 : ~bad_exception_() BOOST_NOEXCEPT_OR_NOTHROW { } 117 : }; 118 : 119 : template <class Exception> 120 : exception_ptr 121 0 : get_static_exception_object() 122 : { 123 0 : Exception ba; 124 0 : exception_detail::clone_impl<Exception> c(ba); 125 : #ifndef BOOST_EXCEPTION_DISABLE 126 0 : c << 127 0 : throw_function(BOOST_CURRENT_FUNCTION) << 128 0 : throw_file(__FILE__) << 129 : throw_line(__LINE__); 130 : #endif 131 0 : static exception_ptr ep(shared_ptr<exception_detail::clone_base const>(new exception_detail::clone_impl<Exception>(c))); 132 0 : 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 0 : unknown_exception: 155 : public boost::exception, 156 : public std::exception 157 : { 158 : public: 159 : 160 : unknown_exception() 161 : { 162 : } 163 : 164 : explicit 165 : unknown_exception( std::exception const & e ) 166 : { 167 : add_original_type(e); 168 : } 169 : 170 : explicit 171 : unknown_exception( boost::exception const & e ): 172 : boost::exception(e) 173 : { 174 : add_original_type(e); 175 : } 176 : 177 0 : ~unknown_exception() BOOST_NOEXCEPT_OR_NOTHROW 178 0 : { 179 0 : } 180 : 181 : private: 182 : 183 : template <class E> 184 : void 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 210 : current_exception_std_exception_wrapper( T const & e1 ): 211 : T(e1) 212 : { 213 : add_original_type(e1); 214 : } 215 : 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 : 223 0 : ~current_exception_std_exception_wrapper() BOOST_NOEXCEPT_OR_NOTHROW 224 : { 225 0 : } 226 : 227 : private: 228 : 229 : template <class E> 230 : void 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 * 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 * 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 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 280 : current_exception_unknown_exception() 281 : { 282 : return boost::copy_exception(unknown_exception()); 283 : } 284 : 285 : inline 286 : exception_ptr 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 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 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 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 461 0 : rethrow_exception( exception_ptr const & p ) 462 : { 463 0 : BOOST_ASSERT(p); 464 0 : p.ptr_->rethrow(); 465 0 : 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 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 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