aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-08-27 21:53:47 -0400
committerAnthony G. Basile <blueness@gentoo.org>2014-08-27 22:13:34 -0400
commit820c792432841a41270a3caaaac172b8ebb15f33 (patch)
tree4c2ce11b6640d3d215b2ad5c4886975a0371c662
parentudev: add missing new-line in udevadm error (diff)
downloadeudev-820c792432841a41270a3caaaac172b8ebb15f33.tar.gz
eudev-820c792432841a41270a3caaaac172b8ebb15f33.tar.bz2
eudev-820c792432841a41270a3caaaac172b8ebb15f33.zip
shared: make container_of() use unique variable names
If you stack container_of() macros, you will get warnings due to shadowing variables of the parent context. To avoid this, use unique names for variables. Two new helpers are added: UNIQ: This evaluates to a truly unique value never returned by any evaluation of this macro. It's a shortcut for __COUNTER__. UNIQ_T: Takes two arguments and concatenates them. It is a shortcut for CONCATENATE, but meant to defined typed local variables. As you usually want to use variables that you just defined, you need to reference the same unique value at least two times. However, UNIQ returns a new value on each evaluation, therefore, you have to pass the unique values into the macro like this: #define my_macro(a, b) __max_macro(UNIQ, UNIQ, (a), (b)) #define __my_macro(uniqa, uniqb, a, b) ({ typeof(a) UNIQ_T(A, uniqa) = (a); typeof(b) UNIQ_T(B, uniqb) = (b); MY_UNSAFE_MACRO(UNIQ_T(A, uniqa), UNIQ_T(B, uniqb)); }) This way, MY_UNSAFE_MACRO() can safely evaluate it's arguments multiple times as they are local variables. But you can also stack invocations to the macro my_macro() without clashing names. This is the same as if you did: #define my_macro(a, b) __max_macro(__COUNTER__, __COUNTER__, (a), (b)) #define __my_macro(prefixa, prefixb, a, b) ({ typeof(a) CONCATENATE(A, prefixa) = (a); typeof(b) CONCATENATE(B, prefixb) = (b); MY_UNSAFE_MACRO(CONCATENATE(A, prefixa), CONCATENATE(B, prefixb)); }) ...but in my opinion, the first macro is easier to write and read. This patch starts by converting container_of() to use this new helper. Other macros may follow (like MIN, MAX, CLAMP, ...). Signed-off-by: Anthony G. Basile <blueness@gentoo.org>
-rw-r--r--src/shared/macro.h16
1 files changed, 11 insertions, 5 deletions
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 112e90196..e8c564837 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -45,6 +45,12 @@
#define REENABLE_WARNING \
_Pragma("GCC diagnostic pop")
+#define XCONCATENATE(x, y) x ## y
+#define CONCATENATE(x, y) XCONCATENATE(x, y)
+
+#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
+#define UNIQ __COUNTER__
+
/* Rounds up */
#define ALIGN4(l) (((l) + 3) & ~3)
@@ -70,13 +76,13 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) {
* @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) \
+#define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member)
+#define __container_of(uniq, ptr, type, member) \
__extension__ ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) ); \
- })
+ const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \
+ (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \
+ })
#define assert_se(expr) \
do { \