diff options
| author | Martin Hořeňovský | 2024-12-27 23:46:25 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2025-07-14 10:39:48 +0200 |
| commit | 6097bd6ee910f4ebb6216e0d1817fb84a51a7efb (patch) | |
| tree | 212c1b8e93229f0b9528ea3b3d0d5b1b9fa8ee11 | |
| parent | b62413aee344b346d120ccdc676fedf4bd6233b3 (diff) | |
| download | catch3-6097bd6ee910f4ebb6216e0d1817fb84a51a7efb.tar.gz | |
Mark code past FAIL and SKIP as unreachable
This helps the compiler see that the execution does not continue,
which in turn means that it is not an error if the user does not
return value from the function after FAIL/SKIP.
Closes #2941
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/catch2/catch_all.hpp | 1 | ||||
| -rw-r--r-- | src/catch2/catch_test_macros.hpp | 21 | ||||
| -rw-r--r-- | src/catch2/internal/catch_unreachable.hpp | 52 | ||||
| -rw-r--r-- | src/catch2/meson.build | 1 |
5 files changed, 72 insertions, 4 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ad4ef5d..d8015737 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -144,6 +144,7 @@ set(IMPL_HEADERS ${SOURCES_DIR}/internal/catch_uniform_integer_distribution.hpp ${SOURCES_DIR}/internal/catch_unique_name.hpp ${SOURCES_DIR}/internal/catch_unique_ptr.hpp + ${SOURCES_DIR}/internal/catch_unreachable.hpp ${SOURCES_DIR}/internal/catch_void_type.hpp ${SOURCES_DIR}/internal/catch_wildcard_pattern.hpp ${SOURCES_DIR}/internal/catch_windows_h_proxy.hpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 88dd57ea..0d173715 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -126,6 +126,7 @@ #include <catch2/internal/catch_uniform_integer_distribution.hpp> #include <catch2/internal/catch_unique_name.hpp> #include <catch2/internal/catch_unique_ptr.hpp> +#include <catch2/internal/catch_unreachable.hpp> #include <catch2/internal/catch_void_type.hpp> #include <catch2/internal/catch_wildcard_pattern.hpp> #include <catch2/internal/catch_xmlwriter.hpp> diff --git a/src/catch2/catch_test_macros.hpp b/src/catch2/catch_test_macros.hpp index 6ee2129f..97708557 100644 --- a/src/catch2/catch_test_macros.hpp +++ b/src/catch2/catch_test_macros.hpp @@ -14,6 +14,7 @@ #include <catch2/internal/catch_section.hpp> #include <catch2/internal/catch_test_registry.hpp> #include <catch2/internal/catch_unique_name.hpp> +#include <catch2/internal/catch_unreachable.hpp> // All of our user-facing macros support configuration toggle, that @@ -47,10 +48,16 @@ #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) - #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_FAIL( ... ) do { \ + INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ + Catch::Detail::Unreachable(); \ + } while ( false ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_SKIP( ... ) do { \ + INTERNAL_CATCH_MSG( "CATCH_SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ + Catch::Detail::Unreachable(); \ + } while (false) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) @@ -148,10 +155,16 @@ #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) - #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define FAIL( ... ) do { \ + INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ + Catch::Detail::Unreachable(); \ + } while (false) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) - #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define SKIP( ... ) do { \ + INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ + Catch::Detail::Unreachable(); \ + } while (false) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) diff --git a/src/catch2/internal/catch_unreachable.hpp b/src/catch2/internal/catch_unreachable.hpp new file mode 100644 index 00000000..02cca494 --- /dev/null +++ b/src/catch2/internal/catch_unreachable.hpp @@ -0,0 +1,52 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_UNREACHABLE_HPP_INCLUDED +#define CATCH_UNREACHABLE_HPP_INCLUDED + +/**\file + * Polyfill `std::unreachable` + * + * We need something like `std::unreachable` to tell the compiler that + * some macros, e.g. `FAIL` or `SKIP`, do not continue execution in normal + * manner, and should handle it as such, e.g. not warn if there is no return + * from non-void function after a `FAIL` or `SKIP`. + */ + +#include <exception> + +#if defined( __cpp_lib_unreachable ) && __cpp_lib_unreachable > 202202L +# include <utility> +namespace Catch { + namespace Detail { + using Unreachable = std::unreachable; + } +} // namespace Catch + +#else // vv If we do not have std::unreachable, we implement something similar + +namespace Catch { + namespace Detail { + + [[noreturn]] + inline void Unreachable() noexcept { +# if defined( NDEBUG ) +# if defined( _MSC_VER ) && !defined( __clang__ ) + __assume( false ); +# elif defined( __GNUC__ ) + __builtin_unreachable(); +# endif +# endif // ^^ NDEBUG + std::terminate(); + } + + } // namespace Detail +} // end namespace Catch + +#endif + +#endif // CATCH_UNREACHABLE_HPP_INCLUDED diff --git a/src/catch2/meson.build b/src/catch2/meson.build index 191aea3f..90a04f00 100644 --- a/src/catch2/meson.build +++ b/src/catch2/meson.build @@ -152,6 +152,7 @@ internal_headers = [ 'internal/catch_uniform_integer_distribution.hpp', 'internal/catch_unique_name.hpp', 'internal/catch_unique_ptr.hpp', + 'internal/catch_unreachable.hpp', 'internal/catch_void_type.hpp', 'internal/catch_wildcard_pattern.hpp', 'internal/catch_windows_h_proxy.hpp', |