Changeset View
Changeset View
Standalone View
Standalone View
src/util/check.h
Show All 20 Lines | |||||
* Throw a NonFatalCheckError when the condition evaluates to false | * Throw a NonFatalCheckError when the condition evaluates to false | ||||
* | * | ||||
* This should only be used | * This should only be used | ||||
* - where the condition is assumed to be true, not for error handling or | * - where the condition is assumed to be true, not for error handling or | ||||
* validating user input | * validating user input | ||||
* - where a failure to fulfill the condition is recoverable and does not abort | * - where a failure to fulfill the condition is recoverable and does not abort | ||||
* the program | * the program | ||||
* | * | ||||
* For example in RPC code, where it is undersirable to crash the whole program, | * For example in RPC code, where it is undesirable to crash the whole program, | ||||
* this can be generally used to replace asserts or recoverable logic errors. A | * this can be generally used to replace asserts or recoverable logic errors. A | ||||
* NonFatalCheckError in RPC code is caught and passed as a string to the RPC | * NonFatalCheckError in RPC code is caught and passed as a string to the RPC | ||||
* caller, which can then report the issue to the developers. | * caller, which can then report the issue to the developers. | ||||
*/ | */ | ||||
#define CHECK_NONFATAL(condition) \ | #define CHECK_NONFATAL(condition) \ | ||||
do { \ | do { \ | ||||
if (!(condition)) { \ | if (!(condition)) { \ | ||||
throw NonFatalCheckError( \ | throw NonFatalCheckError( \ | ||||
strprintf("%s:%d (%s)\n" \ | strprintf("%s:%d (%s)\n" \ | ||||
"Internal bug detected: '%s'\n" \ | "Internal bug detected: '%s'\n" \ | ||||
"You may report this issue here: %s\n", \ | "You may report this issue here: %s\n", \ | ||||
__FILE__, __LINE__, __func__, (#condition), \ | __FILE__, __LINE__, __func__, (#condition), \ | ||||
PACKAGE_BUGREPORT)); \ | PACKAGE_BUGREPORT)); \ | ||||
} \ | } \ | ||||
} while (false) | } while (false) | ||||
#if defined(NDEBUG) | |||||
#error "Cannot compile without assertions!" | |||||
#endif | |||||
/** Helper for Assert(). TODO remove in C++14 and replace | |||||
* `decltype(get_pure_r_value(val))` with `T` (templated lambda) */ | |||||
template <typename T> T get_pure_r_value(T &&val) { | |||||
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 check; \ | |||||
}() | |||||
#endif // BITCOIN_UTIL_CHECK_H | #endif // BITCOIN_UTIL_CHECK_H |