summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Huddleston Sequoia <jeremyhu@apple.com>2012-08-28 10:06:51 -0700
committerJeremy Huddleston Sequoia <jeremyhu@apple.com>2012-09-22 14:12:38 -0700
commit78c77356c5d88d78d69b1a244c7e27cd85544842 (patch)
tree9c0472e515eec1b86a26de5162ee9d2a661238e5
parentdd36e132fae41d18dbb04f7111b92b4b187bd539 (diff)
list: Use offsetof() and typeof() to determine member offsets within a structure
Some compilers have difficulty with the previous implementation which relies on undefined behavior according to the C standard. Using offsetof() from <stddef.h> (which most likely just uses __builtin_offsetof on modern compilers) allows us to accomplish this without ambiguity. This fix also requires support for typeof(). If your compiler does not support typeof(), then the old implementation will be used. If you see failures in test/list, please try a more modern compiler. v2: Added fallback if typeof() is not present. Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu@apple.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> (cherry picked from commit b8ab93dfbc7f292b5bfe7e9113e1af824ccbd1a8)
-rw-r--r--configure.ac1
-rw-r--r--include/dix-config.h.in3
-rw-r--r--include/list.h21
3 files changed, 21 insertions, 4 deletions
diff --git a/configure.ac b/configure.ac
index 7c7e69e78..24da6e809 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,6 +136,7 @@ AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
+AC_C_TYPEOF
AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"])
AC_CHECK_SIZEOF([unsigned long])
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 3fb641367..2e4300e19 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -417,6 +417,9 @@
/* Define to 64-bit byteswap macro */
#undef bswap_64
+/* Define to 1 if typeof works with your compiler. */
+#undef HAVE_TYPEOF
+
/* The compiler supported TLS storage class, prefering initial-exec if tls_model is supported */
#undef TLS
diff --git a/include/list.h b/include/list.h
index d54a207b1..2d48a8646 100644
--- a/include/list.h
+++ b/include/list.h
@@ -26,6 +26,8 @@
#ifndef _XORG_LIST_H_
#define _XORG_LIST_H_
+#include <stddef.h> /* offsetof() */
+
/**
* @file Classic doubly-link circular list implementation.
* For real usage examples of the linked list, see the file test/list.c
@@ -232,7 +234,7 @@ xorg_list_is_empty(struct xorg_list *head)
*/
#ifndef container_of
#define container_of(ptr, type, member) \
- (type *)((char *)(ptr) - (char *) &((type *)0)->member)
+ (type *)((char *)(ptr) - offsetof(type, member))
#endif
/**
@@ -271,9 +273,20 @@ xorg_list_is_empty(struct xorg_list *head)
#define xorg_list_last_entry(ptr, type, member) \
xorg_list_entry((ptr)->prev, type, member)
-#define __container_of(ptr, sample, member) \
- (void *)((char *)(ptr) \
- - ((char *)&(sample)->member - (char *)(sample)))
+#ifdef HAVE_TYPEOF
+#define __container_of(ptr, sample, member) \
+ container_of(ptr, typeof(*sample), member)
+#else
+/* This implementation of __container_of has undefined behavior according
+ * to the C standard, but it works in many cases. If your compiler doesn't
+ * support typeof() and fails with this implementation, please try a newer
+ * compiler.
+ */
+#define __container_of(ptr, sample, member) \
+ (void *)((char *)(ptr) \
+ - ((char *)&(sample)->member - (char *)(sample)))
+#endif
+
/**
* Loop through the list given by head and set pos to struct in the list.
*