Skip to content

[libc++] Fix C++23 standard modules when using with clang-cl on Windows #148992

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

siradam7th
Copy link

The following PR fixes a couple of issues and compilation errors when using libcxx with clang-cl on Windows.

Issues:

  • compilation error because of missing definition of get_new_handler() in the ucrt/new.h that is included by libcxx/include/__new
  • compilation errors due to static inline in functions definition for ctime inside std.cppm.in and std.compat.cppm.in (std.cppm, std.compat.cppm).

Fixes:

  • defining get_new_handler() function under the std namespace when using _LIBCPP_ABI_VCRUNTIME.
  • defining _BUILD_STD_MODULE before including <ctime> inside std.cppm.in because MSVC's headers already have a fix in place.
  • both std.cppm and std.compat.cppm are fixed.

This pull request fixes the following issues:

@siradam7th siradam7th requested a review from a team as a code owner July 15, 2025 23:49
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 15, 2025

@llvm/pr-subscribers-libcxx

Author: Adam (siradam7th)

Changes

The following PR fixes a couple of issues and compilation errors when using libcxx with clang-cl on Windows.

Issues:

  • compilation error because of missing definition of get_new_handler() in the ucrt/new.h that is included by libcxx/include/__new
  • compilation errors due to static inline in functions definition for ctime inside std.cppm.in and std.compat.cppm.in (std.cppm, std.compat.cppm).

Fixes:

  • defining get_new_handler() function under the std namespace when using _LIBCPP_ABI_VCRUNTIME.
  • defining _BUILD_STD_MODULE before including &lt;ctime&gt; inside std.cppm.in because MSVC's headers already have a fix in place.
  • both std.cppm and std.compat.cppm are fixed.

This pull request fixes the following issues:


Full diff: https://github.com/llvm/llvm-project/pull/148992.diff

4 Files Affected:

  • (modified) libcxx/include/__new/new_handler.h (+5)
  • (modified) libcxx/modules/std.compat/ctime.inc (+4-2)
  • (modified) libcxx/modules/std.cppm.in (+3)
  • (modified) libcxx/modules/std/ctime.inc (+4-2)
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 <new.h>
+// <new.h> 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 <cstdio>
 #include <cstdlib>
 #include <cstring>
+#ifdef _LIBCPP_ABI_VCRUNTIME
+#define _BUILD_STD_MODULE
+#endif
 #include <ctime>
 #include <cuchar>
 #include <cwchar>
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

Copy link

⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off Keep my email addresses private setting in your account.
See LLVM Developer Policy and LLVM Discourse for more information.

@siradam7th
Copy link
Author

I have moved the macro definition to the file generate_libcxx_cppm_in.py.
I also fixed an encoding problem with that same file that stops it from running on Windows.

using ::asctime _LIBCPP_USING_IF_EXISTS;
using ::clock _LIBCPP_USING_IF_EXISTS;
using ::strftime _LIBCPP_USING_IF_EXISTS;

#ifndef _LIBCPP_ABI_VCRUNTIME
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you simply leaving these functions missing when using UCRT?

Also, it seem that we should modify this line libcxx/utils/libcxx/test/features.py to enable the tests:

or ("_WIN32" in compilerMacros(cfg) and not _mingwSupportsModules(cfg))

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking into it, however it seems that moving the definition '_BUILD_STD_MODULE' triggered some other weird errors, I'll do more testing tomorrow and see...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, these lines should be removed. Now get_new_handler.pass.cpp should always pass.

// 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++

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like just defining the macro is not enough, I have resorted to defining the actual functions as inline, I'll push the changes once I made sure that everything works with both std and std.compact.

Copy link

⚠️ Python code formatter, darker found issues in your code. ⚠️

You can test this locally with the following command:
darker --check --diff -r HEAD~1...HEAD libcxx/utils/generate_libcxx_cppm_in.py
View the diff from darker here.
--- generate_libcxx_cppm_in.py	2025-07-16 02:27:04.000000 +0000
+++ generate_libcxx_cppm_in.py	2025-07-16 07:22:36.872831 +0000
@@ -11,11 +11,13 @@
 
 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", encoding='utf-8') 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++ -*-
 //===----------------------------------------------------------------------===//
 //

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants