util/assert: add optional message to assert, assume, and static_assert
Removed static_assert_nomsg, since static_assert's message argument is optional now. In C2X mode this uses the native _Static_assert functionality, otherwise it falls back to a macro-based overload. Additionally, rewrote the assert macro so it correctly marks the failing branch as a dead end.
This commit is contained in:
parent
7c19322940
commit
711edc218f
8 changed files with 83 additions and 31 deletions
10
meson.build
10
meson.build
|
@ -334,6 +334,16 @@ config.set('TAISEI_BUILDCONF_HAVE_ATTR_MALLOC_WITH_ARGS', cc.compiles(
|
|||
args : ['-Wattributes', '-Werror']
|
||||
))
|
||||
|
||||
config.set('TAISEI_BUILDCONF_HAVE_STATIC_ASSERT_WITHOUT_MSG', cc.compiles(
|
||||
'''
|
||||
#include <assert.h>
|
||||
static_assert(1, "with message");
|
||||
static_assert(1);
|
||||
''',
|
||||
name : 'static_assert() without message',
|
||||
args : ['-Werror']
|
||||
))
|
||||
|
||||
prefer_relpath_systems = [
|
||||
'windows',
|
||||
]
|
||||
|
|
|
@ -68,7 +68,7 @@ typedef enum {
|
|||
NUM_EPRIOS = EPRIO_LAST - EPRIO_FIRST + 1,
|
||||
} EventPriority;
|
||||
|
||||
static_assert_nomsg(EPRIO_DEFAULT == 0);
|
||||
static_assert(EPRIO_DEFAULT == 0);
|
||||
|
||||
typedef enum {
|
||||
EFLAG_MENU = (1 << 0),
|
||||
|
|
|
@ -150,11 +150,11 @@ typedef enum PixmapFormat {
|
|||
} PixmapFormat;
|
||||
|
||||
// sanity check
|
||||
static_assert_nomsg(_impl_pixmap_format_layout(PIXMAP_FORMAT_ETC2_EAC_RG11) == PIXMAP_LAYOUT_RG);
|
||||
static_assert_nomsg(_impl_pixmap_format_compression(PIXMAP_FORMAT_ASTC_4x4_RGBA) == PIXMAP_COMPRESSION_ASTC_4x4_RGBA);
|
||||
static_assert_nomsg(_impl_pixmap_format_depth(PIXMAP_FORMAT_RGB16F) == 16);
|
||||
static_assert_nomsg(_impl_pixmap_format_depth(PIXMAP_FORMAT_RGB8) == 8);
|
||||
static_assert_nomsg(_impl_pixmap_format_layout(PIXMAP_FORMAT_RGB8) == PIXMAP_LAYOUT_RGB);
|
||||
static_assert(_impl_pixmap_format_layout(PIXMAP_FORMAT_ETC2_EAC_RG11) == PIXMAP_LAYOUT_RG);
|
||||
static_assert(_impl_pixmap_format_compression(PIXMAP_FORMAT_ASTC_4x4_RGBA) == PIXMAP_COMPRESSION_ASTC_4x4_RGBA);
|
||||
static_assert(_impl_pixmap_format_depth(PIXMAP_FORMAT_RGB16F) == 16);
|
||||
static_assert(_impl_pixmap_format_depth(PIXMAP_FORMAT_RGB8) == 8);
|
||||
static_assert(_impl_pixmap_format_layout(PIXMAP_FORMAT_RGB8) == PIXMAP_LAYOUT_RGB);
|
||||
|
||||
INLINE bool pixmap_format_is_compressed(PixmapFormat fmt) {
|
||||
return _impl_pixmap_format_is_compressed(fmt);
|
||||
|
|
|
@ -167,7 +167,7 @@ static MagicUniformSpec magic_unfiroms[] = {
|
|||
[UMAGIC_COLOR_OUT_SIZES] = { "r_colorOutputSizes[0]", "vec2", UNIFORM_VEC2 },
|
||||
[UMAGIC_DEPTH_OUT_SIZE] = { "r_depthOutputSize", "vec2", UNIFORM_VEC2 },
|
||||
};
|
||||
static_assert_nomsg(ARRAY_SIZE(magic_unfiroms) == NUM_MAGIC_UNIFORMS);
|
||||
static_assert(ARRAY_SIZE(magic_unfiroms) == NUM_MAGIC_UNIFORMS);
|
||||
|
||||
static void gl33_update_uniform(Uniform *uniform, uint offset, uint count, const void *data) {
|
||||
// these are validated properly in gl33_uniform
|
||||
|
|
|
@ -186,7 +186,7 @@ static GLenum target_from_class_and_layer(TextureClass cls, uint layer) {
|
|||
[CUBEMAP_FACE_POS_Z] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
[CUBEMAP_FACE_NEG_Z] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
};
|
||||
static_assert_nomsg(ARRAY_SIZE(facemap) == 6);
|
||||
static_assert(ARRAY_SIZE(facemap) == 6);
|
||||
assert(layer < ARRAY_SIZE(facemap));
|
||||
return facemap[layer];
|
||||
} else if(target == GL_TEXTURE_2D) {
|
||||
|
|
|
@ -479,7 +479,7 @@ static bool load_pixmap(
|
|||
static void texture_loader_cubemap_from_pixmaps(TextureLoadData *ld) {
|
||||
ResourceLoadState *st = ld->st;
|
||||
|
||||
static_assert_nomsg(sizeof(*ld->cubemaps)/sizeof(*ld->pixmaps) == ARRAY_SIZE(ld->src_paths.cubemap));
|
||||
static_assert(sizeof(*ld->cubemaps)/sizeof(*ld->pixmaps) == ARRAY_SIZE(ld->src_paths.cubemap));
|
||||
const int nsides = sizeof(*ld->cubemaps)/sizeof(*ld->pixmaps);
|
||||
ld->num_pixmaps = nsides;
|
||||
ld->cubemaps = ALLOC_ARRAY(1, typeof(*ld->cubemaps));
|
||||
|
|
|
@ -12,14 +12,31 @@
|
|||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
void _ts_assert_fail(const char *cond, const char *func, const char *file, int line, bool use_log) {
|
||||
void _ts_assert_fail(
|
||||
const char *cond, const char *msg, const char *func, const char *file, int line, bool use_log
|
||||
) {
|
||||
use_log = use_log && log_initialized();
|
||||
|
||||
if(use_log) {
|
||||
_taisei_log(LOG_FAKEFATAL, func, file, line, "%s:%i: assertion `%s` failed", file, line, cond);
|
||||
if(msg) {
|
||||
_taisei_log(LOG_FAKEFATAL, func, file, line,
|
||||
"%s:%i: assertion `%s` failed: %s", file, line, cond, msg);
|
||||
} else {
|
||||
_taisei_log(LOG_FAKEFATAL, func, file, line,
|
||||
"%s:%i: assertion `%s` failed", file, line, cond);
|
||||
}
|
||||
|
||||
log_sync(true);
|
||||
} else {
|
||||
tsfprintf(stderr, "%s:%i: %s(): assertion `%s` failed\n", file, line, func, cond);
|
||||
if(msg) {
|
||||
tsfprintf(stderr,
|
||||
"%s:%i: %s(): assertion `%s` failed: %s\n", file, line, func, cond, msg);
|
||||
} else {
|
||||
tsfprintf(stderr,
|
||||
"%s:%i: %s(): assertion `%s` failed\n", file, line, func, cond);
|
||||
}
|
||||
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,21 +9,26 @@
|
|||
#pragma once
|
||||
#include "taisei.h"
|
||||
|
||||
#if __has_attribute(analyzer_noreturn)
|
||||
#define attr_analyzer_noreturn \
|
||||
__attribute__ ((analyzer_noreturn))
|
||||
#else
|
||||
#define attr_analyzer_noreturn
|
||||
#include "util/macrohax.h"
|
||||
|
||||
#ifndef TAISEI_BUILDCONF_HAVE_STATIC_ASSERT_WITHOUT_MSG
|
||||
#undef static_assert
|
||||
#define _static_assert_0(cond) _Static_assert(cond, #cond)
|
||||
#define _static_assert_1(cond, msg) _Static_assert(cond, msg)
|
||||
#define static_assert(cond, ...) \
|
||||
MACROHAX_OVERLOAD_NARGS(_static_assert_, __VA_ARGS__)(cond, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
attr_analyzer_noreturn
|
||||
void _ts_assert_fail(const char *cond, const char *func, const char *file, int line, bool use_log);
|
||||
void _ts_assert_fail(
|
||||
const char *cond,
|
||||
const char *msg,
|
||||
const char *func,
|
||||
const char *file,
|
||||
int line,
|
||||
bool use_log
|
||||
);
|
||||
|
||||
#undef assert
|
||||
#undef static_assert
|
||||
|
||||
#define static_assert _Static_assert
|
||||
#define static_assert_nomsg(x) static_assert(x, #x)
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
void _emscripten_trap(void);
|
||||
|
@ -42,15 +47,35 @@ void _ts_assert_fail(const char *cond, const char *func, const char *file, int l
|
|||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define _assert(cond, uselog)
|
||||
#define _assume(cond, uselog) ASSUME(cond)
|
||||
#define _assert(cond, msg, uselog)
|
||||
#define _assume(cond, msg, uselog) ASSUME(cond)
|
||||
#else
|
||||
#define _assert(cond, uselog) (LIKELY(cond) ? (void)0 : (_ts_assert_fail(#cond, __func__, _TAISEI_SRC_FILE, __LINE__, uselog), TRAP()))
|
||||
#define _assume(cond, uselog) _assert(cond, uselog)
|
||||
#define _assert(cond, msg, uselog) ({ \
|
||||
if(UNLIKELY(!(cond))) { \
|
||||
_ts_assert_fail(#cond, msg, __func__, _TAISEI_SRC_FILE, __LINE__, uselog); \
|
||||
TRAP(); \
|
||||
__builtin_unreachable(); \
|
||||
} \
|
||||
})
|
||||
#define _assume(cond, msg, uselog) _assert(cond, msg, uselog)
|
||||
#endif
|
||||
|
||||
#define assert(cond) _assert(cond, true)
|
||||
#define assert_nolog(cond) _assert(cond, false)
|
||||
#define _assert_0(cond) _assert(cond, NULL, true)
|
||||
#define _assert_1(cond, msg) _assert(cond, msg, true)
|
||||
#define assert(cond, ...) \
|
||||
MACROHAX_OVERLOAD_NARGS(_assert_, __VA_ARGS__)(cond, ##__VA_ARGS__)
|
||||
|
||||
#define assume(cond) _assume(cond, true)
|
||||
#define assume_nolog(cond) _assume(cond, false)
|
||||
#define _assert_nolog_0(cond) _assert(cond, NULL, false)
|
||||
#define _assert_nolog_1(cond, msg) _assert(cond, msg, false)
|
||||
#define assert_nolog(cond, ...) \
|
||||
MACROHAX_OVERLOAD_NARGS(_assert_nolog_, __VA_ARGS__)(cond, ##__VA_ARGS__)
|
||||
|
||||
#define _assume_0(cond) _assume(cond, NULL, true)
|
||||
#define _assume_1(cond, msg) _assume(cond, msg, true)
|
||||
#define assume(cond, ...) \
|
||||
MACROHAX_OVERLOAD_NARGS(_assume_, __VA_ARGS__)(cond, ##__VA_ARGS__)
|
||||
|
||||
#define _assume_nolog_0(cond) _assume(cond, NULL, false)
|
||||
#define _assume_nolog_1(cond, msg) _assume(cond, msg, false)
|
||||
#define assume_nolog(cond, ...) \
|
||||
MACROHAX_OVERLOAD_NARGS(_assume_nolog_, __VA_ARGS__)(cond, ##__VA_ARGS__)
|
||||
|
|
Loading…
Reference in a new issue