mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-28 02:32:14 +01:00
util/check: stop using lambda for Assert/Assume
This commit is contained in:
parent
7c9fe25c16
commit
2ef47ba6c5
@ -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 \
|
||||
|
@ -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)
|
||||
|
14
src/util/check.cpp
Normal file
14
src/util/check.cpp
Normal file
@ -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();
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user