[ccan] container_of_var() macro broken for compilers without typeof()
Rusty Russell
rusty at rustcorp.com.au
Wed Nov 10 17:22:52 EST 2010
On Wed, 10 Nov 2010 08:13:21 am Delio Brignoli wrote:
> Hello Rusty,
>
> Thanks for setting up ccan. The code I am developing is using list.h and has to compile on windows with Visual C and GCC on linux, but the container_of_var() macro will not work for compilers that #define HAVE_TYPEOF 0, because (a) the #ifdef is always true (maybe this is deliberate)
Erk, no, but explains why I didn't see this! I've added a TODO to add this
to ccanlint to check; thanks!
> and (b) 'containing_type' is undefined.
> I understand this cannot be fixed (*) but I was wondering if the #else branch should contain and #error to display an explicit error message.
>
> (*) except by changing the list's interface, which I suspect would not be a popular solution.
Oh no, it can be fixed, here's the quick patch I'm putting in now. I'm
testing the rest of the tree with !HAVE_TYPEOF too..
Thanks for the report!
Rusty.
diff --git a/ccan/check_type/check_type.h b/ccan/check_type/check_type.h
index d0dc0d4..8840567 100644
--- a/ccan/check_type/check_type.h
+++ b/ccan/check_type/check_type.h
@@ -51,7 +51,7 @@
#define check_types_match(expr1, expr2) \
((typeof(expr1) *)0 != (typeof(expr2) *)0)
#else
-#include "build_assert/build_assert.h"
+#include <ccan/build_assert/build_assert.h>
/* Without typeof, we can only test the sizes. */
#define check_type(expr, type) \
EXPR_BUILD_ASSERT(sizeof(expr) == sizeof(type))
diff --git a/ccan/container_of/container_of.h b/ccan/container_of/container_of.h
index de3f450..2a6b1cd 100644
--- a/ccan/container_of/container_of.h
+++ b/ccan/container_of/container_of.h
@@ -51,12 +51,13 @@
* return i;
* }
*/
-#ifdef HAVE_TYPEOF
+#if HAVE_TYPEOF
#define container_of_var(member_ptr, var, member) \
container_of(member_ptr, typeof(*var), member)
#else
-#define container_of_var(member_ptr, var, member) \
- ((void *)((char *)(member_ptr) - offsetof(containing_type, member)))
+#define container_of_var(member_ptr, var, member) \
+ ((void *)((char *)(member_ptr) \
+ - ((char *)&(var)->member - (char *)(var))))
#endif
#endif /* CCAN_CONTAINER_OF_H */
diff --git a/ccan/container_of/test/compile_fail-var-types.c b/ccan/container_of/test/compile_fail-var-types.c
index f9312b6..b7f395c 100644
--- a/ccan/container_of/test/compile_fail-var-types.c
+++ b/ccan/container_of/test/compile_fail-var-types.c
@@ -14,6 +14,9 @@ int main(int argc, char *argv[])
#ifdef FAIL
/* b is a char, but intp is an int * */
foop = container_of_var(intp, foop, b);
+#if !HAVE_TYPEOF
+#error "Unfortunately we don't fail if we don't have typeof."
+#endif
#else
foop = NULL;
#endif
More information about the ccan
mailing list