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.
This commit is contained in:
@@ -270,26 +270,65 @@ NM_G_ERROR_MSG (GError *error)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if _NM_CC_SUPPORT_GENERIC
|
#if _NM_CC_SUPPORT_GENERIC
|
||||||
#define _NM_CONSTCAST(type, obj) \
|
#define _NM_CONSTCAST_FULL(type, obj_expr, obj) \
|
||||||
(_Generic ((obj), \
|
(_Generic ((obj_expr), \
|
||||||
void * : ((type *) (obj)), \
|
|
||||||
void *const : ((type *) (obj)), \
|
|
||||||
const void * : ((const type *) (obj)), \
|
const void * : ((const type *) (obj)), \
|
||||||
const void *const: ((const type *) (obj)), \
|
void * : (( type *) (obj)), \
|
||||||
const type * : (obj), \
|
const type * : ((const type *) (obj)), \
|
||||||
const type *const: (obj), \
|
type * : (( type *) (obj))))
|
||||||
type * : (obj), \
|
#define _NM_CONSTCAST2_FULL(type, obj_expr, obj, alias_type2) \
|
||||||
type *const : (obj)))
|
(_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
|
#else
|
||||||
/* _NM_CONSTCAST() is there to preserve constness of a pointer.
|
/* _NM_CONSTCAST() is there to preserve constness of a pointer.
|
||||||
* It uses C11's _Generic(). If that is not supported, we fall back
|
* It uses C11's _Generic(). If that is not supported, we fall back
|
||||||
* to casting away constness. So, with _Generic, we get some additional
|
* to casting away constness. So, with _Generic, we get some additional
|
||||||
* static type checking by preserving constness, without, we cast it
|
* static type checking by preserving constness, without, we cast it
|
||||||
* to a non-const pointer. */
|
* 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))
|
((type *) (obj))
|
||||||
#endif
|
#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
|
#if _NM_CC_SUPPORT_GENERIC
|
||||||
/* returns @value, if the type of @value matches @type.
|
/* returns @value, if the type of @value matches @type.
|
||||||
* This requires support for C11 _Generic(). If no support is
|
* 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
|
#define _NM_GET_PRIVATE( self, type, is_check) (&(_NM_GOBJECT_CAST (type, (self), is_check )->_priv))
|
||||||
* as both (type*) and (const type*), and return a const
|
#define _NM_GET_PRIVATE_PTR( self, type, is_check) ( (_NM_GOBJECT_CAST (type, (self), is_check )->_priv))
|
||||||
* private pointer accordingly. */
|
#define _NM_GET_PRIVATE2( self, type, is_check, alias_type2) (&(_NM_GOBJECT_CAST2 (type, (self), is_check, alias_type2)->_priv))
|
||||||
#define __NM_GET_PRIVATE(self, type, is_check, addrop) \
|
#define _NM_GET_PRIVATE2_PTR(self, type, is_check, alias_type2) ( (_NM_GOBJECT_CAST2 (type, (self), is_check, alias_type2)->_priv))
|
||||||
({ \
|
|
||||||
/* 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)
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
@@ -66,7 +66,7 @@ struct _NMDeviceVlanClass {
|
|||||||
|
|
||||||
G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE)
|
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
|
static void
|
||||||
update_connection (NMDevice *device, NMConnection *connection)
|
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);
|
NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection);
|
||||||
int ifindex = nm_device_get_ifindex (device);
|
int ifindex = nm_device_get_ifindex (device);
|
||||||
const char *setting_parent, *new_parent;
|
const char *setting_parent, *new_parent;
|
||||||
@@ -558,7 +558,7 @@ static void
|
|||||||
get_property (GObject *object, guint prop_id,
|
get_property (GObject *object, guint prop_id,
|
||||||
GValue *value, GParamSpec *pspec)
|
GValue *value, GParamSpec *pspec)
|
||||||
{
|
{
|
||||||
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE ((NMDeviceVlan *) object);
|
NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_VLAN_ID:
|
case PROP_VLAN_ID:
|
||||||
|
@@ -2867,7 +2867,7 @@ struct _NMLinuxPlatformClass {
|
|||||||
|
|
||||||
G_DEFINE_TYPE (NMLinuxPlatform, nm_linux_platform, NM_TYPE_PLATFORM)
|
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 *
|
NMPlatform *
|
||||||
nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support)
|
nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support)
|
||||||
|
Reference in New Issue
Block a user