diff --git a/src/util/check.cpp b/src/util/check.cpp index 77783c843d7..37c4ec0a2b1 100644 --- a/src/util/check.cpp +++ b/src/util/check.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2022 The Bitcoin Core developers +// Copyright (c) 2022-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -11,30 +11,32 @@ #include #include +#include #include #include -std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func) +std::string StrFormatInternalBug(std::string_view msg, const std::source_location& loc) { return strprintf("Internal bug detected: %s\n%s:%d (%s)\n" "%s %s\n" "Please report this issue here: %s\n", - msg, file, line, func, CLIENT_NAME, FormatFullVersion(), CLIENT_BUGREPORT); + msg, loc.file_name(), loc.line(), loc.function_name(), + CLIENT_NAME, FormatFullVersion(), CLIENT_BUGREPORT); } -NonFatalCheckError::NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func) - : std::runtime_error{StrFormatInternalBug(msg, file, line, func)} +NonFatalCheckError::NonFatalCheckError(std::string_view msg, const std::source_location& loc) + : std::runtime_error{StrFormatInternalBug(msg, loc)} { } bool g_detail_test_only_CheckFailuresAreExceptionsNotAborts{false}; -void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion) +void assertion_fail(const std::source_location& loc, std::string_view assertion) { if (g_detail_test_only_CheckFailuresAreExceptionsNotAborts) { - throw NonFatalCheckError{assertion, file, line, func}; + throw NonFatalCheckError{assertion, loc}; } - auto str = strprintf("%s:%s %s: Assertion `%s' failed.\n", file, line, func, assertion); + auto str = strprintf("%s:%s %s: Assertion `%s' failed.\n", loc.file_name(), loc.line(), loc.function_name(), assertion); fwrite(str.data(), 1, str.size(), stderr); std::abort(); } diff --git a/src/util/check.h b/src/util/check.h index 1267d9b5826..fc9fa1271ac 100644 --- a/src/util/check.h +++ b/src/util/check.h @@ -1,4 +1,4 @@ -// Copyright (c) 2019-2022 The Bitcoin Core developers +// Copyright (c) 2019-present The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,6 +9,7 @@ #include #include // IWYU pragma: export +#include #include #include #include @@ -52,26 +53,26 @@ struct test_only_CheckFailuresAreExceptionsNotAborts { ~test_only_CheckFailuresAreExceptionsNotAborts() { g_detail_test_only_CheckFailuresAreExceptionsNotAborts = false; }; }; -std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func); +std::string StrFormatInternalBug(std::string_view msg, const std::source_location& loc); class NonFatalCheckError : public std::runtime_error { public: - NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func); + NonFatalCheckError(std::string_view msg, const std::source_location& loc); }; /** Internal helper */ -void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion); +void assertion_fail(const std::source_location& loc, std::string_view assertion); /** Helper for CHECK_NONFATAL() */ template -T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, const char* func, const char* assertion) +T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, std::source_location loc, std::string_view assertion) { if (!val) { if constexpr (G_ABORT_ON_FAILED_ASSUME) { - assertion_fail(file, line, func, assertion); + assertion_fail(loc, assertion); } - throw NonFatalCheckError{assertion, file, line, func}; + throw NonFatalCheckError{assertion, loc}; } return std::forward(val); } @@ -82,11 +83,11 @@ T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, co /** Helper for Assert()/Assume() */ template -constexpr T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] const char* file, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* assertion) +constexpr T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] std::source_location loc, [[maybe_unused]] std::string_view assertion) { if (IS_ASSERT || std::is_constant_evaluated() || G_ABORT_ON_FAILED_ASSUME) { if (!val) { - assertion_fail(file, line, func, assertion); + assertion_fail(loc, assertion); } } return std::forward(val); @@ -95,7 +96,7 @@ constexpr T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] con // All macros may use __func__ inside a lambda, so put them under nolint. // NOLINTBEGIN(bugprone-lambda-function-name) -#define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), __FILE__, __LINE__, __func__) +#define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), std::source_location::current()) /** * Identity function. Throw a NonFatalCheckError when the condition evaluates to false @@ -109,10 +110,10 @@ constexpr T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] con * caller, which can then report the issue to the developers. */ #define CHECK_NONFATAL(condition) \ - inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition) + inline_check_non_fatal(condition, std::source_location::current(), #condition) /** Identity function. Abort if the value compares equal to zero */ -#define Assert(val) inline_assertion_check(val, __FILE__, __LINE__, __func__, #val) +#define Assert(val) inline_assertion_check(val, std::source_location::current(), #val) /** * Assume is the identity function. @@ -124,14 +125,14 @@ constexpr T&& inline_assertion_check(LIFETIMEBOUND T&& val, [[maybe_unused]] con * - For non-fatal errors in interactive sessions (e.g. RPC or command line * interfaces), CHECK_NONFATAL() might be more appropriate. */ -#define Assume(val) inline_assertion_check(val, __FILE__, __LINE__, __func__, #val) +#define Assume(val) inline_assertion_check(val, std::source_location::current(), #val) /** * NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code. It throws a NonFatalCheckError. */ #define NONFATAL_UNREACHABLE() \ throw NonFatalCheckError( \ - "Unreachable code reached (non-fatal)", __FILE__, __LINE__, __func__) + "Unreachable code reached (non-fatal)", std::source_location::current()) // NOLINTEND(bugprone-lambda-function-name)