diff options
author | Anthony Towns <aj@erisian.com.au> | 2022-03-26 12:41:28 +1000 |
---|---|---|
committer | Anthony Towns <aj@erisian.com.au> | 2022-03-30 23:09:13 +1000 |
commit | 2ef47ba6c57a12840499a13908ab61aefca6cb55 (patch) | |
tree | 8fa4af2c41a838756e8dffa5d3587c0ef414faf5 | |
parent | 7c9fe25c16d48b53a61fa2f6ff77eaf8820cb1f6 (diff) |
util/check: stop using lambda for Assert/Assume
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/test/util_tests.cpp | 33 | ||||
-rw-r--r-- | src/util/check.cpp | 14 | ||||
-rw-r--r-- | src/util/check.h | 24 |
4 files changed, 65 insertions, 8 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index af6bcaf4d7..a9eac7a51c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -621,6 +621,7 @@ libbitcoin_util_a_SOURCES = \ util/asmap.cpp \ util/bip32.cpp \ util/bytevectorhash.cpp \ + util/check.cpp \ util/error.cpp \ util/fees.cpp \ util/getuniquepath.cpp \ @@ -839,6 +840,7 @@ bitcoin_chainstate_SOURCES = \ uint256.cpp \ util/asmap.cpp \ util/bytevectorhash.cpp \ + util/check.cpp \ util/getuniquepath.cpp \ util/hasher.cpp \ util/moneystr.cpp \ diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 1881573e7a..b5d8411e1d 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -78,6 +78,31 @@ BOOST_AUTO_TEST_CASE(util_datadir) BOOST_CHECK_EQUAL(dd_norm, args.GetDataDirBase()); } +namespace { +class NoCopyOrMove +{ +public: + int i; + explicit NoCopyOrMove(int i) : i{i} { } + + NoCopyOrMove() = delete; + NoCopyOrMove(const NoCopyOrMove&) = delete; + NoCopyOrMove(NoCopyOrMove&&) = delete; + NoCopyOrMove& operator=(const NoCopyOrMove&) = delete; + NoCopyOrMove& operator=(NoCopyOrMove&&) = delete; + + operator bool() const { return i != 0; } + + int get_ip1() { return i + 1; } + bool test() + { + // Check that Assume can be used within a lambda and still call methods + [&]() { Assume(get_ip1()); }(); + return Assume(get_ip1() != 5); + } +}; +} // namespace + BOOST_AUTO_TEST_CASE(util_check) { // Check that Assert can forward @@ -89,6 +114,14 @@ BOOST_AUTO_TEST_CASE(util_check) // Check that Assume can be used as unary expression const bool result{Assume(two == 2)}; Assert(result); + + // Check that Assert doesn't require copy/move + NoCopyOrMove x{9}; + Assert(x).i += 3; + Assert(x).test(); + + // Check nested Asserts + BOOST_CHECK_EQUAL(Assert((Assert(x).test() ? 3 : 0)), 3); } BOOST_AUTO_TEST_CASE(util_criticalsection) diff --git a/src/util/check.cpp b/src/util/check.cpp new file mode 100644 index 0000000000..2a9f885560 --- /dev/null +++ b/src/util/check.cpp @@ -0,0 +1,14 @@ +// Copyright (c) 2022 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <util/check.h> + +#include <tinyformat.h> + +void assertion_fail(const char* file, int line, const char* func, const char* assertion) +{ + auto str = strprintf("%s:%s %s: Assertion `%s' failed.\n", file, line, func, assertion); + fwrite(str.data(), 1, str.size(), stderr); + std::abort(); +} diff --git a/src/util/check.h b/src/util/check.h index a443c13cf2..80e973e7e2 100644 --- a/src/util/check.h +++ b/src/util/check.h @@ -47,14 +47,26 @@ class NonFatalCheckError : public std::runtime_error #endif /** Helper for Assert() */ -template <typename T> -T get_pure_r_value(T&& val) +void assertion_fail(const char* file, int line, const char* func, const char* assertion); + +/** Helper for Assert()/Assume() */ +template <bool IS_ASSERT, typename T> +T&& inline_assertion_check(T&& val, const char* file, int line, const char* func, const char* assertion) { + if constexpr (IS_ASSERT +#ifdef ABORT_ON_FAILED_ASSUME + || true +#endif + ) { + if (!val) { + assertion_fail(file, line, func, assertion); + } + } return std::forward<T>(val); } /** Identity function. Abort if the value compares equal to zero */ -#define Assert(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); assert(#val && check); return std::forward<decltype(get_pure_r_value(val))>(check); }()) +#define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val) /** * Assume is the identity function. @@ -66,10 +78,6 @@ T get_pure_r_value(T&& val) * - For non-fatal errors in interactive sessions (e.g. RPC or command line * interfaces), CHECK_NONFATAL() might be more appropriate. */ -#ifdef ABORT_ON_FAILED_ASSUME -#define Assume(val) Assert(val) -#else -#define Assume(val) ([&]() -> decltype(get_pure_r_value(val)) { auto&& check = (val); return std::forward<decltype(get_pure_r_value(val))>(check); }()) -#endif +#define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val) #endif // BITCOIN_UTIL_CHECK_H |