IGNORABLE extern char static_assert_failed[1 - 2*!(cond)]
#endif
-/* --- @CHECK_TYPE@ ---
+/* --- @CHECK_TYPE@ --- *
*
* Arguments: @expty@ = expected type of @x@
* @expty x@ = some object
#define CHECK_TYPE(expty, x) (!sizeof(*(expty *)0 = (x)))
-/* --- @CONVERT_CAREFULLY@ ---
+/* --- @CONVERT_CAREFULLY@ --- *
*
* Arguments: @newty@ = new type for the result
* @expty@ = expected type of @x@
#define CONVERT_CAREFULLY(newty, expty, x) \
(CHECK_TYPE(expty, x) + (/*unconst unvolatile*/ newty)(x))
+/* --- @CONTAINER@ --- *
+ *
+ * Arguments: @type@ = the parent type, a structure or union
+ * @mem@ = the name of the member we have a pointer to
+ * @memty *p@ = pointer to @member@ within @type@
+ *
+ * Returns: The address of the containing @ty@ object.
+ */
+
+#define CONTAINER(type, member, p) \
+ (!sizeof((p) = &((type *)0)->mem) + \
+ (type *)((unsigned char *)(p) - offsetof(type, mem)))
+
/* --- @UNCONST@, @UNVOLATILE@, @UNQUALIFY@ --- *
*
* Arguments: @type@ = a type name
# define LAUNDER(x) \
({ __typeof__(x) _y; __asm__("" : "=g"(_y) : "0"(x)); _y; })
# define ADMIRE(x) \
- ({ __asm__("" : : "g"(x)); })
+ ({ __asm__("" :: "g"(x)); })
# define ADMIRE_BUF(p, sz) \
- ({ __asm__("" : : "g"(p), "g"(sz)); })
-# define RELAX do __asm__ __volatile__("" ::: "memory"); while (0)
+ ({ __asm__("" :: "m"(*(unsigned char *)p), "g"(sz) : "memory"); })
+# define RELAX do __asm__(""); while (0)
#endif
#if CLANG_VERSION_P(3, 3)