Brian Silverman | 2987761 | 2018-08-05 00:42:41 -0700 | [diff] [blame^] | 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 <typeinfo> // for bad_cast, bad_typeid |
| 24 | #include <exception> // for exception, bad_exception |
| 25 | #include <stdexcept> // for std exception hierarchy |
| 26 | #include <boost/cstdlib.hpp> // for exit codes |
| 27 | #include <ostream> // for ostream |
| 28 | |
| 29 | # if defined(__BORLANDC__) && (__BORLANDC__ <= 0x0551) |
| 30 | # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
| 31 | # endif |
| 32 | |
| 33 | #if defined(MPW_CPLUS) && (MPW_CPLUS <= 0x890) |
| 34 | # define BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
| 35 | namespace std { class bad_typeid { }; } |
| 36 | # endif |
| 37 | |
| 38 | namespace boost |
| 39 | { |
| 40 | |
| 41 | namespace detail |
| 42 | { |
| 43 | // A separate reporting function was requested during formal review. |
| 44 | inline void report_exception( std::ostream & os, |
| 45 | const char * name, const char * info ) |
| 46 | { os << "\n** uncaught exception: " << name << " " << info << std::endl; } |
| 47 | } |
| 48 | |
| 49 | // catch_exceptions ------------------------------------------------------// |
| 50 | |
| 51 | template< class Generator > // Generator is function object returning int |
| 52 | int catch_exceptions( Generator function_object, |
| 53 | std::ostream & out, std::ostream & err ) |
| 54 | { |
| 55 | int result = 0; // quiet compiler warnings |
| 56 | bool exception_thrown = true; // avoid setting result for each excptn type |
| 57 | |
| 58 | #ifndef BOOST_NO_EXCEPTIONS |
| 59 | try |
| 60 | { |
| 61 | #endif |
| 62 | result = function_object(); |
| 63 | exception_thrown = false; |
| 64 | #ifndef BOOST_NO_EXCEPTIONS |
| 65 | } |
| 66 | |
| 67 | // As a result of hard experience with strangely interleaved output |
| 68 | // under some compilers, there is a lot of use of endl in the code below |
| 69 | // where a simple '\n' might appear to do. |
| 70 | |
| 71 | // The rules for catch & arguments are a bit different from function |
| 72 | // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't |
| 73 | // required, but it doesn't hurt and some programmers ask for it. |
| 74 | |
| 75 | catch ( const char * ex ) |
| 76 | { detail::report_exception( out, "", ex ); } |
| 77 | catch ( const std::string & ex ) |
| 78 | { detail::report_exception( out, "", ex.c_str() ); } |
| 79 | |
| 80 | // std:: exceptions |
| 81 | catch ( const std::bad_alloc & ex ) |
| 82 | { detail::report_exception( out, "std::bad_alloc:", ex.what() ); } |
| 83 | |
| 84 | # ifndef BOOST_BUILT_IN_EXCEPTIONS_MISSING_WHAT |
| 85 | catch ( const std::bad_cast & ex ) |
| 86 | { detail::report_exception( out, "std::bad_cast:", ex.what() ); } |
| 87 | catch ( const std::bad_typeid & ex ) |
| 88 | { detail::report_exception( out, "std::bad_typeid:", ex.what() ); } |
| 89 | # else |
| 90 | catch ( const std::bad_cast & ) |
| 91 | { detail::report_exception( out, "std::bad_cast", "" ); } |
| 92 | catch ( const std::bad_typeid & ) |
| 93 | { detail::report_exception( out, "std::bad_typeid", "" ); } |
| 94 | # endif |
| 95 | |
| 96 | catch ( const std::bad_exception & ex ) |
| 97 | { detail::report_exception( out, "std::bad_exception:", ex.what() ); } |
| 98 | catch ( const std::domain_error & ex ) |
| 99 | { detail::report_exception( out, "std::domain_error:", ex.what() ); } |
| 100 | catch ( const std::invalid_argument & ex ) |
| 101 | { detail::report_exception( out, "std::invalid_argument:", ex.what() ); } |
| 102 | catch ( const std::length_error & ex ) |
| 103 | { detail::report_exception( out, "std::length_error:", ex.what() ); } |
| 104 | catch ( const std::out_of_range & ex ) |
| 105 | { detail::report_exception( out, "std::out_of_range:", ex.what() ); } |
| 106 | catch ( const std::range_error & ex ) |
| 107 | { detail::report_exception( out, "std::range_error:", ex.what() ); } |
| 108 | catch ( const std::overflow_error & ex ) |
| 109 | { detail::report_exception( out, "std::overflow_error:", ex.what() ); } |
| 110 | catch ( const std::underflow_error & ex ) |
| 111 | { detail::report_exception( out, "std::underflow_error:", ex.what() ); } |
| 112 | catch ( const std::logic_error & ex ) |
| 113 | { detail::report_exception( out, "std::logic_error:", ex.what() ); } |
| 114 | catch ( const std::runtime_error & ex ) |
| 115 | { detail::report_exception( out, "std::runtime_error:", ex.what() ); } |
| 116 | catch ( const std::exception & ex ) |
| 117 | { detail::report_exception( out, "std::exception:", ex.what() ); } |
| 118 | |
| 119 | catch ( ... ) |
| 120 | { detail::report_exception( out, "unknown exception", "" ); } |
| 121 | #endif // BOOST_NO_EXCEPTIONS |
| 122 | |
| 123 | if ( exception_thrown ) result = boost::exit_exception_failure; |
| 124 | |
| 125 | if ( result != 0 && result != exit_success ) |
| 126 | { |
| 127 | out << std::endl << "**** returning with error code " |
| 128 | << result << std::endl; |
| 129 | err |
| 130 | << "********** errors detected; see stdout for details ***********" |
| 131 | << std::endl; |
| 132 | } |
| 133 | #if !defined(BOOST_NO_CPP_MAIN_SUCCESS_MESSAGE) |
| 134 | else { out << std::flush << "no errors detected" << std::endl; } |
| 135 | #endif |
| 136 | return result; |
| 137 | } // catch_exceptions |
| 138 | |
| 139 | } // boost |
| 140 | |
| 141 | #endif // BOOST_CATCH_EXCEPTIONS_HPP |
| 142 | |