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 : #include <attributes.h>
9 :
10 : #include <stdexcept>
11 : #include <utility>
12 :
13 : std::string StrFormatInternalBug(const char* msg, const char* file, int line, const char* func);
14 :
15 : class NonFatalCheckError : public std::runtime_error
16 : {
17 : public:
18 : NonFatalCheckError(const char* msg, const char* file, int line, const char* func);
19 : };
20 :
21 : #define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), __FILE__, __LINE__, __func__)
22 :
23 : /** Helper for CHECK_NONFATAL() */
24 : template <typename T>
25 338584 : T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, const char* func, const char* assertion)
26 : {
27 338584 : if (!val) {
28 0 : throw NonFatalCheckError{assertion, file, line, func};
29 : }
30 338584 : return std::forward<T>(val);
31 0 : }
32 :
33 : /**
34 : * Identity function. Throw a NonFatalCheckError when the condition evaluates to false
35 : *
36 : * This should only be used
37 : * - where the condition is assumed to be true, not for error handling or validating user input
38 : * - where a failure to fulfill the condition is recoverable and does not abort the program
39 : *
40 : * For example in RPC code, where it is undesirable to crash the whole program, this can be generally used to replace
41 : * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC
42 : * caller, which can then report the issue to the developers.
43 : */
44 : #define CHECK_NONFATAL(condition) \
45 : inline_check_non_fatal(condition, __FILE__, __LINE__, __func__, #condition)
46 :
47 : #if defined(NDEBUG)
48 : #error "Cannot compile without assertions!"
49 : #endif
50 :
51 : /** Helper for Assert() */
52 : void assertion_fail(const char* file, int line, const char* func, const char* assertion);
53 :
54 : /** Helper for Assert()/Assume() */
55 : template <bool IS_ASSERT, typename T>
56 5680840 : 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)
57 : {
58 : if constexpr (IS_ASSERT
59 : #ifdef ABORT_ON_FAILED_ASSUME
60 : || true
61 : #endif
62 : ) {
63 594018 : if (!val) {
64 0 : assertion_fail(file, line, func, assertion);
65 0 : }
66 : }
67 5680840 : return std::forward<T>(val);
68 : }
69 :
70 : /** Identity function. Abort if the value compares equal to zero */
71 : #define Assert(val) inline_assertion_check<true>(val, __FILE__, __LINE__, __func__, #val)
72 :
73 : /**
74 : * Assume is the identity function.
75 : *
76 : * - Should be used to run non-fatal checks. In debug builds it behaves like
77 : * Assert()/assert() to notify developers and testers about non-fatal errors.
78 : * In production it doesn't warn or log anything.
79 : * - For fatal errors, use Assert().
80 : * - For non-fatal errors in interactive sessions (e.g. RPC or command line
81 : * interfaces), CHECK_NONFATAL() might be more appropriate.
82 : */
83 : #define Assume(val) inline_assertion_check<false>(val, __FILE__, __LINE__, __func__, #val)
84 :
85 : /**
86 : * NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code. It throws a NonFatalCheckError.
87 : */
88 : #define NONFATAL_UNREACHABLE() \
89 : throw NonFatalCheckError( \
90 : "Unreachable code reached (non-fatal)", __FILE__, __LINE__, __func__)
91 :
92 : #endif // BITCOIN_UTIL_CHECK_H
|