#ifndef COSMOPOLITAN_LIBC_ASSERT_H_
#define COSMOPOLITAN_LIBC_ASSERT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_

extern bool __assert_disable;
void __assert_fail(const char *, const char *, int) hidden relegated;

#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__), 0)))
#endif

#ifndef __cplusplus
#define static_assert _Static_assert
#endif

#ifdef __GNUC__
#if !defined(TINY) && !defined(MODE_DBG)
/**
 * Specifies expression can't possibly be false.
 *
 * This macro uses the `notpossible` keyword and is intended for things
 * like systems integration, where we know for a fact that something is
 * never going to happen, but there's no proof. So we don't want to add
 * extra bloat for filenames and line numbers, since `ShowCrashReports`
 * can print a backtrace if we just embed the UD2 instruction to crash.
 * That's useful for systems code, for the following reason. Invariants
 * make sense with _unassert() since they usually get placed at the top
 * of functions. But if you used _unassert() to test a system call does
 * not fail, then check happens at the end of your function usually and
 * is therefore likely to result in a failure condition where execution
 * falls through into a different function, which is shocking to debug.
 *
 * In `MODE=tiny` these assertions are redefined as undefined behavior.
 */
#define _npassert(x)                 \
  __extension__({                    \
    if (__builtin_expect(!(x), 0)) { \
      notpossible;                   \
    }                                \
    (void)0;                         \
  })
#else
#define _npassert(x) _unassert(x)
#endif
#endif

#ifdef __GNUC__
/**
 * Specifies expression being false is undefined behavior.
 *
 * This is a good way to tell the compiler about your invariants, which
 * leads to smaller faster programs. The expression is never removed by
 * the preprocessor so it's recommended that it be free of side-effects
 * if you intend for it to be removed. At the same time, this guarantee
 * makes this assertion useful for things like system calls, since they
 * won't be removed by `NDEBUG` mode.
 *
 * If this assertion fails, the worst possible things can happen unless
 * you've built your binary in `MODE=dbg` since UBSAN is the only thing
 * that's capable of debugging this macro.
 */
#define _unassert(x)                 \
  __extension__({                    \
    if (__builtin_expect(!(x), 0)) { \
      unreachable;                   \
    }                                \
    (void)0;                         \
  })
#endif

COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ASSERT_H_ */
