Skip to content

Commit dca80ff

Browse files
author
MarcoFalke
committed
Merge #20255: util: Add Assume() identity function
faa0585 util: Remove probably misleading TODO (MarcoFalke) fac5efe util: Add Assume() identity function (MarcoFalke) fa86156 util: Allow Assert(...) to be used in all contexts (practicalswift) Pull request description: This is needed for #20138. Please refer to the added documentation for motivation. ACKs for top commit: practicalswift: cr ACK faa0585 jnewbery: utACK faa0585 hebasto: ACK faa0585, I have reviewed the code and it looks OK, I agree it can be merged. Tree-SHA512: 72165fbd898b92ab9a79b070993fa1faa86c2e3545b6645e72c652bda295d5107bc298d0482bf3aaf0926fc0c3e6418a445c0e073b08568c44231f547f76a688
2 parents ca759bc + faa0585 commit dca80ff

File tree

3 files changed

+48
-2
lines changed

3 files changed

+48
-2
lines changed

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ if test "x$enable_debug" = xyes; then
348348

349349
AX_CHECK_PREPROC_FLAG([-DDEBUG],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG"]],,[[$CXXFLAG_WERROR]])
350350
AX_CHECK_PREPROC_FLAG([-DDEBUG_LOCKORDER],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DDEBUG_LOCKORDER"]],,[[$CXXFLAG_WERROR]])
351+
AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
351352
AX_CHECK_COMPILE_FLAG([-ftrapv],[DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -ftrapv"],,[[$CXXFLAG_WERROR]])
352353
fi
353354

@@ -1189,6 +1190,8 @@ if test "x$enable_fuzz" = "xyes"; then
11891190
use_upnp=no
11901191
use_zmq=no
11911192

1193+
AX_CHECK_PREPROC_FLAG([-DABORT_ON_FAILED_ASSUME],[[DEBUG_CPPFLAGS="$DEBUG_CPPFLAGS -DABORT_ON_FAILED_ASSUME"]],,[[$CXXFLAG_WERROR]])
1194+
11921195
AC_MSG_CHECKING([whether main function is needed])
11931196
AX_CHECK_LINK_FLAG(
11941197
[[-fsanitize=$use_sanitizers]],

doc/developer-notes.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,33 @@ configure option adds `-DDEBUG_LOCKORDER` to the compiler flags. This inserts
276276
run-time checks to keep track of which locks are held and adds warnings to the
277277
`debug.log` file if inconsistencies are detected.
278278

279+
### Assertions and Checks
280+
281+
The util file `src/util/check.h` offers helpers to protect against coding and
282+
internal logic bugs. They must never be used to validate user, network or any
283+
other input.
284+
285+
* `assert` or `Assert` should be used to document assumptions when any
286+
violation would mean that it is not safe to continue program execution. The
287+
code is always compiled with assertions enabled.
288+
- For example, a nullptr dereference or any other logic bug in validation
289+
code means the program code is faulty and must terminate immediately.
290+
* `CHECK_NONFATAL` should be used for recoverable internal logic bugs. On
291+
failure, it will throw an exception, which can be caught to recover from the
292+
error.
293+
- For example, a nullptr dereference or any other logic bug in RPC code
294+
means that the RPC code is faulty and can not be executed. However, the
295+
logic bug can be shown to the user and the program can continue to run.
296+
* `Assume` should be used to document assumptions when program execution can
297+
safely continue even if the assumption is violated. In debug builds it
298+
behaves like `Assert`/`assert` to notify developers and testers about
299+
nonfatal errors. In production it doesn't warn or log anything, though the
300+
expression is always evaluated.
301+
- For example it can be assumed that a variable is only initialized once,
302+
but a failed assumption does not result in a fatal bug. A failed
303+
assumption may or may not result in a slightly degraded user experience,
304+
but it is safe to continue program execution.
305+
279306
### Valgrind suppressions file
280307

281308
Valgrind is a programming tool for memory debugging, memory leak detection, and

src/util/check.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,30 @@ class NonFatalCheckError : public std::runtime_error
4646
#error "Cannot compile without assertions!"
4747
#endif
4848

49-
/** Helper for Assert(). TODO remove in C++14 and replace `decltype(get_pure_r_value(val))` with `T` (templated lambda) */
49+
/** Helper for Assert() */
5050
template <typename T>
5151
T get_pure_r_value(T&& val)
5252
{
5353
return std::forward<T>(val);
5454
}
5555

5656
/** Identity function. Abort if the value compares equal to zero */
57-
#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); }()
57+
#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); }())
58+
59+
/**
60+
* Assume is the identity function.
61+
*
62+
* - Should be used to run non-fatal checks. In debug builds it behaves like
63+
* Assert()/assert() to notify developers and testers about non-fatal errors.
64+
* In production it doesn't warn or log anything.
65+
* - For fatal errors, use Assert().
66+
* - For non-fatal errors in interactive sessions (e.g. RPC or command line
67+
* interfaces), CHECK_NONFATAL() might be more appropriate.
68+
*/
69+
#ifdef ABORT_ON_FAILED_ASSUME
70+
#define Assume(val) Assert(val)
71+
#else
72+
#define Assume(val) ((void)(val))
73+
#endif
5874

5975
#endif // BITCOIN_UTIL_CHECK_H

0 commit comments

Comments
 (0)