catch_exception_translator_registry.cpp
1 2 // Copyright Catch2 Authors 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 // SPDX-License-Identifier: BSL-1.0 8 #include <catch2/internal/catch_exception_translator_registry.hpp> 9 #include <catch2/internal/catch_compiler_capabilities.hpp> 10 #include <catch2/internal/catch_enforce.hpp> 11 #include <catch2/internal/catch_test_failure_exception.hpp> 12 #include <catch2/internal/catch_move_and_forward.hpp> 13 14 #include <exception> 15 16 namespace Catch { 17 18 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 19 namespace { 20 static std::string tryTranslators( 21 std::vector< 22 Detail::unique_ptr<IExceptionTranslator const>> const& translators ) { 23 if ( translators.empty() ) { 24 std::rethrow_exception( std::current_exception() ); 25 } else { 26 return translators[0]->translate( translators.begin() + 1, 27 translators.end() ); 28 } 29 } 30 31 } 32 #endif //!defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 33 34 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() = default; 35 36 void ExceptionTranslatorRegistry::registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ) { 37 m_translators.push_back( CATCH_MOVE( translator ) ); 38 } 39 40 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 41 std::string ExceptionTranslatorRegistry::translateActiveException() const { 42 // Compiling a mixed mode project with MSVC means that CLR 43 // exceptions will be caught in (...) as well. However, these do 44 // do not fill-in std::current_exception and thus lead to crash 45 // when attempting rethrow. 46 // /EHa switch also causes structured exceptions to be caught 47 // here, but they fill-in current_exception properly, so 48 // at worst the output should be a little weird, instead of 49 // causing a crash. 50 if ( std::current_exception() == nullptr ) { 51 return "Non C++ exception. Possibly a CLR exception."; 52 } 53 54 // First we try user-registered translators. If none of them can 55 // handle the exception, it will be rethrown handled by our defaults. 56 try { 57 return tryTranslators(m_translators); 58 } 59 // To avoid having to handle TFE explicitly everywhere, we just 60 // rethrow it so that it goes back up the caller. 61 catch( TestFailureException& ) { 62 std::rethrow_exception(std::current_exception()); 63 } 64 catch( TestSkipException& ) { 65 std::rethrow_exception(std::current_exception()); 66 } 67 catch( std::exception const& ex ) { 68 return ex.what(); 69 } 70 catch( std::string const& msg ) { 71 return msg; 72 } 73 catch( const char* msg ) { 74 return msg; 75 } 76 catch(...) { 77 return "Unknown exception"; 78 } 79 } 80 81 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 82 std::string ExceptionTranslatorRegistry::translateActiveException() const { 83 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!"); 84 } 85 #endif 86 87 }