/ externals / catch / src / catch2 / internal / catch_exception_translator_registry.cpp
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  }