diff options
author | Thomas Haller <thaller@redhat.com> | 2019-12-13 12:06:20 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-12-13 13:46:37 +0100 |
commit | f5b0713651f8603f93be82a47b22ed578762f5eb (patch) | |
tree | d2a6478321bcef16bfcc916529d6ae0d62df799a | |
parent | 4711019d34296f4fbc9543199d6c38b368740c33 (diff) | |
download | NetworkManager-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.h | 26 |
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__ */ |