summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-11-09 10:05:00 +0100
committerThomas Haller <thaller@redhat.com>2017-11-09 10:57:13 +0100
commitb1810d7a68d188aa8f36a0e23a7be705a742b1aa (patch)
tree1f2aa50d47569060e461d4a8ab0e0dafd53ea963
parentf02df2c2ca0a57696840e80c647b4d8176ea449b (diff)
downloadNetworkManager-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.h96
-rw-r--r--src/devices/nm-device-vlan.c6
-rw-r--r--src/platform/nm-linux-platform.c2
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)