Branch data Line data Source code
# 1 : : // Copyright (c) 2019-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #ifndef BITCOIN_UTIL_CHECK_H
# 6 : : #define BITCOIN_UTIL_CHECK_H
# 7 : :
# 8 : : #if defined(HAVE_CONFIG_H)
# 9 : : #include <config/bitcoin-config.h>
# 10 : : #endif
# 11 : :
# 12 : : #include <tinyformat.h>
# 13 : :
# 14 : : #include <stdexcept>
# 15 : :
# 16 : : class NonFatalCheckError : public std::runtime_error
# 17 : : {
# 18 : : using std::runtime_error::runtime_error;
# 19 : : };
# 20 : :
# 21 : : /**
# 22 : : * Throw a NonFatalCheckError when the condition evaluates to false
# 23 : : *
# 24 : : * This should only be used
# 25 : : * - where the condition is assumed to be true, not for error handling or validating user input
# 26 : : * - where a failure to fulfill the condition is recoverable and does not abort the program
# 27 : : *
# 28 : : * For example in RPC code, where it is undesirable to crash the whole program, this can be generally used to replace
# 29 : : * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
# 30 : : * caller, which can then report the issue to the developers.
# 31 : : */
# 32 : : #define CHECK_NONFATAL(condition) \
# 33 : 5495288 : do { \
# 34 : 5495288 : if (!(condition)) { \
# 35 : 1 : throw NonFatalCheckError( \
# 36 : 1 : strprintf("Internal bug detected: '%s'\n" \
# 37 : 1 : "%s:%d (%s)\n" \
# 38 : 1 : "You may report this issue here: %s\n", \
# 39 : 1 : (#condition), \
# 40 : 1 : __FILE__, __LINE__, __func__, \
# 41 : 1 : PACKAGE_BUGREPORT)); \
# 42 : 1 : } \
# 43 : 5495288 : } while (false)
# 44 : :
# 45 : : #if defined(NDEBUG)
# 46 : : #error "Cannot compile without assertions!"
# 47 : : #endif
# 48 : :
# 49 : : /** Helper for Assert() */
# 50 : : void assertion_fail(const char* file, int line, const char* func, const char* assertion);
# 51 : :
# 52 : : /** Helper for Assert()/Assume() */
# 53 : : template <bool IS_ASSERT, typename T>
# 54 : : T&& inline_assertion_check(T&& val, [[maybe_unused]] const char* file, [[maybe_unused]] int line, [[maybe_unused]] const char* func, [[maybe_unused]] const char* assertion)
# 55 : 1120993 : {
# 56 : 1120993 : if constexpr (IS_ASSERT
# 57 : 1120993 : #ifdef ABORT_ON_FAILED_ASSUME
# 58 : 1120993 : || true
# 59 : 1120993 : #endif
# 60 : 1120993 : ) {
# 61 [ - + ][ - + ]: 1120993 : if (!val) {
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ][ - + ]
# [ - + ]
# 62 : 0 : assertion_fail(file, line, func, assertion);
# 63 : 0 : }
# 64 : 1120993 : }
# 65 : 1120993 : return std::forward<T>(val);
# 66 : 1120993 : }
# 67 : :
# 68 : : /** Identity function. Abort if the value compares equal to zero */
# 69 : 1261383 : #define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
# 70 : :
# 71 : : /**
# 72 : : * Assume is the identity function.
# 73 : : *
# 74 : : * - Should be used to run non-fatal checks. In debug builds it behaves like
# 75 : : * Assert()/assert() to notify developers and testers about non-fatal errors.
# 76 : : * In production it doesn't warn or log anything.
# 77 : : * - For fatal errors, use Assert().
# 78 : : * - For non-fatal errors in interactive sessions (e.g. RPC or command line
# 79 : : * interfaces), CHECK_NONFATAL() might be more appropriate.
# 80 : : */
# 81 : 131597 : #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
# 82 : :
# 83 : : #endif // BITCOIN_UTIL_CHECK_H
|