summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/al/lib.h32
-rw-r--r--meson.build27
2 files changed, 42 insertions, 17 deletions
diff --git a/include/al/lib.h b/include/al/lib.h
index 5e65149..f5379e5 100644
--- a/include/al/lib.h
+++ b/include/al/lib.h
@@ -15,7 +15,10 @@
// https://forum.vcfed.org/index.php?threads/c-item-size-check-at-compile-time.1244920/
#define AL_ASSERT_TYPE_SIZE(type, size) \
- typedef char type##__size_test[(!!(sizeof(type) == size)) * 2 - 1]
+ typedef char type##__size_assert[(!!(sizeof(type) == size)) * 2 - 1]
+
+#define AL_STATIC_ASSERT(what, a, cmp, b) \
+ typedef char what##__assert[(!!(a cmp b)) * 2 - 1]
#define AL_USE_STDLIB
//#define AL_PARANOID_REALLOC
@@ -43,13 +46,6 @@
#include <wchar.h>
#include <stdio.h>
#include <stdarg.h>
-#if !defined AL_DEBUG && defined AL_RELEASE_ASSERTS
-#undef NDEBUG
-#include <assert.h>
-#define NDEBUG
-#else
-#include <assert.h>
-#endif
#include <ctype.h>
#ifdef AL_MEMORY_TRACKING
@@ -100,12 +96,23 @@ static inline void *al_realloc(void *ptr, size_t n) { return ptr ? realloc(ptr,
#define al_snprintf snprintf
#define al_vsnprintf vsnprintf
#define al_fflush fflush
-#if defined AL_DEBUG || defined AL_RELEASE_ASSERTS
-#define al_assert assert
+
+#if (defined AL_DEBUG || defined AL_RELEASE_ASSERTS) && defined AL_ASSERT_FUNCTION
+#include <assert.h>
+// Directly define al_assert() as <assert.h> would if NDEBUG was not set.
+#if defined AL_ASSERT_INCLUDE_FUNC
+#define al_assert(expr) ((expr) ? (void)0 : AL_ASSERT_FUNCTION(#expr, __FILE__, __LINE__, __func__))
+#elif defined AL_ASSERT_EXPR_LAST
+#define al_assert(expr) ((expr) ? (void)0 : AL_ASSERT_FUNCTION(__FILE__, __LINE__, #expr))
#else
-#define al_assert(expr) do { (void)sizeof(expr); } while (0) // NOLINT(bugprone-sizeof-expression)
+#define al_assert(expr) ((expr) ? (void)0 : AL_ASSERT_FUNCTION(#expr, __FILE__, __LINE__))
#endif
-
+// Loosely assert that <assert.h> behaves as we expect and redefines itself on every include.
+#undef assert
+#else
+#define al_assert(expr) ((void)sizeof(expr)) // NOLINT(bugprone-sizeof-expression)
+#endif
+// Use __VA_ARGS__ to allow for an empty return.
#define al_assert_and_return(...) do { \
al_assert(false); \
return __VA_ARGS__; \
@@ -181,7 +188,6 @@ static inline char *al_memdup0(const char *s, size_t n)
buf[n] = '\0';
return buf;
}
-
#endif
static inline u32 al_next_power_of_two(u32 n)
diff --git a/meson.build b/meson.build
index 285af45..c948887 100644
--- a/meson.build
+++ b/meson.build
@@ -24,16 +24,35 @@ have_wide_string_width = compiler.has_function('wcswidth')
# For testing: '-Wshadow', '-Wconversion', '-Wc++-compat'
alabaster_args = ['-fstrict-aliasing', '-Wstrict-aliasing']
-if get_option('release-asserts')
- alabaster_args += ['-DAL_RELEASE_ASSERTS']
-endif
-
if is_debug
alabaster_args += ['-DAL_DEBUG']
+elif get_option('release-asserts')
+ # It's possible that some external code would rely on NDEBUG for conditionally
+ # excluding something other than asserts. The trade-off here is to accept that rather
+ # than possibly miss an assert.
+ alabaster_args += ['-DAL_RELEASE_ASSERTS']
else
alabaster_args += ['-DNDEBUG']
endif
+# The definition of the assert() macro is determined by the _last_ place where
+# <assert.h> was included, because it redefines itself each time. Making it
+# unnecessarily complicated to predict if assert() will be active or a no-op.
+# Maybe I just haven't seen why this could make sense but to me it's counterintuitive.
+# We define al_assert() to be unchanging and let any dependencies figure it out for themselves.
+# Another note, which I hadn't heard before but, this clearly makes relying on NDEBUG
+# for anything other than asserts a very bad practice.
+# https://sourceware.org/git/?p=glibc.git;a=blob;f=assert/assert.h;h=31892aebcb9115a3b48be4d179eb9e8ab2f8784f;hb=HEAD#l24
+if compiler.has_function('__assert_fail', prefix: '#include <assert.h>')
+ alabaster_args += ['-DAL_ASSERT_FUNCTION=__assert_fail', '-DAL_ASSERT_INCLUDE_FUNC']
+elif compiler.has_function('_assert', prefix: '#include <assert.h>')
+ # https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/assert-macro-assert-wassert?view=msvc-170
+ alabaster_args += ['-DAL_ASSERT_FUNCTION=_assert']
+elif compiler.has_function('__assert', prefix: '#include <assert.h>')
+ # https://github.com/aosp-mirror/platform_bionic/blob/731631f300090436d7f5df80d50b6275c8c60a93/libc/include/assert.h#L63
+ alabaster_args += ['-DAL_ASSERT_FUNCTION=__assert', '-DAL_ASSERT_EXPR_LAST']
+endif
+
if is_msvc_specifically
alabaster_args += ['/arch:AVX']
endif