[PATCH v2] Enforce type check in ARRAY_SIZE macro

janisozaur at gmail.com janisozaur at gmail.com
Sun Jul 8 16:34:41 CDT 2018


From: Michał Janiszewski <janisozaur at gmail.com>

Inspired by kernel check and recent unification of ARRAY_SIZE, provide
a way of enforcing the macro can only be applied to actual arrays and
not to pointers.

v2: Fix parentheses

Signed-off-by: Michał Janiszewski <janisozaur at gmail.com>
---
 include/winnt.h | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/include/winnt.h b/include/winnt.h
index 7f822c4aec..b99a375ab0 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -760,7 +760,26 @@ typedef struct _MEMORY_BASIC_INFORMATION
   ((type *)((PCHAR)(address) - offsetof(type, field)))
 
 #ifdef __WINESRC__
-# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+// Validate types used in the expression.
+// Based on https://elixir.bootlin.com/linux/v4.17.4/source/include/linux/kernel.h#L71
+
+#ifdef __GNUC__
+/**
+ * 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
+ * e.g. in a structure initializer (or where-ever else comma expressions
+ * aren't permitted).
+ */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a) \
+    BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
+#else
+#define __must_be_array(a) 0
+#endif
+
+# define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + __must_be_array(x))
 #endif
 
 /* Types */
-- 
2.18.0




More information about the wine-devel mailing list