diff options
author | Thomas Haller <thaller@redhat.com> | 2017-11-09 10:05:00 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-11-09 10:57:13 +0100 |
commit | b1810d7a68d188aa8f36a0e23a7be705a742b1aa (patch) | |
tree | 1f2aa50d47569060e461d4a8ab0e0dafd53ea963 | |
parent | f02df2c2ca0a57696840e80c647b4d8176ea449b (diff) | |
download | NetworkManager-b1810d7a68d188aa8f36a0e23a7be705a742b1aa.tar.gz |
shared: rework _NM_GET_PRIVATE() to use _Generic()
_NM_GET_PRIVATE() used typeof() to propagate constness of the @self
pointer. However, that means, it could only be used with a self pointer
of the exact type. That means, you explicitly had to cast from (GObject *)
or from (void *).
The requirement is cumbersome, and often led us to either create @self
pointer we didn't need:
NMDeviceVlan *self = NM_DEVICE_VLAN (device);
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self);
or casting:
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDevice *) device);
In both cases we forcefully cast the source variable, loosing help from
the compiler to detect a bug.
For "nm-linux-platform.c", instead we commonly have a pointer of type
NMPlatform. Hence, we always forcefully cast the type via _NM_GET_PRIVATE_VOID().
Rework the macro to use _Generic(). If compiler supports _Generic(), then we
will get all compile time checks as desired. If the compiler doesn't support
_Generic(), it will still work. You don't get the compile-time checking of course,
but you'd notice that something is wrong once you build with a suitable
compiler.
-rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 96 | ||||
-rw-r--r-- | src/devices/nm-device-vlan.c | 6 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 2 |
3 files changed, 57 insertions, 47 deletions
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index d9dab83d73..68b69bf403 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -270,26 +270,65 @@ NM_G_ERROR_MSG (GError *error) #endif #if _NM_CC_SUPPORT_GENERIC -#define _NM_CONSTCAST(type, obj) \ - (_Generic ((obj), \ - void * : ((type *) (obj)), \ - void *const : ((type *) (obj)), \ +#define _NM_CONSTCAST_FULL(type, obj_expr, obj) \ + (_Generic ((obj_expr), \ const void * : ((const type *) (obj)), \ - const void *const: ((const type *) (obj)), \ - const type * : (obj), \ - const type *const: (obj), \ - type * : (obj), \ - type *const : (obj))) + void * : (( type *) (obj)), \ + const type * : ((const type *) (obj)), \ + type * : (( type *) (obj)))) +#define _NM_CONSTCAST2_FULL(type, obj_expr, obj, alias_type2) \ + (_Generic ((obj_expr), \ + const void *: ((const type *) (obj)), \ + void *: (( type *) (obj)), \ + const alias_type2 *: ((const type *) (obj)), \ + alias_type2 *: (( type *) (obj)), \ + const type *: ((const type *) (obj)), \ + type *: (( type *) (obj)))) +#define _NM_CONSTCAST3_FULL(type, obj_expr, obj, alias_type2, alias_type3) \ + (_Generic ((obj_expr), \ + const void *: ((const type *) (obj)), \ + void *: (( type *) (obj)), \ + const alias_type2 *: ((const type *) (obj)), \ + alias_type2 *: (( type *) (obj)), \ + const alias_type3 *: ((const type *) (obj)), \ + alias_type3 *: (( type *) (obj)), \ + const type *: ((const type *) (obj)), \ + type *: (( type *) (obj)))) #else /* _NM_CONSTCAST() is there to preserve constness of a pointer. * It uses C11's _Generic(). If that is not supported, we fall back * to casting away constness. So, with _Generic, we get some additional * static type checking by preserving constness, without, we cast it * to a non-const pointer. */ -#define _NM_CONSTCAST(type, obj) \ +#define _NM_CONSTCAST_FULL(type, obj_expr, obj) \ + ((type *) (obj)) +#define _NM_CONSTCAST2_FULL(type, obj_expr, obj, alias_type2) \ + ((type *) (obj)) +#define _NM_CONSTCAST3_FULL(type, obj_expr, obj, alias_type2, alias_type2) \ ((type *) (obj)) #endif +#define _NM_CONSTCAST(type, obj) \ + _NM_CONSTCAST_FULL(type, (obj), (obj)) + +#define _NM_CONSTCAST2(type, obj, alias_type2) \ + _NM_CONSTCAST2_FULL(type, (obj), (obj), alias_type2) + +#define _NM_GOBJECT_CAST(type, obj, is_check) \ + ({ \ + const void *_obj = (obj); \ + \ + nm_assert (is_check (_obj)); \ + _NM_CONSTCAST2_FULL (type, (obj), _obj, GObject); \ + }) +#define _NM_GOBJECT_CAST2(type, obj, is_check, alias_type2) \ + ({ \ + const void *_obj = (obj); \ + \ + nm_assert (is_check (_obj)); \ + _NM_CONSTCAST3_FULL (type, (obj), _obj, GObject, alias_type2); \ + }) + #if _NM_CC_SUPPORT_GENERIC /* returns @value, if the type of @value matches @type. * This requires support for C11 _Generic(). If no support is @@ -581,39 +620,10 @@ _notify (obj_type *obj, _PropertyEnums prop) \ /*****************************************************************************/ -/* these are implemented as a macro, because they accept self - * as both (type*) and (const type*), and return a const - * private pointer accordingly. */ -#define __NM_GET_PRIVATE(self, type, is_check, addrop) \ - ({ \ - /* preserve the const-ness of self. Unfortunately, that - * way, @self cannot be a void pointer */ \ - typeof (self) _self = (self); \ - \ - /* Get compiler error if variable is of wrong type */ \ - _nm_unused const type *const _self2 = (_self); \ - \ - nm_assert (is_check (_self)); \ - ( addrop ( _NM_CONSTCAST (type, _self)->_priv) ); \ - }) - -#define _NM_GET_PRIVATE(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, &) -#define _NM_GET_PRIVATE_PTR(self, type, is_check) __NM_GET_PRIVATE(self, type, is_check, ) - -#define __NM_GET_PRIVATE_VOID(self, type, is_check, result_cmd) \ - ({ \ - /* (self) can be any non-const pointer. It will be cast to "type *". - * We don't explicitly cast but assign first to (void *) which - * will fail if @self is pointing to const. */ \ - void *const _self1 = (self); \ - type *const _self = _self1; \ - \ - nm_assert (is_check (_self)); \ - ( result_cmd ); \ - }) - -#define _NM_GET_PRIVATE_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check, &_self->_priv) -#define _NM_GET_PRIVATE_PTR_VOID(self, type, is_check) __NM_GET_PRIVATE_VOID(self, type, is_check, _self->_priv) +#define _NM_GET_PRIVATE( self, type, is_check) (&(_NM_GOBJECT_CAST (type, (self), is_check )->_priv)) +#define _NM_GET_PRIVATE_PTR( self, type, is_check) ( (_NM_GOBJECT_CAST (type, (self), is_check )->_priv)) +#define _NM_GET_PRIVATE2( self, type, is_check, alias_type2) (&(_NM_GOBJECT_CAST2 (type, (self), is_check, alias_type2)->_priv)) +#define _NM_GET_PRIVATE2_PTR(self, type, is_check, alias_type2) ( (_NM_GOBJECT_CAST2 (type, (self), is_check, alias_type2)->_priv)) /*****************************************************************************/ diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index e30dae7449..1253a66418 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -66,7 +66,7 @@ struct _NMDeviceVlanClass { G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) -#define NM_DEVICE_VLAN_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceVlan, NM_IS_DEVICE_VLAN) +#define NM_DEVICE_VLAN_GET_PRIVATE(self) _NM_GET_PRIVATE2 (self, NMDeviceVlan, NM_IS_DEVICE_VLAN, NMDevice) /*****************************************************************************/ @@ -418,7 +418,7 @@ complete_connection (NMDevice *device, static void update_connection (NMDevice *device, NMConnection *connection) { - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) device); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); int ifindex = nm_device_get_ifindex (device); const char *setting_parent, *new_parent; @@ -558,7 +558,7 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) object); + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); switch (prop_id) { case PROP_VLAN_ID: diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index c4c93ed3f1..9ce520bdcc 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -2867,7 +2867,7 @@ struct _NMLinuxPlatformClass { G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM) -#define NM_LINUX_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE_VOID(self, NMLinuxPlatform, NM_IS_LINUX_PLATFORM) +#define NM_LINUX_PLATFORM_GET_PRIVATE(self) _NM_GET_PRIVATE2(self, NMLinuxPlatform, NM_IS_LINUX_PLATFORM, NMPlatform) NMPlatform * nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support) |