Skip to content

[libc] Fullbuild breaks with clang/musl system due to wint_t #63510

Open
@alfredfo

Description

@alfredfo

Compiling with ninja install-libc

err:

[2/18] Building CXX object projects/libc/src/wchar/CMakeFiles/libc.src.wchar.wctob.dir/wctob.cpp.o
FAILED: projects/libc/src/wchar/CMakeFiles/libc.src.wchar.wctob.dir/wctob.cpp.o 
/usr/lib/llvm/16/bin/clang++-16  --config=/etc/clang/abi-breaking-shit.cfg -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_LIBCPP_ENABLE_ASSERTIONS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/llvm-project/build-libc-full/projects/libc/src/wchar -I/llvm-project/libc/src/wchar -I/llvm-project/build-libc-full/include -I/llvm-project/llvm/include -I/llvm-project/build-libc-full/projects/libc/include -I/llvm-project/libc -I/llvm-project/build-libc-full/projects/libc -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -g -std=c++17 -fpie -ffreestanding -fno-builtin -fno-exceptions -fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti -Wall -Wextra -Wimplicit-fallthrough -Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path -Wstrict-prototypes -Wthread-safety -DLIBC_COPT_PUBLIC_PACKAGING -MD -MT projects/libc/src/wchar/CMakeFiles/libc.src.wchar.wctob.dir/wctob.cpp.o -MF projects/libc/src/wchar/CMakeFiles/libc.src.wchar.wctob.dir/wctob.cpp.o.d -o projects/libc/src/wchar/CMakeFiles/libc.src.wchar.wctob.dir/wctob.cpp.o -c /llvm-project/libc/src/wchar/wctob.cpp
In file included from /llvm-project/libc/src/wchar/wctob.cpp:9:
In file included from /llvm-project/libc/src/wchar/wctob.h:12:
/llvm-project/build-libc-full/projects/libc/include/wchar.h:21:11: error: unknown type name 'wint_t'
int wctob(wint_t) __NOEXCEPT;
          ^
In file included from /llvm-project/libc/src/wchar/wctob.cpp:9:
/llvm-project/libc/src/wchar/wctob.h:16:11: error: unknown type name 'wint_t'
int wctob(wint_t c);
          ^
In file included from /llvm-project/libc/src/wchar/wctob.cpp:11:
/llvm-project/libc/src/__support/wctype_utils.h:28:38: error: unknown type name 'wint_t'
LIBC_INLINE cpp::optional<int> wctob(wint_t c) {
                                     ^
/llvm-project/libc/src/__support/wctype_utils.h:36:27: error: use of undeclared identifier 'wint_t'
LIBC_INLINE cpp::optional<wint_t> btowc(int c) {
                          ^
/llvm-project/libc/src/__support/wctype_utils.h:38:12: error: no viable conversion from returned value of type 'const nullopt_t' to function return type 'int'
    return cpp::nullopt;
           ^~~~~~~~~~~~
/llvm-project/libc/src/__support/wctype_utils.h:39:22: error: unknown type name 'wint_t'
  return static_cast<wint_t>(c);
                     ^
/llvm-project/libc/src/wchar/wctob.cpp:17:1: error: definition 'wctob' cannot also be an alias
LLVM_LIBC_FUNCTION(int, wctob, (wint_t c)) {
^
/llvm-project/libc/src/__support/common.h:38:3: note: expanded from macro 'LLVM_LIBC_FUNCTION'
  LLVM_LIBC_FUNCTION_IMPL(type, name, arglist)
  ^
/llvm-project/libc/src/__support/common.h:30:38: note: expanded from macro 'LLVM_LIBC_FUNCTION_IMPL'
  decltype(__llvm_libc::name) name [[gnu::alias(#name)]];                      \
                                     ^
/llvm-project/libc/src/wchar/wctob.cpp:17:33: error: unknown type name 'wint_t'
LLVM_LIBC_FUNCTION(int, wctob, (wint_t c)) {
                                ^
8 errors generated.

looking at libc/include/llvm-libc-types/wint_t.h we can see that it wants the type wint_t from stddef.h by using the implementation specific __need_wint_t macro. Because this is C++ it will use the libc++ wrapper header that #include_next's stddef.h

libc/include/llvm-libc-types/wint_t.h:

// Since __need_wint_t is defined, we get the definition of wint_t from the
// standalone C header stddef.h. Also, because __need_wint_t is defined,
// including stddef.h will pull only the type wint_t and nothing else.
#define __need_wint_t
#include <stddef.h>
#undef __need_wint_t

We now have two choices, either include the musl stddef.h header, or the internal Clang header.

Clang:

#if defined(__need_wint_t)
/* Always define wint_t when modules are available. */
#if !defined(_WINT_T) || __has_feature(modules)
#if !__has_feature(modules)
#define _WINT_T
#endif
typedef __WINT_TYPE__ wint_t;
#endif
#undef __need_wint_t
#endif /* __need_wint_t */

musl:

#if defined(__NEED_wint_t) && !defined(__DEFINED_wint_t)
typedef unsigned wint_t;
#define __DEFINED_wint_t
#endif

As Clang uses __need_wint_t (underscore) it will work, however it won't with musl as it uses __NEED_wint_t. I am unsure if LLVM libc intends to use the Clang header, or if it depends on glibc internals (it too uses underscore).

Compiling wctob.cpp with the first command + -save-temps, we can see in wctob.ii (preprocessed) that stddef.h comes from the system libc.

$ grep stddef.h wctob.ii 
# 1 "/usr/include/c++/v1/stddef.h" 1 3
# 15 "/usr/include/c++/v1/stddef.h" 3
# 1 "/usr/include/stddef.h" 1 3 4
# 19 "/usr/include/stddef.h" 3 4
# 20 "/usr/include/stddef.h" 2 3 4
# 18 "/usr/include/c++/v1/stddef.h" 2 3
# 1 "/usr/include/c++/v1/stddef.h" 1 3
# 15 "/usr/include/c++/v1/stddef.h" 3
# 1 "/usr/include/c++/v1/stddef.h" 1 3
# 15 "/usr/include/c++/v1/stddef.h" 3
# 1 "/usr/include/c++/v1/stddef.h" 1 3
# 15 "/usr/include/c++/v1/stddef.h" 3

Include path ordering with compilation command + -v

ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /llvm-project/build-libc-full/projects/libc/src/wchar
 /llvm-project/libc/src/wchar
 /llvm-project/build-libc-full/include
 /llvm-project/llvm/include
 /llvm-project/build-libc-full/projects/libc/include
 /llvm-project/libc
 /llvm-project/build-libc-full/projects/libc
 /usr/include/c++/v1
 /usr/include
 /usr/lib/llvm/16/bin/../../../../lib/clang/16/include

A very simple and ugly? fix is to just define __NEED_wint_t too. Note that -ffreestanding is used when compiling.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions