1 // boost/catch_exceptions.hpp -----------------------------------------------// 2 3 // Copyright Beman Dawes 1995-2001. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 // See http://www.boost.org/libs/test for documentation. 8 9 // Revision History 10 // 13 Jun 01 report_exception() made inline. (John Maddock, Jesse Jones) 11 // 26 Feb 01 Numerous changes suggested during formal review. (Beman) 12 // 25 Jan 01 catch_exceptions.hpp code factored out of cpp_main.cpp. 13 // 22 Jan 01 Remove test_tools dependencies to reduce coupling. 14 // 5 Nov 00 Initial boost version (Beman Dawes) 15 16 #ifndef BOOST_CATCH_EXCEPTIONS_HPP 17 #define BOOST_CATCH_EXCEPTIONS_HPP 18 19 // header dependencies are deliberately restricted to the standard library 20 // to reduce coupling to other boost libraries. 21 #include <string> // for string 22 #include <new> // for bad_alloc 23 #include <ostream> // for ostream 24 #include <typeinfo> // for bad_cast, bad_typeid 25 #include <exception> // for exception, bad_exception 26 #include <stdexcept> // for std exception hierarchy 27 #include <boost/config.hpp> 28 #include <boost/cstdlib.hpp> // for exit codes 29 30 # if defined(BOOST_BORLANDC) && (__BORLANDC__ <= 0x0551) 31 # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT 32 # endif 33 34 #if defined(MPW_CPLUS) && (MPW_CPLUS <= 0x890) 35 # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT 36 namespace std { class bad_typeid { }; } 37 # endif 38 39 namespace boost 40 { 41 42 namespace detail 43 { 44 // A separate reporting function was requested during formal review. report_exception(std::ostream & os,const char * name,const char * info)45 inline void report_exception( std::ostream & os, 46 const char * name, const char * info ) 47 { os << "\n** uncaught exception: " << name << " " << info << std::endl; } 48 } 49 50 // catch_exceptions ------------------------------------------------------// 51 52 template< class Generator > // Generator is function object returning int catch_exceptions(Generator function_object,std::ostream & out,std::ostream & err)53 int catch_exceptions( Generator function_object, 54 std::ostream & out, std::ostream & err ) 55 { 56 int result = 0; // quiet compiler warnings 57 bool exception_thrown = true; // avoid setting result for each excptn type 58 59 #ifndef BOOST_NO_EXCEPTIONS 60 try 61 { 62 #endif 63 result = function_object(); 64 exception_thrown = false; 65 #ifndef BOOST_NO_EXCEPTIONS 66 } 67 68 // As a result of hard experience with strangely interleaved output 69 // under some compilers, there is a lot of use of endl in the code below 70 // where a simple '\n' might appear to do. 71 72 // The rules for catch & arguments are a bit different from function 73 // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't 74 // required, but it doesn't hurt and some programmers ask for it. 75 76 catch ( const char * ex ) 77 { detail::report_exception( out, "", ex ); } 78 catch ( const std::string & ex ) 79 { detail::report_exception( out, "", ex.c_str() ); } 80 81 // std:: exceptions 82 catch ( const std::bad_alloc & ex ) 83 { detail::report_exception( out, "std::bad_alloc:", ex.what() ); } 84 85 # ifndef BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT 86 catch ( const std::bad_cast & ex ) 87 { detail::report_exception( out, "std::bad_cast:", ex.what() ); } 88 catch ( const std::bad_typeid & ex ) 89 { detail::report_exception( out, "std::bad_typeid:", ex.what() ); } 90 # else 91 catch ( const std::bad_cast & ) 92 { detail::report_exception( out, "std::bad_cast", "" ); } 93 catch ( const std::bad_typeid & ) 94 { detail::report_exception( out, "std::bad_typeid", "" ); } 95 # endif 96 97 catch ( const std::bad_exception & ex ) 98 { detail::report_exception( out, "std::bad_exception:", ex.what() ); } 99 catch ( const std::domain_error & ex ) 100 { detail::report_exception( out, "std::domain_error:", ex.what() ); } 101 catch ( const std::invalid_argument & ex ) 102 { detail::report_exception( out, "std::invalid_argument:", ex.what() ); } 103 catch ( const std::length_error & ex ) 104 { detail::report_exception( out, "std::length_error:", ex.what() ); } 105 catch ( const std::out_of_range & ex ) 106 { detail::report_exception( out, "std::out_of_range:", ex.what() ); } 107 catch ( const std::range_error & ex ) 108 { detail::report_exception( out, "std::range_error:", ex.what() ); } 109 catch ( const std::overflow_error & ex ) 110 { detail::report_exception( out, "std::overflow_error:", ex.what() ); } 111 catch ( const std::underflow_error & ex ) 112 { detail::report_exception( out, "std::underflow_error:", ex.what() ); } 113 catch ( const std::logic_error & ex ) 114 { detail::report_exception( out, "std::logic_error:", ex.what() ); } 115 catch ( const std::runtime_error & ex ) 116 { detail::report_exception( out, "std::runtime_error:", ex.what() ); } 117 catch ( const std::exception & ex ) 118 { detail::report_exception( out, "std::exception:", ex.what() ); } 119 120 catch ( ... ) 121 { detail::report_exception( out, "unknown exception", "" ); } 122 #endif // BOOST_NO_EXCEPTIONS 123 124 if ( exception_thrown ) result = boost::exit_exception_failure; 125 126 if ( result != 0 && result != exit_success ) 127 { 128 out << std::endl << "**** returning with error code " 129 << result << std::endl; 130 err 131 << "********** errors detected; see stdout for details ***********" 132 << std::endl; 133 } 134 #if !defined(BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE) 135 else { out << std::flush << "no errors detected" << std::endl; } 136 #endif 137 return result; 138 } // catch_exceptions 139 140 } // boost 141 142 #endif // BOOST_CATCH_EXCEPTIONS_HPP 143 144