This patch updates the container_of() implementation taken from the
Linux kernel.

We need to turn off -Wpointer-arith as the new container_of()
implementation does void pointer artihmetic as shown by this example
warning:

linux_helpers.h:43:26: warning: pointer of type ‘void *’ used in
arithmetic [-Wpointer-arith]
---
 dlm_controld/Makefile        |  2 +-
 dlm_controld/linux_helpers.h | 36 ++++++++++++++++++++++++++++++++++++
 dlm_controld/list.h          | 12 +-----------
 dlm_controld/rbtree.h        |  2 +-
 4 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/dlm_controld/Makefile b/dlm_controld/Makefile
index 28b6bb0a..328a64ba 100644
--- a/dlm_controld/Makefile
+++ b/dlm_controld/Makefile
@@ -38,7 +38,7 @@ LIB_SOURCE = lib.c
 
 CFLAGS += -D_GNU_SOURCE -O2 -ggdb \
        -Wall -Wformat -Wformat-security -Wmissing-prototypes -Wnested-externs \
-       -Wpointer-arith -Wextra -Wshadow -Wcast-align -Wwrite-strings \
+       -Wextra -Wshadow -Wcast-align -Wwrite-strings \
        -Waggregate-return -Wstrict-prototypes -Winline -Wredundant-decls \
        -Wno-sign-compare -Wno-unused-parameter -Wp,-D_FORTIFY_SOURCE=2 \
        -fexceptions -fasynchronous-unwind-tables -fdiagnostics-show-option \
diff --git a/dlm_controld/linux_helpers.h b/dlm_controld/linux_helpers.h
index 5ef13466..09705cff 100644
--- a/dlm_controld/linux_helpers.h
+++ b/dlm_controld/linux_helpers.h
@@ -3,6 +3,42 @@
 #ifndef __DLM_LINUX_HELPERS__
 #define __DLM_LINUX_HELPERS__
 
+/*
+ * static_assert - check integer constant expression at build time
+ *
+ * static_assert() is a wrapper for the C11 _Static_assert, with a
+ * little macro magic to make the message optional (defaulting to the
+ * stringification of the tested expression).
+ *
+ * Contrary to BUILD_BUG_ON(), static_assert() can be used at global
+ * scope, but requires the expression to be an integer constant
+ * expression (i.e., it is not enough that __builtin_constant_p() is
+ * true for expr).
+ *
+ * Also note that BUILD_BUG_ON() fails the build if the condition is
+ * true, while static_assert() fails the build if the expression is
+ * false.
+ */
+#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
+#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
+
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:       the pointer to the member.
+ * @type:      the type of the container struct this is embedded in.
+ * @member:    the name of the member within the struct.
+ *
+ * WARNING: any const qualifier of @ptr is lost.
+ */
+#define container_of(ptr, type, member) ({                             \
+       void *__mptr = (void *)(ptr);                                   \
+       static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
+                     __same_type(*(ptr), void),                        \
+                     "pointer type mismatch in container_of()");       \
+       ((type *)(__mptr - offsetof(type, member))); })
+
 #define WRITE_ONCE(x, val)                             \
 do {                                                   \
        *(volatile typeof(x) *)&(x) = (val);            \
diff --git a/dlm_controld/list.h b/dlm_controld/list.h
index a2a5e5f3..e9df2ef2 100644
--- a/dlm_controld/list.h
+++ b/dlm_controld/list.h
@@ -3,17 +3,7 @@
 #ifndef _LINUX_LIST_H
 #define _LINUX_LIST_H
 
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr:        the pointer to the member.
- * @type:       the type of the container struct this is embedded in.
- * @member:     the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                      \
-       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-       (type *)( (char *)__mptr - offsetof(type,member) );})
+#include "linux_helpers.h"
 
 /*
  * These are non-NULL pointers that will result in page faults
diff --git a/dlm_controld/rbtree.h b/dlm_controld/rbtree.h
index ddb86ff6..48b6e32f 100644
--- a/dlm_controld/rbtree.h
+++ b/dlm_controld/rbtree.h
@@ -20,7 +20,7 @@
 #include <stdbool.h>
 #include <string.h>
 
-#include "list.h"
+#include "linux_helpers.h"
 #include "rbtree_types.h"
 
 #define rb_parent(r)   ((struct rb_node *)((r)->__rb_parent_color & ~3))
-- 
2.31.1

Reply via email to