[PATCH] Define alignof using _Alignof when using C11 or newer

1 view
Skip to first unread message

Khem Raj

unread,
Jan 15, 2023, 2:15:20 AM1/15/23
to opkg-...@googlegroups.com, Khem Raj
WG14 N2350 made very clear that it is an UB having type definitions
within "offsetof" [1]. This patch enhances the implementation of macro
alignof_slot to use builtin "_Alignof" to avoid undefined behavior on
when using std=c11 or newer

clang 16+ has started to flag this [2]

Fixes build when using -std >= gnu11 and using clang16+

Older compilers gcc < 4.9 or clang < 8 has buggy _Alignof even though it
may support C11, exclude those compilers too

[1] https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm
[2] https://reviews.llvm.org/D133574

Signed-off-by: Khem Raj <raj....@gmail.com>
---
libopkg/md5.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/libopkg/md5.c b/libopkg/md5.c
index 981b9b8..ccb645e 100644
--- a/libopkg/md5.c
+++ b/libopkg/md5.c
@@ -237,7 +237,17 @@ void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
/* Process available complete blocks. */
if (len >= 64) {
#if !_STRING_ARCH_unaligned
+/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
+ <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
+ clang versions < 8.0.0 have the same bug. */
+#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
+ || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
+ && !defined __clang__) \
+ || (defined __clang__ && __clang_major__ < 8))
#define alignof(type) offsetof (struct { char c; type x; }, x)
+#else
+#define alignof(type) _Alignof(type)
+#endif
#define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
if (UNALIGNED_P(buffer))
while (len > 64) {
--
2.39.0

Alex Stewart

unread,
Jan 17, 2023, 4:05:18 PM1/17/23
to Khem Raj, opkg-...@googlegroups.com
Hey Khem,

This seems fine to me. I wasn't able to reproduce a similar error by
compiling with clang-16 on my machine, but I'm not sure I understand how
to set the C std to be 11 or greater.

Could you at least post the warning text that clang is giving you, for
future reference?

I'll pull this tomorrow, if there are no objections.

Thanks,

On 1/15/23 01:15, Khem Raj wrote:
> WG14 N2350 made very clear that it is an UB having type definitions
> within "offsetof" [1]. This patch enhances the implementation of macro
> alignof_slot to use builtin "_Alignof" to avoid undefined behavior on
> when using std=c11 or newer
>
> clang 16+ has started to flag this [2]
>
> Fixes build when using -std >= gnu11 and using clang16+
>
> Older compilers gcc < 4.9 or clang < 8 has buggy _Alignof even though it
> may support C11, exclude those compilers too
>
> [1] https://urldefense.com/v3/__https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm__;!!FbZ0ZwI3Qg!uL8KRK3_An6qVsles3O__Vz2tUnmrXOWJBNAgiagXJ2lQR-ZXLj2SvnZsKasE0K-3Yosaw4oVtHECYju$
> [2] https://urldefense.com/v3/__https://reviews.llvm.org/D133574__;!!FbZ0ZwI3Qg!uL8KRK3_An6qVsles3O__Vz2tUnmrXOWJBNAgiagXJ2lQR-ZXLj2SvnZsKasE0K-3Yosaw4oVieCis4q$
>
> Signed-off-by: Khem Raj <raj....@gmail.com>
> ---
> libopkg/md5.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/libopkg/md5.c b/libopkg/md5.c
> index 981b9b8..ccb645e 100644
> --- a/libopkg/md5.c
> +++ b/libopkg/md5.c
> @@ -237,7 +237,17 @@ void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
> /* Process available complete blocks. */
> if (len >= 64) {
> #if !_STRING_ARCH_unaligned
> +/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
> + <https://urldefense.com/v3/__https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023__;!!FbZ0ZwI3Qg!uL8KRK3_An6qVsles3O__Vz2tUnmrXOWJBNAgiagXJ2lQR-ZXLj2SvnZsKasE0K-3Yosaw4oVvvV5AKh$ >.
> + clang versions < 8.0.0 have the same bug. */
> +#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
> + || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
> + && !defined __clang__) \
> + || (defined __clang__ && __clang_major__ < 8))
> #define alignof(type) offsetof (struct { char c; type x; }, x)
> +#else
> +#define alignof(type) _Alignof(type)
> +#endif
> #define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
> if (UNALIGNED_P(buffer))
> while (len > 64) {

--
Alex Stewart
Software Engineer - NI Real-Time OS
NI (National Instruments)

alex.s...@ni.com

Khem Raj

unread,
Jan 17, 2023, 5:22:47 PM1/17/23
to Alex Stewart, opkg-...@googlegroups.com
On Tue, Jan 17, 2023 at 1:05 PM Alex Stewart <alex.s...@ni.com> wrote:
>
> Hey Khem,
>
> This seems fine to me. I wasn't able to reproduce a similar error by
> compiling with clang-16 on my machine, but I'm not sure I understand how
> to set the C std to be 11 or greater.
>

Hmm I am not sure how old your clang-16 snapshot is does it include
https://reviews.llvm.org/D133574?
you can try clang16 branch on meta-clang if you are using OE.

> Could you at least post the warning text that clang is giving you, for
> future reference?

Sure. I dont have the logs handy but you, this change has been
settling in slowly, it was reverted and than relanded
as a warning again. So Depending upon your clang 16 snapshot, you can
reproduce this by adding
-Werror -Wgnu-alignof-expression as of today.

Khem Raj

unread,
Jan 17, 2023, 6:15:38 PM1/17/23
to Alex Stewart, opkg-...@googlegroups.com
here is the warning-turned-error from todays clang

riscv64-yoe-linux-musl-clang -target riscv64-yoe-linux-musl
-mlittle-endian --dyld-prefix=/usr -Qunused-arguments
-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wformat
-Wformat-security -Werror=format-security
--sysroot=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/recipe-sysroot
-DHAVE_CONFIG_H -I. -I../../opkg-0.6.1/libopkg -I.. -Wall
-DHOST_CPU_STR=\"riscv64\" -DDATADIR=\"/usr/share\"
-DSYSCONFDIR=\"/etc\" -DVARDIR=\"/var\" -I../../opkg-0.6.1 -O2 -pipe
-g -feliminate-unused-debug-types
-fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/opkg-0.6.1=/usr/src/debug/opkg/1_0.6.1-r0
-fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/opkg-0.6.1=/usr/src/debug/opkg/1_0.6.1-r0
-fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/build=/usr/src/debug/opkg/1_0.6.1-r0
-fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/build=/usr/src/debug/opkg/1_0.6.1-r0
-fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/recipe-sysroot=
-fmacro-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/recipe-sysroot=
-fdebug-prefix-map=/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/recipe-sysroot-native=
-c ../../opkg-0.6.1/libopkg/md5.c -fPIC -DPIC -o .libs/md5.o
-Wgnu-offsetof-extensions -Werror
../../opkg-0.6.1/libopkg/md5.c:242:13: error: defining a type within
'offsetof' is a Clang extension [-Werror,-Wgnu-offsetof-extensions]
if (UNALIGNED_P(buffer))
^~~~~~~~~~~~~~~~~~~
../../opkg-0.6.1/libopkg/md5.c:241:40: note: expanded from macro 'UNALIGNED_P'
#define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
^~~~~~~~~~~~~~~~~~
../../opkg-0.6.1/libopkg/md5.c:240:33: note: expanded from macro 'alignof'
#define alignof(type) offsetof (struct { char c; type x; }, x)
^~~~~~
/mnt/b/yoe/master/build/tmp/work/riscv64-yoe-linux-musl/opkg/1_0.6.1-r0/recipe-sysroot/usr/include/stddef.h:22:51:
note: expanded from macro 'offsetof'
#define offsetof(type, member) __builtin_offsetof(type, member)
^~~~
1 error generated.

Alex Stewart

unread,
Jan 18, 2023, 6:01:30 PM1/18/23
to Khem Raj, opkg-...@googlegroups.com
Pulled this commit to `master` as
19e2a38c27cd98df9e5d5d959bba80136b77fa01 [1].

[1]
https://git.yoctoproject.org/opkg/commit/?id=19e2a38c27cd98df9e5d5d959bba80136b77fa01

Thanks!

On 1/15/23 01:15, Khem Raj wrote:
> WG14 N2350 made very clear that it is an UB having type definitions
> within "offsetof" [1]. This patch enhances the implementation of macro
> alignof_slot to use builtin "_Alignof" to avoid undefined behavior on
> when using std=c11 or newer
>
> clang 16+ has started to flag this [2]
>
> Fixes build when using -std >= gnu11 and using clang16+
>
> Older compilers gcc < 4.9 or clang < 8 has buggy _Alignof even though it
> may support C11, exclude those compilers too
>
> Signed-off-by: Khem Raj <raj....@gmail.com>
> ---
> libopkg/md5.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/libopkg/md5.c b/libopkg/md5.c
> index 981b9b8..ccb645e 100644
> --- a/libopkg/md5.c
> +++ b/libopkg/md5.c
> @@ -237,7 +237,17 @@ void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
> /* Process available complete blocks. */
> if (len >= 64) {
> #if !_STRING_ARCH_unaligned
> +/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
> + <https://urldefense.com/v3/__https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023__;!!FbZ0ZwI3Qg!uL8KRK3_An6qVsles3O__Vz2tUnmrXOWJBNAgiagXJ2lQR-ZXLj2SvnZsKasE0K-3Yosaw4oVvvV5AKh$ >.
> + clang versions < 8.0.0 have the same bug. */
> +#if (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 \
> + || (defined __GNUC__ && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
> + && !defined __clang__) \
> + || (defined __clang__ && __clang_major__ < 8))
> #define alignof(type) offsetof (struct { char c; type x; }, x)
> +#else
> +#define alignof(type) _Alignof(type)
> +#endif
> #define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
> if (UNALIGNED_P(buffer))
> while (len > 64) {

--
Reply all
Reply to author
Forward
0 new messages