From ed2c4e4947d9f703675acdc0dad3c380fb0a390a Mon Sep 17 00:00:00 2001 From: siradam7th Date: Wed, 16 Jul 2025 00:35:50 +0100 Subject: [PATCH 1/5] fix libc++ std modules compilation on Windows using clang-cl --- libcxx/include/__new/new_handler.h | 5 +++++ libcxx/modules/std.compat/ctime.inc | 6 ++++-- libcxx/modules/std.cppm.in | 3 +++ libcxx/modules/std/ctime.inc | 6 ++++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/libcxx/include/__new/new_handler.h b/libcxx/include/__new/new_handler.h index 05f4e846c3ef9..2350f9ae9bc19 100644 --- a/libcxx/include/__new/new_handler.h +++ b/libcxx/include/__new/new_handler.h @@ -17,6 +17,11 @@ #if defined(_LIBCPP_ABI_VCRUNTIME) # include +// does not define 'get_new_handler' +// which makes the 'std' module build fail, this fixes it +namespace std { +_LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT; +} #else _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD typedef void (*new_handler)(); diff --git a/libcxx/modules/std.compat/ctime.inc b/libcxx/modules/std.compat/ctime.inc index eba8234a08969..7547b055b6807 100644 --- a/libcxx/modules/std.compat/ctime.inc +++ b/libcxx/modules/std.compat/ctime.inc @@ -14,15 +14,17 @@ export { using ::timespec _LIBCPP_USING_IF_EXISTS; using ::tm _LIBCPP_USING_IF_EXISTS; - using ::asctime _LIBCPP_USING_IF_EXISTS; using ::clock _LIBCPP_USING_IF_EXISTS; + using ::strftime _LIBCPP_USING_IF_EXISTS; + +#ifndef _LIBCPP_ABI_VCRUNTIME using ::ctime _LIBCPP_USING_IF_EXISTS; using ::difftime _LIBCPP_USING_IF_EXISTS; using ::gmtime _LIBCPP_USING_IF_EXISTS; using ::localtime _LIBCPP_USING_IF_EXISTS; using ::mktime _LIBCPP_USING_IF_EXISTS; - using ::strftime _LIBCPP_USING_IF_EXISTS; using ::time _LIBCPP_USING_IF_EXISTS; using ::timespec_get _LIBCPP_USING_IF_EXISTS; +#endif } // export diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in index 984b18321923c..f19dc07169fda 100644 --- a/libcxx/modules/std.cppm.in +++ b/libcxx/modules/std.cppm.in @@ -51,6 +51,9 @@ module; #include #include #include +#ifdef _LIBCPP_ABI_VCRUNTIME +#define _BUILD_STD_MODULE +#endif #include #include #include diff --git a/libcxx/modules/std/ctime.inc b/libcxx/modules/std/ctime.inc index 5bfa61917e5f2..e9f8ecb6ec63e 100644 --- a/libcxx/modules/std/ctime.inc +++ b/libcxx/modules/std/ctime.inc @@ -14,15 +14,17 @@ export namespace std { using std::timespec _LIBCPP_USING_IF_EXISTS; using std::tm _LIBCPP_USING_IF_EXISTS; - using std::asctime _LIBCPP_USING_IF_EXISTS; using std::clock _LIBCPP_USING_IF_EXISTS; + using std::strftime _LIBCPP_USING_IF_EXISTS; + +#ifndef _LIBCPP_ABI_VCRUNTIME using std::ctime _LIBCPP_USING_IF_EXISTS; using std::difftime _LIBCPP_USING_IF_EXISTS; using std::gmtime _LIBCPP_USING_IF_EXISTS; using std::localtime _LIBCPP_USING_IF_EXISTS; using std::mktime _LIBCPP_USING_IF_EXISTS; - using std::strftime _LIBCPP_USING_IF_EXISTS; using std::time _LIBCPP_USING_IF_EXISTS; using std::timespec_get _LIBCPP_USING_IF_EXISTS; +#endif } // namespace std From b6bf097211fc8755f233a8c81d7248910da03529 Mon Sep 17 00:00:00 2001 From: siradam7th Date: Sun, 20 Jul 2025 02:49:00 +0100 Subject: [PATCH 2/5] fix python file encoding error on Windows --- libcxx/utils/generate_libcxx_cppm_in.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libcxx/utils/generate_libcxx_cppm_in.py b/libcxx/utils/generate_libcxx_cppm_in.py index 39076a61b55b8..4e0d39289f33e 100644 --- a/libcxx/utils/generate_libcxx_cppm_in.py +++ b/libcxx/utils/generate_libcxx_cppm_in.py @@ -9,11 +9,19 @@ import os.path import sys -from libcxx.header_information import module_c_headers, module_headers, header_restrictions, headers_not_available, libcxx_root +from libcxx.header_information import ( + module_c_headers, + module_headers, + header_restrictions, + headers_not_available, + libcxx_root, +) def write_file(module): - with open(libcxx_root / "modules" / f"{module}.cppm.in", "w") as module_cpp_in: + with open( + libcxx_root / "modules" / f"{module}.cppm.in", "w", encoding="utf-8" + ) as module_cpp_in: module_cpp_in.write( """\ // -*- C++ -*- @@ -25,6 +33,7 @@ def write_file(module): // //===----------------------------------------------------------------------===// + // WARNING, this entire header is generated by // utils/generate_libcxx_cppm_in.py // DO NOT MODIFY! From 4e7a4c990be91e342baff24742d343c868d7970f Mon Sep 17 00:00:00 2001 From: siradam7th Date: Sun, 20 Jul 2025 02:58:17 +0100 Subject: [PATCH 3/5] add missing functions defined as inline, remove '_BUILD_STD_MODULE' --- libcxx/modules/std.compat/ctime.inc | 40 ++++++++++++++++++++++++++++ libcxx/modules/std.cppm.in | 3 --- libcxx/modules/std/ctime.inc | 41 +++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) diff --git a/libcxx/modules/std.compat/ctime.inc b/libcxx/modules/std.compat/ctime.inc index 7547b055b6807..dbaf76fe6363d 100644 --- a/libcxx/modules/std.compat/ctime.inc +++ b/libcxx/modules/std.compat/ctime.inc @@ -27,4 +27,44 @@ export { using ::time _LIBCPP_USING_IF_EXISTS; using ::timespec_get _LIBCPP_USING_IF_EXISTS; #endif + +// A workaround for UCRT because it defines these functions +// as static and that causes the error "internal linkage cannot be exported" +#ifdef _LIBCPP_ABI_VCRUNTIME + + template + inline char* __CRTDECL ctime(_In_ time_t const* const _Time) noexcept { + return _ctime64(_Time); + } + + template + inline double __CRTDECL difftime(_In_ time_t const _Time1, _In_ time_t const _Time2) noexcept { + return _difftime64(_Time1, _Time2); + } + + template + inline tm* __CRTDECL gmtime(_In_ time_t const* const _Time) noexcept { + return _gmtime64(_Time); + } + + template + inline tm* __CRTDECL localtime(_In_ time_t const* const _Time) noexcept { + return _localtime64(_Time); + } + + template + inline time_t __CRTDECL mktime(_Inout_ tm* const _Tm) noexcept { + return _mktime64(_Tm); + } + + template + inline time_t __CRTDECL time(_Out_opt_ time_t* const _Time) noexcept { + return _time64(_Time); + } + + template + inline int __CRTDECL timespec_get(_Out_ timespec* const _Ts, _In_ int const _Base) noexcept { + return _timespec64_get(reinterpret_cast<_timespec64*>(_Ts), _Base); + } +#endif } // export diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in index f19dc07169fda..984b18321923c 100644 --- a/libcxx/modules/std.cppm.in +++ b/libcxx/modules/std.cppm.in @@ -51,9 +51,6 @@ module; #include #include #include -#ifdef _LIBCPP_ABI_VCRUNTIME -#define _BUILD_STD_MODULE -#endif #include #include #include diff --git a/libcxx/modules/std/ctime.inc b/libcxx/modules/std/ctime.inc index e9f8ecb6ec63e..4caa9d3e33d36 100644 --- a/libcxx/modules/std/ctime.inc +++ b/libcxx/modules/std/ctime.inc @@ -14,6 +14,7 @@ export namespace std { using std::timespec _LIBCPP_USING_IF_EXISTS; using std::tm _LIBCPP_USING_IF_EXISTS; + using std::asctime _LIBCPP_USING_IF_EXISTS; using std::clock _LIBCPP_USING_IF_EXISTS; using std::strftime _LIBCPP_USING_IF_EXISTS; @@ -27,4 +28,44 @@ export namespace std { using std::time _LIBCPP_USING_IF_EXISTS; using std::timespec_get _LIBCPP_USING_IF_EXISTS; #endif + +// A workaround for UCRT because it defines these functions +// as static and that causes the error "internal linkage cannot be exported" +#ifdef _LIBCPP_ABI_VCRUNTIME + + template + inline char* __CRTDECL ctime(_In_ time_t const* const _Time) noexcept { + return _ctime64(_Time); + } + + template + inline double __CRTDECL difftime(_In_ time_t const _Time1, _In_ time_t const _Time2) noexcept { + return _difftime64(_Time1, _Time2); + } + + template + inline tm* __CRTDECL gmtime(_In_ time_t const* const _Time) noexcept { + return _gmtime64(_Time); + } + + template + inline tm* __CRTDECL localtime(_In_ time_t const* const _Time) noexcept { + return _localtime64(_Time); + } + + template + inline time_t __CRTDECL mktime(_Inout_ tm* const _Tm) noexcept { + return _mktime64(_Tm); + } + + template + inline time_t __CRTDECL time(_Out_opt_ time_t* const _Time) noexcept { + return _time64(_Time); + } + + template + inline int __CRTDECL timespec_get(_Out_ timespec* const _Ts, _In_ int const _Base) noexcept { + return _timespec64_get(reinterpret_cast<_timespec64*>(_Ts), _Base); + } +#endif } // namespace std From bf7ca141d4366bdef2cca482e89624fddf5362ce Mon Sep 17 00:00:00 2001 From: siradam7th Date: Sun, 20 Jul 2025 03:12:45 +0100 Subject: [PATCH 4/5] remove 'FIXME' for 'get_new_handler()' test --- .../alloc.errors/set.new.handler/get_new_handler.pass.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp b/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp index c5725bde6e6c3..2c0081703760e 100644 --- a/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp +++ b/libcxx/test/std/language.support/support.dynamic/alloc.errors/set.new.handler/get_new_handler.pass.cpp @@ -8,12 +8,6 @@ // test get_new_handler -// FIXME: When libc++ is linked against vcruntime (i.e. the default config in -// MSVC mode), the declarations of std::set_new_handler and std::get_new_handler -// are provided by vcruntime/UCRT's new.h. However, that header actually only -// declares set_new_handler - it's missing a declaration of get_new_handler. - -// XFAIL: msvc && stdlib=libc++ #include #include From b64ac1e96c824378abf61e2334911fe74aea5511 Mon Sep 17 00:00:00 2001 From: siradam7th Date: Tue, 22 Jul 2025 04:06:09 +0100 Subject: [PATCH 5/5] fix missing symbols for 'get_new_handler()' and 'set_new_handler()' --- libcxx/include/__new/new_handler.h | 9 --------- libcxx/src/new_handler.cpp | 4 +--- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/libcxx/include/__new/new_handler.h b/libcxx/include/__new/new_handler.h index 2350f9ae9bc19..8f93578da9f9c 100644 --- a/libcxx/include/__new/new_handler.h +++ b/libcxx/include/__new/new_handler.h @@ -15,19 +15,10 @@ # pragma GCC system_header #endif -#if defined(_LIBCPP_ABI_VCRUNTIME) -# include -// does not define 'get_new_handler' -// which makes the 'std' module build fail, this fixes it -namespace std { -_LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT; -} -#else _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD typedef void (*new_handler)(); _LIBCPP_EXPORTED_FROM_ABI new_handler set_new_handler(new_handler) _NOEXCEPT; _LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT; _LIBCPP_END_UNVERSIONED_NAMESPACE_STD -#endif // _LIBCPP_ABI_VCRUNTIME #endif // _LIBCPP___NEW_NEW_HANDLER_H diff --git a/libcxx/src/new_handler.cpp b/libcxx/src/new_handler.cpp index 49c21d85f5908..5124cb501c938 100644 --- a/libcxx/src/new_handler.cpp +++ b/libcxx/src/new_handler.cpp @@ -11,9 +11,7 @@ #include "include/atomic_support.h" #if defined(_LIBCPP_ABI_MICROSOFT) -# if !defined(_LIBCPP_ABI_VCRUNTIME) -# define _LIBPCPP_DEFINE_NEW_HANDLER -# endif +# define _LIBPCPP_DEFINE_NEW_HANDLER #elif defined(LIBCXX_BUILDING_LIBCXXABI) // nothing to do, we use the one from libc++abi #elif defined(LIBCXXRT)