Project

General

Profile

Download (4.25 KB) Statistics
| Branch: | Tag: | Revision:
#ifndef __COMMON_ASSERT_H__
#define __COMMON_ASSERT_H__

#include <stddef.h> // for size_t
#include <stdint.h> // for uint64_t
#include "simplest-defs.h" // for STRINGIFY

// Use CHECK for checking something that you really want checked.
//
// Use ASSERT for checking something that you want checked, but the
// functionality of the program won't be compromised if the predicate isn't
// checked, or even run. It should be correct to define ASSERT as "#define
// ASSERT(x) ((void)0)". This means that you should not put side effects into
// ASSERT predicates.
//
// Use ASSERT_WITH_SIDE_EFFECTS for checking something you want checked, but
// there may be side effects in the predicate, so we need need to evaluate the
// predicate even if NOASSERT is set.
//
// See wisdom.tex for more discussion.

#ifndef CHECK_ASSERT_SIDE_EFFECTS
#define CHECK_ASSERT_SIDE_EFFECTS 0
#endif

#ifdef NOASSERT
#define ASSERT(x) ((0) ? ((void)(x), (void)(0)) : (void)(0))
#define ASSERT0 ASSERT
#define ASSERTv(x, typeof_val, val) ((0) ? ((void)(x), (void)(val), (void)(0)) : (void)(0))
#define ASSERT_EQ_u(a, b) ((0) ? ((void)(a), (void)(b), (void)(0)) \
: (void)(0))
#define ASSERT_EQ_i(a, b) ((0) ? ((void)(a), (void)(b), (void)(0)) \
: (void)(0))
#define ASSERT_WITH_SIDE_EFFECTS(expr) ((void)expr)
#elif !CHECK_ASSERT_SIDE_EFFECTS // && !NOASSERT
#define ASSERT CHECK
#define ASSERT0 CHECK0
#define ASSERTv CHECKv
#define ASSERT_EQ_u CHECK_EQ_u
#define ASSERT_EQ_i CHECK_EQ_i
#define ASSERT_WITH_SIDE_EFFECTS ASSERT
#else // CHECK_ASSERT_SIDE_EFFECTS && !NOASSERT
// See https://stackoverflow.com/questions/10593492/catching-assert-with-side-effects
// for this trick for noticing that you have an ASSERT with side effects.
extern int not_needed_if_expr_has_no_side_effects;
#define ASSERT(expr) ((void)(not_needed_if_expr_has_no_side_effects || (expr)))
#define ASSERT0(expr) ASSERT((expr) == 0)
#define ASSERTv(x, typeof_val, val) ASSERT(x)
#define ASSERT_EQ_u(a, b) ASSERT((a) == (b))
#define ASSERT_EQ_i(a, b) ASSERT((a) == (b))
#define ASSERT_WITH_SIDE_EFFECTS(expr) ((void)(expr))
#endif // CHECK_ASSERT_SIDE_EFFECTS && !NOASSERT

#define CHECK(x) ((x) ? (void) (0) : assert_fail (STRINGIFY(x), __FILE__, __LINE__, __PRETTY_FUNCTION__))
#define CHECK0(x) CHECK((x) == 0)
/* Check and print variable of specified type. */
#define CHECKv(x, typeof_val, val) ((x) ? (void) (0) : assert_fail_ ## typeof_val \
(STRINGIFY(x), #val, val, __FILE__, __LINE__, __PRETTY_FUNCTION__))
#define CHECKvv(x, fmt_args...) ((x) ? (void)(0) : assert_fail_v(STRINGIFY(x), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt_args) )
#define UNREACHABLE() CHECK("UNREACHABLE" && 0)

void assert_fail(const char *assertion,
const char *file, size_t line, const char *function)
__attribute__ ((__noreturn__));
void assert_fail_int(const char *assertion, const char *str_var, int var,
const char *file, size_t line, const char *function)
__attribute__ ((__noreturn__));
void assert_fail_v(const char *assertion,
const char *file,
size_t line,
const char *function,
const char *fmt_string,
...)
__attribute__ ((__noreturn__))
__attribute__ ((format (printf, 5, 6)));
void
check_eq_u(uintmax_t a, uintmax_t b,
const char *file, size_t line, const char *function,
const char *assertion);

#define CHECK_EQ_u(a, b) ( \
check_eq_u((uintmax_t)(a), (uintmax_t)(b), \
__FILE__, __LINE__, __PRETTY_FUNCTION__, \
STRINGIFY(a) " == " STRINGIFY(b)))


void
check_eq_i(intmax_t a, intmax_t b,
const char *file, size_t line, const char *function,
const char *assertion);

#define CHECK_EQ_i(a, b) ( \
check_eq_i((intmax_t)(a), (intmax_t)(b), \
__FILE__, __LINE__, __PRETTY_FUNCTION__, \
STRINGIFY(a) " == " STRINGIFY(b)))


#endif
(2-2/14)