For the most part of C++ history, it couldn't have type declarations inside anonymous unions for different reasons. At the same time, __struct_group() relies on the latters, so when the @TAG arguments is not empty, C++ code doesn't want to build: In file included from test_cpp.cpp:5: In file included from tools/testing/selftests/bpf/tools/include/bpf/libbpf.h:18: tools/include/uapi/linux/bpf.h:6774:17: error: types cannot be declared in an anonymous union __struct_group(xdp_meta_generic_rx, rx_full, /* no attrs */, ^ The safest way to fix this without trying to switch standards (which is impossible anyway in UAPI) etc., is to disable tag declaration for that language. This won't break anything since for now it's not buildable at all. Use a separate definition for __struct_group() when __cplusplus is defined to mitigate the error. Also, mirror stddef.h into tools/ so that kernel-shipped userspace code would use the fixed definition instead of _something_ present in the system. Fixes: 50d7bd38c3aa ("stddef: Introduce struct_group() helper macro") Signed-off-by: Alexander Lobakin <alexandr.lobakin@xxxxxxxxx> --- include/uapi/linux/stddef.h | 12 ++++++-- tools/include/uapi/linux/stddef.h | 50 +++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 tools/include/uapi/linux/stddef.h diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h index 7837ba4fe728..67ee9c8aba56 100644 --- a/include/uapi/linux/stddef.h +++ b/include/uapi/linux/stddef.h @@ -20,14 +20,22 @@ * and size: one anonymous and one named. The former's members can be used * normally without sub-struct naming, and the latter can be used to * reason about the start, end, and size of the group of struct members. - * The named struct can also be explicitly tagged for layer reuse, as well - * as both having struct attributes appended. + * The named struct can also be explicitly tagged for layer reuse (C only), + * as well as both having struct attributes appended. */ +#ifndef __cplusplus #define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ union { \ struct { MEMBERS } ATTRS; \ struct TAG { MEMBERS } ATTRS NAME; \ } +#else +#define __struct_group(__IGNORED, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct { MEMBERS } ATTRS NAME; \ + } +#endif /** * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union diff --git a/tools/include/uapi/linux/stddef.h b/tools/include/uapi/linux/stddef.h new file mode 100644 index 000000000000..40d1c4b21003 --- /dev/null +++ b/tools/include/uapi/linux/stddef.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + +#ifndef __always_inline +#define __always_inline inline +#endif + +/** + * __struct_group() - Create a mirrored named and anonyomous struct + * + * @TAG: The tag name for the named sub-struct (usually empty) + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes (usually empty) + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical layout + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. + * The named struct can also be explicitly tagged for layer reuse (C only), + * as well as both having struct attributes appended. + */ +#ifndef __cplusplus +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } +#else +#define __struct_group(__IGNORED, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct { MEMBERS } ATTRS NAME; \ + } +#endif + +/** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } -- 2.36.1