Repository: bitcoin/bitcoin
File: src/util/check.h (C/C++)

Code before:
    true
#else
    false
#endif
};

std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func);

class NonFatalCheckError : public std::runtime_error
{
public:
    NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func);
};

/** Helper for CHECK_NONFATAL() */
template <typename T>
T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, const char* func, const char* assertion)
{
    if (!val) {
        throw NonFatalCheckError{assertion, file, line, func};
    }
    return std::forward<T>(val);
}

#if defined(NDEBUG)
#error "Cannot compile without assertions!"
#endif

/** Helper for Assert() */
void assertion_fail(std::string_view file, int line, std::string_view func, std::string_view assertion);

/** Helper for Assert()/Assume() */
template <bool IS_ASSERT, typename T>
constexpr 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)
{
    if (IS_ASSERT || std::is_constant_evaluated() || G_FUZZING
#ifdef ABORT_ON_FAILED_ASSUME
        || true
#endif
    ) {
        if (!val) {
            assertion_fail(file, line, func, assertion);
        }
    }
    return std::forward<T>(val);
}

// All macros may use __func__ inside a lambda, so put them under nolint.
// NOLINTBEGIN(bugprone-lambda-function-name)

#define STR_INTERNAL_BUG(msg) StrFormatInternalBug((msg), __FILE__, __LINE__, __func__)

Review comment (bug):
In commit "fuzz: enable running fuzz test cases in Debug mode" (1718da848a0a7591f0eab086e159f1e9e0f2c59b)

I don't think I the understand reason for ABORT_ON_FAILED_ASSUME affecting return value of EnableFuzzDeterminism(), and trying to force non-determinism when assume doesn't abort. It seems like this behavior might cause the `assert(EnableFuzzDeterminism())` to fail, but also this code might just be easier to understand if fuzz determinism only depended on the FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION build option and FUZZ_NONDETERMINISM environment variable and didn't have this third factor.

Is the reason maybe that this is trying to optimize code and avoid needing to access the `g_enable_dynamic_fuzz_determinism` variable in release builds? IMO would be good to either remove the !G_ABORT_ON_FAILED_ASSUME condition or document why it's here.

Code after:
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
    true
#else
    false
#endif
};
constexpr bool G_ABORT_ON_FAILED_ASSUME{
#ifdef ABORT_ON_FAILED_ASSUME
    true
#else
    false
#endif
};

extern std::atomic<bool> g_enable_dynamic_fuzz_determinism;

inline bool EnableFuzzDeterminism()
{
    if constexpr (G_FUZZING_BUILD) {
        return true;
    } else if constexpr (!G_ABORT_ON_FAILED_ASSUME) {
        // Running fuzz tests is always disabled if Assume() doesn't abort
        // (ie, non-fuzz non-debug builds), as otherwise tests which
        // should fail due to a failing Assume may still pass. As such,
        // we also statically disable fuzz determinism in that case.
        return false;
    } else {
        return g_enable_dynamic_fuzz_determinism;
    }
}

std::string StrFormatInternalBug(std::string_view msg, std::string_view file, int line, std::string_view func);

class NonFatalCheckError : public std::runtime_error
{
public:
    NonFatalCheckError(std::string_view msg, std::string_view file, int line, std::string_view func);
};

/** Helper for CHECK_NONFATAL() */
template <typename T>
T&& inline_check_non_fatal(LIFETIMEBOUND T&& val, const char* file, int line, const char* func, const char* assertion)
{
    if (!val) {
        throw NonFatalCheckError{assertion, file, line, func};
    }
    return std::forward<T>(val);
}

#if defined(NDEBUG)
#error "Cannot compile without assertions!"