summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-12-13 12:06:20 +0100
committerThomas Haller <thaller@redhat.com>2019-12-13 13:46:37 +0100
commitf5b0713651f8603f93be82a47b22ed578762f5eb (patch)
treed2a6478321bcef16bfcc916529d6ae0d62df799a
parent4711019d34296f4fbc9543199d6c38b368740c33 (diff)
downloadNetworkManager-f5b0713651f8603f93be82a47b22ed578762f5eb.tar.gz
shared/glib: reimplement g_atomic_pointer_compare_and_exchange() macro
With glib 2.63.2 and clang 9.0.0 (Fedora 32) we get compile errors: ../clients/cloud-setup/nmcs-provider-ec2.c:51:8: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'const char **' [-Werror,-Wincompatible-pointer-types] if (!g_atomic_pointer_compare_and_exchange (&base_cached, NULL, base)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange' __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ ^~~~~~~~~~~~~~ ../src/devices/bluetooth/nm-bluez-manager.c:2836:2: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'const NMBtVTableNetworkServer **' (aka 'const struct _NMBtVTableNetworkServer **') [-Werror,-Wincompatible-pointer-types] g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, NULL, &priv->vtable_network_server); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange' __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ ^~~~~~~~~~~~~~ ../src/devices/bluetooth/nm-bluez-manager.c:2853:2: error: passing 'typeof ((&priv->vtable_network_server)) *' (aka 'struct _NMBtVTableNetworkServer **') to parameter of type 'const NMBtVTableNetworkServer **' (aka 'const struct _NMBtVTableNetworkServer **') discards qualifiers in nested pointer types [-Werror,-Wincompatible-pointer-types-discards-qualifiers] g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, &priv->vtable_network_server, NULL); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange' __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ ^~~~~~~~~~~~~~ ../src/devices/nm-device.c:8857:8: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'GBytes **' (aka 'struct _GBytes **') [-Werror,-Wincompatible-pointer-types] if (!g_atomic_pointer_compare_and_exchange (&global_duid, NULL, p)) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange' __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \ ^~~~~~~~~~~~~~ The issue happens because glib passes the "atomic" argument to __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) without cast, and clang 9 seems to be picky about const pointers. Add our own version of the macro that does better casts while also having better compile time checks for valid arguments.
-rw-r--r--shared/nm-glib-aux/nm-glib.h26
1 files changed, 26 insertions, 0 deletions
diff --git a/shared/nm-glib-aux/nm-glib.h b/shared/nm-glib-aux/nm-glib.h
index fa44f316c8..dfb75bf05f 100644
--- a/shared/nm-glib-aux/nm-glib.h
+++ b/shared/nm-glib-aux/nm-glib.h
@@ -575,4 +575,30 @@ _nm_g_value_unset (GValue *value)
/*****************************************************************************/
+/* Glib implements g_atomic_pointer_compare_and_exchange() as a macro.
+ * For one, to inline the atomic operation and also to perform some type checks
+ * on the arguments.
+ * Depending on compiler and glib version, glib passes the arguments as they
+ * are to __atomic_compare_exchange_n(). Some clang version don't accept const
+ * pointers there. Reimplement the macro to get that right, but with stronger
+ * type checks (as we use typeof()). Had one job. */
+static inline gboolean
+_g_atomic_pointer_compare_and_exchange (volatile void *atomic,
+ gconstpointer oldval,
+ gconstpointer newval)
+{
+ return g_atomic_pointer_compare_and_exchange ((void **) atomic, (void *) oldval, (void *) newval);
+}
+#undef g_atomic_pointer_compare_and_exchange
+#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
+ ({ \
+ typeof (atomic) const _atomic = (atomic); \
+ typeof (*_atomic) const _oldval = (oldval); \
+ typeof (*_atomic) const _newval = (newval); \
+ \
+ _g_atomic_pointer_compare_and_exchange (_atomic, _oldval, _newval); \
+ })
+
+/*****************************************************************************/
+
#endif /* __NM_GLIB_H__ */