init.h: restore designated initializers in SYS_INIT_NAMED()

As seen in the PR #68125 discussion, commit 19a33c7884 ("init: adjust
the SYS_INIT dev field init to play nice with older compilers") entirely
threw away designated initializers in SYS_INIT_NAMED() to avoid
compatibility issues across toolchains.

One key aspect that was probably missed at the time: C and C++ are two
different languages and this is especially true with respect to
designated initializers.

Designated initializers provide safer and more readable code, especially
in their much stricter C++ version. So use an #ifdef to restore them in
SYS_INIT_NAMED() thanks to a small braces difference between C and C++.

Signed-off-by: Marc Herbert <marc.herbert@intel.com>
This commit is contained in:
Marc Herbert 2024-02-21 00:32:59 +00:00 committed by David Leach
parent 5b6fadc10d
commit c15f029a71
1 changed files with 35 additions and 1 deletions

View File

@ -151,6 +151,39 @@ struct init_entry {
__attribute__((__section__( \
".z_init_" #level STRINGIFY(prio)"_" STRINGIFY(sub_prio)"_")))
/* Designated initializers where added to C in C99. There were added to
* C++ 20 years later in a much more restricted form. C99 allows many
* variations: out of order, mix of designated and not, overlap,
* override,... but C++ allows none of these. See differences detailed
* in the P0329R0.pdf C++ proposal.
* Note __STDC_VERSION__ is undefined when compiling C++.
*/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__) < 201100
/* 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, see longer discussion in
* #69411.
* These braces are compatible with any C version but not with C++20.
*/
# define Z_INIT_SYS_INIT_DEV_NULL { .dev = NULL }
#else
/* When using -std=c++20 or higher, g++ (v12.2.0) reject braces for
* initializing anonymous unions because it is technically a mix of
* designated and not designated initializers which is not allowed in
* C++. Interestingly, the _same_ g++ version does accept the braces above
* when using -std=c++17 or lower!
* The tests/lib/cpp/cxx/ added by commit 3d9c428d57bf invoke the C++
* compiler with a range of different `-std=...` parameters without needing
* any manual configuration.
*/
# define Z_INIT_SYS_INIT_DEV_NULL .dev = NULL
#endif
/** @endcond */
/**
@ -205,7 +238,8 @@ struct init_entry {
#define SYS_INIT_NAMED(name, init_fn_, level, prio) \
static const Z_DECL_ALIGN(struct init_entry) \
Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan \
Z_INIT_ENTRY_NAME(name) = {{ (init_fn_) }, { NULL } }
Z_INIT_ENTRY_NAME(name) = {.init_fn = {.sys = (init_fn_)}, \
Z_INIT_SYS_INIT_DEV_NULL}
/** @} */