One common pattern of using assert function looks as follows: int ret = do_foo(); assert(ret == 0); // which reads as: “do_foo should never fail here, by design” The problem with such code is that if ‘assert’ is removed by the preprocessor in release build, variable ret is no longer used, and the compiler issues a warning about this. Changing assert definition in the way done here make the variable used, from language syntax perspective. Semantically, the variable is still unused at run time (as sizeof can be evaluated at compile time), so the compiler can optimize things away if possible.
50 lines
1.2 KiB
C
50 lines
1.2 KiB
C
/*
|
|
assert.h
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "_ansi.h"
|
|
|
|
#undef assert
|
|
|
|
#ifdef NDEBUG /* required by ANSI standard */
|
|
# define assert(__e) ((void) sizeof(__e))
|
|
#else
|
|
# define assert(__e) ((__e) ? (void)0 : __assert_func (__FILE__, __LINE__, \
|
|
__ASSERT_FUNC, #__e))
|
|
|
|
# ifndef __ASSERT_FUNC
|
|
/* Use g++'s demangled names in C++. */
|
|
# if defined __cplusplus && defined __GNUC__
|
|
# define __ASSERT_FUNC __PRETTY_FUNCTION__
|
|
|
|
/* C99 requires the use of __func__. */
|
|
# elif __STDC_VERSION__ >= 199901L
|
|
# define __ASSERT_FUNC __func__
|
|
|
|
/* Older versions of gcc don't have __func__ but can use __FUNCTION__. */
|
|
# elif __GNUC__ >= 2
|
|
# define __ASSERT_FUNC __FUNCTION__
|
|
|
|
/* failed to detect __func__ support. */
|
|
# else
|
|
# define __ASSERT_FUNC ((char *) 0)
|
|
# endif
|
|
# endif /* !__ASSERT_FUNC */
|
|
#endif /* !NDEBUG */
|
|
|
|
void _EXFUN(__assert, (const char *, int, const char *)
|
|
_ATTRIBUTE ((__noreturn__)));
|
|
void _EXFUN(__assert_func, (const char *, int, const char *, const char *)
|
|
_ATTRIBUTE ((__noreturn__)));
|
|
|
|
#if __STDC_VERSION__ >= 201112L && !defined __cplusplus
|
|
# define static_assert _Static_assert
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|