Skip to content

Commit

Permalink
device.h: make it compatible with both C++20 and pre-C11 gcc
Browse files Browse the repository at this point in the history
Use braces conditionally for designated initializers of anonymous
unions. This is for device.h what what commit 19a33c7 ("init.h:
restore designated initializers in SYS_INIT_NAMED()") did for init.h

See long discussion in zephyrproject-rtos#69411 for more obscure C/C++ compatibility
details.

Signed-off-by: Marc Herbert <[email protected]>
  • Loading branch information
marc-hb committed May 2, 2024
1 parent 2f520e9 commit ed44886
Showing 1 changed file with 34 additions and 9 deletions.
43 changes: 34 additions & 9 deletions include/zephyr/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,24 @@ __syscall int device_init(const struct device *dev);
.state = (state_), \
.data = (data_), \
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \
Z_DEVICE_INIT_PM_BASE(pm_) \
}

/*
* Anonymous unions require C11. Some pre-C11 gcc versions have early
* support for anonymous unions but they require these braces when
* combined with C99 designated initializers. These braces are
* compatible with any C version but not with C++20. For more obscure
* C/C++ compatibility details see commit c15f029a7108 and PR #69411.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
# define Z_DEVICE_INIT_PM_BASE(pm_) \
IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),}))
#else
# define Z_DEVICE_INIT_PM_BASE(pm_) \
IF_ENABLED(CONFIG_PM_DEVICE, (.pm_base = (pm_),))
#endif

/**
* @brief Device section name (used for sorting purposes).
*
Expand Down Expand Up @@ -1008,23 +1023,33 @@ __syscall int device_init(const struct device *dev);
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
.init_fn = {COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
(init_fn_)}, \
{ \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
&DEVICE_NAME_GET(dev_id), \
}, \
Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id), \
}

// TODO: TEST BOTH new DEFER and old non defer. Requires some zephyr,deferred-init devtree
#define Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_) \
static const Z_DECL_ALIGN(struct init_entry) __used __noasan \
__attribute__((__section__(".z_deferred_init"))) \
Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \
.init_fn = {COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
(init_fn_)}, \
{ \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = \
&DEVICE_NAME_GET(dev_id), \
}, \
Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id), \
}
/*
* Anonymous unions require C11. Some pre-C11 gcc versions have early
* support for anonymous unions but they require these braces when
* combined with C99 designated initializers. These braces are
* compatible with any C version but not with C++20. For more obscure
* C/C++ compatibility details see commit c15f029a7108 and PR #69411.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
# define Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id) { Z_DEV_ENTRY_DEV(node_id, dev_id) }
#else
# define Z_DEVICE_INIT_ENTRY_DEV(node_id, dev_id) Z_DEV_ENTRY_DEV(node_id, dev_id)
#endif

#define Z_DEV_ENTRY_DEV(node_id, dev_id) \
COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (.dev_rw), (.dev)) = &DEVICE_NAME_GET(dev_id)

/**
* @brief Define a @ref device and all other required objects.
Expand Down

0 comments on commit ed44886

Please sign in to comment.