summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-18 07:14:27 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-18 16:46:50 -0600
commit957db32f46ca468043e1699817273a3e228c1ffb (patch)
treed0ce176f48866cdd9825901ac0f105b5785da2c9
parent740bffed4da51c4d46a1295baabe3bd249cf9138 (diff)
libmisc: LM_ARRAY_LEN: Compiler-error if not array
-rw-r--r--libmisc/include/libmisc/assert.h11
-rw-r--r--libmisc/include/libmisc/macro.h6
2 files changed, 11 insertions, 6 deletions
diff --git a/libmisc/include/libmisc/assert.h b/libmisc/include/libmisc/assert.h
index 8cf0735..0563a58 100644
--- a/libmisc/include/libmisc/assert.h
+++ b/libmisc/include/libmisc/assert.h
@@ -1,6 +1,6 @@
/* libmisc/assert.h - More assertions
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -16,9 +16,10 @@
const char *msg);
#endif
-#define assert_msg(expr, msg) __assert_msg(expr, #expr, msg) /* libmisc */
-#define assert(expr) __assert_msg(expr, #expr, 0) /* C89, POSIX-2001 */
-#define assert_notreached(msg) do { __assert_msg(0, "notreached", msg); __builtin_unreachable(); } while (0) /* libmisc */
-#define static_assert _Static_assert /* C11 */
+#define assert_msg(expr, msg) __assert_msg(expr, #expr, msg) /* libmisc */
+#define assert(expr) __assert_msg(expr, #expr, 0) /* C89, POSIX-2001 */
+#define assert_notreached(msg) do { __assert_msg(0, "notreached", msg); __builtin_unreachable(); } while (0) /* libmisc */
+#define static_assert _Static_assert /* C11 */
+#define static_assert_as_expr(...) (sizeof(struct {static_assert(__VA_ARGS__);})) /* libmisc */
#endif /* _LIBMISC_ASSERT_H_ */
diff --git a/libmisc/include/libmisc/macro.h b/libmisc/include/libmisc/macro.h
index 6cb15fb..a95ac82 100644
--- a/libmisc/include/libmisc/macro.h
+++ b/libmisc/include/libmisc/macro.h
@@ -7,6 +7,8 @@
#ifndef _LIBMISC_MACRO_H_
#define _LIBMISC_MACRO_H_
+#include <libmisc/assert.h>
+
/* for function definitions */
#define LM_UNUSED(argname)
@@ -16,7 +18,9 @@
/* types */
-#define LM_ARRAY_LEN(ary) (sizeof(ary)/sizeof((ary)[0]))
+/* If it's a pointer instead of an array, then typeof(&ptr[0]) == typeof(ptr) */
+#define _LM_IS_ARRAY(ary) (!__builtin_types_compatible_p(typeof(&(ary)[0]), typeof(ary)))
+#define LM_ARRAY_LEN(ary) ( (sizeof(ary)/sizeof((ary)[0])) + static_assert_as_expr(_LM_IS_ARRAY(ary)) )
#define LM_CAST_FIELD_TO_STRUCT(STRUCT_TYP, FIELD_NAME, PTR_TO_FIELD) ({ \
/* The _fptr assignment is to get the compiler to do type checking. */ \