mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-09 07:08:02 +02:00
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.
(cherry picked from commit b1810d7a68)
This commit is contained in:
parent
3c830ce5cf
commit
fda3458201
3 changed files with 57 additions and 47 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue