Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libcxx/include/__new/new_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

#if defined(_LIBCPP_ABI_VCRUNTIME)
# include <new.h>
Copy link
Member

Choose a reason for hiding this comment

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

How does the MSVC STL get their own definition for get_new_handler()? It seems really brittle to include <new.h> but have our definition for get_new_handler(). We should either declare all of them (set_new_handler(), the new_handler alias, etc) or rely on <new.h> to provide them, but not a mixture of both.

Copy link
Contributor

Choose a reason for hiding this comment

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

MSVC STL just (additionally) declares it in <new>. The declaration is not available from <new.h> or <vcruntime_new.h>.

Copy link
Contributor

Choose a reason for hiding this comment

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

@siradam7th I think it would be better to follow what MSVC STL does. We can just avoid special-casing _LIBCPP_ABI_VCRUNTIME, and consistently declare these 3 things ourselves.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@siradam7th I think it would be better to follow what MSVC STL does. We can just avoid special-casing _LIBCPP_ABI_VCRUNTIME, and consistently declare these 3 things ourselves.

I'll give it a try.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have removed the _LIBCPP_ABI_VCRUNTIME macro conditional from libcxx/include/__new/new_handler.h.
and fixed the missing symbols which are now defined by libcxx/src/new_handler.cpp, and everything is working correctly.
apart from a couple of warnings of redeclaration since some of the cpp files include <new>:

llvm-project\build\include\c++\v1\__new/new_handler.h(20,39): warning: redeclaration of 'std::set_new_handler' should not add 'dllexport' attribute [-Wdll-attribute-on-redeclaration]
   20 | _LIBCPP_EXPORTED_FROM_ABI new_handler set_new_handler(new_handler) _NOEXCEPT;
C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\ucrt\new.h(32,42): note: previous declaration is here
   32 |             _CRTIMP2 new_handler __cdecl set_new_handler(_In_opt_ new_handler _NewHandler) throw();
      |                                          ^
1 warning generated.

// <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)();
Expand Down
6 changes: 4 additions & 2 deletions libcxx/modules/std.compat/ctime.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
Contributor 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
Contributor 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
Member

Choose a reason for hiding this comment

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

The _LIBCPP_USING_IF_EXISTS attribute is intended to make things work when the declarations are not available, and avoid precisely these #ifdef blocks. What's the issue here?

Copy link
Contributor

@frederick-vs-ja frederick-vs-ja Jul 19, 2025

Choose a reason for hiding this comment

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

The issue on these <ctime> functions is that UCRT incorrectly adds static to them, so we can't directly export them. At this time we might simply skip export for them to make the standard modules buildable. MSVC STL chooses to reimplement them in the std namespace as a workaround.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

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))

Is just removing that line enough?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess we can try this:

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not familiar with how the tests are run/generated yet, I'll see...

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
3 changes: 3 additions & 0 deletions libcxx/modules/std.cppm.in
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
6 changes: 4 additions & 2 deletions libcxx/modules/std/ctime.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading