[PATCH] debug: fix BUILD_BUG_ON() for non-constant expressions

From: Ingo Molnar
Date: Sun Aug 17 2008 - 05:58:58 EST


constant expressions get detected at build time via:

kernel/sched.c: In function âtest':
kernel/sched.c:9187: error: size of array âtype name' is negative
make[1]: *** [kernel/sched.o] Error 1

but non-constant expressions (for example BUILD_BUG_ON(variable)) simply
get discarded by the compiler - turning BUILD_BUG_ON() into a dangerous
construct.

So add another layer at the link level to detect such mishaps:

kernel/built-in.o: In function `test':
: undefined reference to `__BUILD_BUG_ON_non_constant'

Signed-off-by: Ingo Molnar <mingo@xxxxxxx>
---
include/linux/kernel.h | 18 ++++++++++++++++--
1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2651f80..36c841e 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -467,8 +467,22 @@ struct sysinfo {
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};

-/* Force a compilation error if condition is true */
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+/*
+ * Force a compilation error if condition is true [array index becomes
+ * negative], and a linker error if condition is not constant [non-defined
+ * variable is used as an array index]:
+ *
+ * ( The linker trick relies on gcc optimizing out a multiplication with
+ * constant zero - which should be reasonable enough. )
+ */
+extern unsigned int __BUILD_BUG_ON_non_constant;
+
+#define BUILD_BUG_ON(condition) \
+do { \
+ (void)sizeof(char[1 - 2*!!(condition)]); \
+ if (!__builtin_constant_p(condition)) \
+ __BUILD_BUG_ON_non_constant++; \
+} while (0)

/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used