[PATCH 0/2] MR10577: Fix build with old clang (<13).
When clang < 13 cross-compiles for Windows, it sets _MSC_VER to 1911 (< 1912). The #if/#elif chain in __config checked _MSC_VER < 1912 first, which prevented the elif branch from defining _LIBCPP_DEFER_NEW_TO_VCRUNTIME. This caused placement new/delete to be defined in both vcruntime_new.h and the libc++ <new> header, resulting in redefinition errors. Fix by checking _LIBCPP_ABI_MICROSOFT first to always define _LIBCPP_DEFER_NEW_TO_VCRUNTIME when using vcruntime, then handle the aligned allocation check as a nested condition. Also add fall back to the wmemchr() call or manual loop on clang < 13. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10577
From: Vitaly Lipatov <lav@etersoft.ru> When clang < 13 cross-compiles for Windows, it sets _MSC_VER to 1911 (< 1912). The #if/#elif chain in __config checked _MSC_VER < 1912 first, which prevented the elif branch from defining _LIBCPP_DEFER_NEW_TO_VCRUNTIME. This caused placement new/delete to be defined in both vcruntime_new.h and the libc++ <new> header, resulting in redefinition errors. Fix by checking _LIBCPP_ABI_MICROSOFT first to always define _LIBCPP_DEFER_NEW_TO_VCRUNTIME when using vcruntime, then handle the aligned allocation check as a nested condition. --- include/msvcrt/__config | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/msvcrt/__config b/include/msvcrt/__config index 78ff1b2ab4e..02b3eefa6ba 100644 --- a/include/msvcrt/__config +++ b/include/msvcrt/__config @@ -992,15 +992,17 @@ template <unsigned> struct __static_assert_check {}; // If we are getting operator new from the MSVC CRT, then allocation overloads // for align_val_t were added in 19.12, aka VS 2017 version 15.3. -#if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 -# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -#elif defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) # define _LIBCPP_DEFER_NEW_TO_VCRUNTIME -# if !defined(__cpp_aligned_new) +# if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +# elif !defined(__cpp_aligned_new) // We're defering to Microsoft's STL to provide aligned new et al. We don't // have it unless the language feature test macro is defined. # define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION # endif +#elif defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION #endif #if defined(__APPLE__) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10577
From: Vitaly Lipatov <lav@etersoft.ru> Clang < 13 reports __has_feature(cxx_constexpr_string_builtins) as true but does not inline __builtin_wmemchr for Windows targets, generating an external call to wmemchr instead. Since Wine's ucrtbase does not export wmemchr (it is defined as static inline in wchar.h), this causes an undefined symbol error at link time for modules using libc++ (e.g. icu). Fall back to the wmemchr() call or manual loop on clang < 13. --- include/msvcrt/__string | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/msvcrt/__string b/include/msvcrt/__string index b919ff80b67..74328903d1e 100644 --- a/include/msvcrt/__string +++ b/include/msvcrt/__string @@ -374,7 +374,7 @@ char_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __ { if (__n == 0) return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) +#if __has_feature(cxx_constexpr_string_builtins) && __clang_major__ >= 13 return __builtin_wmemchr(__s, __a, __n); #elif _LIBCPP_STD_VER <= 14 return wmemchr(__s, __a, __n); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10577
Jacek Caban (@jacek) commented about include/msvcrt/__config:
-#if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 -# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -#elif defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) # define _LIBCPP_DEFER_NEW_TO_VCRUNTIME -# if !defined(__cpp_aligned_new) +# if defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +# elif !defined(__cpp_aligned_new) // We're defering to Microsoft's STL to provide aligned new et al. We don't // have it unless the language feature test macro is defined. # define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION # endif +#elif defined(_LIBCPP_MSVCRT) && defined(_MSC_VER) && _MSC_VER < 1912 +# define _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION #endif Since we always provide those, I think we may just remove `_MSC_VER < 1912` cases for simplicity.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10577#note_135131
Jacek Caban (@jacek) commented about include/msvcrt/__string:
{ if (__n == 0) return nullptr; -#if __has_feature(cxx_constexpr_string_builtins) +#if __has_feature(cxx_constexpr_string_builtins) && __clang_major__ >= 13 I think we could use `__has_builtin(__builtin_wmemchr)` to avoid hardcoding the compiler version.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10577#note_135132
On Mon Apr 6 17:28:55 2026 +0000, Jacek Caban wrote:
I think we could use `__has_builtin(__builtin_wmemchr)` to avoid hardcoding the compiler version. Nevermind, it will not do what we need.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10577#note_135136
On Mon Apr 6 17:57:39 2026 +0000, Jacek Caban wrote:
Nevermind, it will not do what we need. Unfortunately __has_builtin(__builtin_wmemchr) returns true even on clang 11, where the builtin is not actually inlined for Windows targets — clang emits an external jmp wmemchr call instead:
``` $ echo '#if __has_builtin(__builtin_wmemchr) extern "C" const wchar_t *f(const wchar_t *s, wchar_t c, __SIZE_TYPE__ n) { return __builtin_wmemchr(s, c, n); } #endif' | clang-11 -target x86_64-windows -O2 -S -o - -x c++ - 2>&1 | grep wmemchr jmp wmemchr # TAILCALL ``` On clang 19 the same test produces no external wmemchr reference (the builtin is properly inlined). Since __has_builtin doesn't distinguish these cases, I used __clang_major__ >= 13 instead. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10577#note_135140
participants (3)
-
Jacek Caban (@jacek) -
Vitaly Lipatov -
Vitaly Lipatov (@lav)