util: use gcc builtins to better check array sizes
authorFlavio Leitner <fbl@redhat.com>
Wed, 2 Oct 2013 05:40:09 +0000 (02:40 -0300)
committerBen Pfaff <blp@nicira.com>
Wed, 2 Oct 2013 23:45:38 +0000 (16:45 -0700)
GCC provides two useful builtin functions that can help
to improve array size checking during compilation.

This patch contains no functional changes, but it makes
it easier to detect mistakes.

Signed-off-by: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
AUTHORS
lib/util.h

diff --git a/AUTHORS b/AUTHORS
index 63c1ef8..7892328 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -33,6 +33,7 @@ Duffie Cooley           dcooley@nicira.com
 Ed Maste                emaste at freebsd.org
 Edward Tomasz NapieraƂa trasz@freebsd.org
 Ethan Jackson           ethan@nicira.com
+Flavio Leitner          fbl@redhat.com
 FUJITA Tomonori         fujita.tomonori@lab.ntt.co.jp
 Gaetano Catalli         gaetano.catalli@gmail.com
 Giuseppe Lettieri       g.lettieri@iet.unipi.it
index 0db41be..a899065 100644 (file)
@@ -87,8 +87,23 @@ void ovs_assert_failure(const char *, const char *, const char *) NO_RETURN;
 
 extern const char *program_name;
 
+#define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0]))
+#ifdef __GNUC__
+/* return 0 for array types, 1 otherwise */
+#define __ARRAY_CHECK(ARRAY)                                   \
+    !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0]))
+
+/* compile-time fail if not array */
+#define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)]))
+#define __ARRAY_SIZE(ARRAY)                                    \
+    __builtin_choose_expr(__ARRAY_CHECK(ARRAY),                        \
+        __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY))
+#else
+#define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY)
+#endif
+
 /* Returns the number of elements in ARRAY. */
-#define ARRAY_SIZE(ARRAY) (sizeof ARRAY / sizeof *ARRAY)
+#define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
 
 /* Returns X / Y, rounding up.  X must be nonnegative to round correctly. */
 #define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y))