lib/60618: <sys/stddef.h> breaks LLVM and GCC builds
"Rainer Orth via gnats" <[email protected]>
| Newsgroups | gmane.os.netbsd.bugs |
|---|---|
| Message-ID | <[email protected]> |
>Number: 60618 >Category: lib >Synopsis: <sys/stddef.h> breaks LLVM and GCC builds >Confidential: no >Severity: serious >Priority: medium >Responsible: lib-bug-people >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Tue Aug 18 08:00:00 +0000 2026 >Originator: Rainer Orth >Release: NetBSD 11.0 >Organization: Bielefeld University, Center for Biotechnology <organization of PR author (multiple lines)> >Environment: <The following information is extracted from your kernel. Please> <append output of "ldd", "ident" where relevant (multiple lines).> System: NetBSD nbsd-amd64.gcc 11.0 NetBSD 11.0 (GENERIC) #0: Thu Jul 30 15:23:12 UTC 2026 [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC amd64 Architecture: x86_64 Machine: amd64 >Description: The introduction of <sys/stddef.h> in NetBSD 11.0, with <stddef.h> replaced by a symlink, breaks the builds of both LLVM and GCC. This happens because the different definitions of max_align_t in <sys/stddef.h> and the compiler-supplied versions of <stddef.h> can now conflict, causing compilation failures. >How-To-Repeat: The original testcase, extracted from LLVM compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cpp (or its GCC libsanitizer equivalent) is like $ cat stddef-kmemuser.c #define _KMEMUSER #include <sys/sysctl.h> #include <stddef.h> Compiliation with either clang (both the /usr/pkg/bin one and a self-compiled clang-24) fails: $ clang -c stddef-kmemuser.c In file included from stddef-kmemuser.c:2: In file included from /usr/include/sys/sysctl.h:60: In file included from /usr/pkg/lib/clang/21/include/stddef.h:123: /usr/pkg/lib/clang/21/include/__stddef_max_align_t.h:24:3: error: typedef redefinition with different types ('struct max_align_t' vs 'union max_align_t') 24 | } max_align_t; | ^ /usr/include/sys/stddef.h:105:3: note: previous definition is here 105 | } max_align_t; | ^ 1 error generated. GCC trunk is similar: $ gcc -c stddef.c In file included from stddef.c:2: /usr/include/sys/stddef.h:105:3: error: conflicting types for 'max_align_t'; have 'union <anonymous>' 105 | } max_align_t; | ^~~~~~~~~~~ In file included from stddef.c:1: /vol/gcc-17/lib/gcc/amd64-pc-netbsd10.1/17.0.0/include/stddef.h:451:3: note: previous declaration of 'max_align_t' with type 'max_align_t' 451 | } max_align_t; | ^~~~~~~~~~~ This doesn't happen with the bundled gcc 12.5.0 because, unlike upstream, that version doesn't install the gcc-supplied stddef.h. Both GCC stddef.h (from gcc/ginclude/stdef.h in the source tree) and LLVM stddef.h (from clang/lib/Headers/stddef.h in the source tree) exist to always provide a fully standard-conformant version of <stddef.h> even if the system headers violate the standard in some way, overriding the system header. AFAICS that's not necessary on NetBSD 11.0, but is done unconditionally by both compilers. In both cases the compiler stddef.h definition of max_align_t differs from the system header: the compiler headers use typedef struct { ... } max_align_t; while <sys/stddef.h> uses typedef union { ... } max_align_t; Both definitions comply with the C standard and have been like this forever AFAICS. However, when both defitions are present in the same compilation, the errors above happen. In the original example, this happens because with _KMEMUSER defined <sys/sysctl.h> indirectly includes <machine/pcb.h>. That one, along with <sys/container_of.h>, include <sys/stdef.h> instead of <stddef.h>, so both the compiler and system versions of <stddef.h> are present. While this is the (admittedly somewhat contrieved) real-live example, the same error obvious occurs with the trivial $ cat stddef.c #include <stddef.h> #include <sys/stddef.h> >Fix: For the original testcase, I've worked around this like so: #include <stddef.h> // Inhibit the inclusion of the NetBSD 11 <sys/stddef.h> which clashes with // Clang <stddef.h> max_align_t. #define _SYS_STDDEF_H_ before including <sys/sysctl.h>. A real solution would consist of: * Change <machine/pcb.h> and <sys/container_of.h> to just include <stddef.h> like all other system headers. * Maybe undo the introduction of <sys/stddef.h> and move the header back to <stddef.h> so no conflict is possible. * If that's not going to happen, GCC'S stddef.h would need to account for the changed multiple-inclusion guard (_STDDEF_H_ -> _SYS_STDDEF_H_) to avoid the conflict on its own. Clang stddef.h would still be left out in the cold, though. IMO there needs to be some solution that works with unmodified upstream GCC and LLVM, not something that's just done for the bundled versions. This allows for GCC and LLVM developers to build the code without having to hunt down NetBSD-private patches. >Unformatted: <Please check that the above is correct for the bug being reported,> <and append source date of snapshot, if applicable (one line).>