From 096ad576251484e9aa4ea35b61eff6e69342357f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 04:17:21 -0800 Subject: [PATCH 01/11] `_EXPORT_STD using meow = meow;` --- stl/inc/exception | 4 ++-- stl/inc/new | 6 +++--- stl/inc/typeinfo | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/exception b/stl/inc/exception index bb34e333cf..051d2f2dbf 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -35,8 +35,8 @@ _STD_END _STD_BEGIN -_EXPORT_STD class exception; -_EXPORT_STD class bad_exception; +_EXPORT_STD using exception = exception; +_EXPORT_STD using bad_exception = bad_exception; _EXPORT_STD using ::terminate; diff --git a/stl/inc/new b/stl/inc/new index 6b6a8164e3..22329d06a6 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -24,7 +24,7 @@ _STL_DISABLE_CLANG_WARNINGS // Mirroring declarations: _STD_BEGIN -_EXPORT_STD extern "C++" struct nothrow_t; +_EXPORT_STD using nothrow_t = nothrow_t; _EXPORT_STD extern "C++" const nothrow_t nothrow; _STD_END @@ -76,8 +76,8 @@ _EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept _STD_BEGIN #if _HAS_EXCEPTIONS -_EXPORT_STD class bad_alloc; -_EXPORT_STD class bad_array_new_length; +_EXPORT_STD using bad_alloc = bad_alloc; +_EXPORT_STD using bad_array_new_length = bad_array_new_length; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv // exports bad_alloc and bad_array_new_length. #endif // ^^^ !_HAS_EXCEPTIONS ^^^ diff --git a/stl/inc/typeinfo b/stl/inc/typeinfo index de903e92e1..662bc41433 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -23,7 +23,7 @@ _STL_DISABLE_CLANG_WARNINGS #include #pragma pop_macro("raw_name") -_EXPORT_STD extern "C++" class type_info; // for typeid, MSVC looks for type_info in the global namespace +_EXPORT_STD using type_info = type_info; // for typeid, MSVC looks for type_info in the global namespace _STD_BEGIN @@ -33,8 +33,8 @@ _INLINE_VAR constexpr int _Small_object_num_ptrs = 6 + 16 / sizeof(void*); _EXPORT_STD using ::type_info; #if _HAS_EXCEPTIONS -_EXPORT_STD class bad_cast; -_EXPORT_STD class bad_typeid; +_EXPORT_STD using bad_cast = bad_cast; +_EXPORT_STD using bad_typeid = bad_typeid; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv _EXPORT_STD class bad_cast : public exception { // base of all bad cast exceptions public: From 9e7c285ad29bd8cedbe8652c0a1f79f066dbbe17 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 04:22:13 -0800 Subject: [PATCH 02/11] Test that the affected classes are exported. --- .../std/include/test_header_units_and_modules.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index ae0e81eda4..d334219322 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -204,6 +204,10 @@ void test_deque() { void test_exception() { using namespace std; puts("Testing ."); + + static_assert(is_class_v); + static_assert(is_class_v); + assert(uncaught_exceptions() == 0); const exception_ptr ep = current_exception(); assert(!ep); @@ -471,6 +475,11 @@ void test_mutex() { void test_new() { using namespace std; puts("Testing ."); + + static_assert(is_class_v); + static_assert(is_class_v); + static_assert(is_class_v); + bool caught_bad_alloc = false; try { @@ -988,6 +997,11 @@ void test_typeindex() { void test_typeinfo() { using namespace std; puts("Testing ."); + + static_assert(is_class_v); + static_assert(is_class_v); + static_assert(is_class_v); + const type_info& t1 = typeid(int); const type_info& t2 = typeid(const int&); const type_info& t3 = typeid(double); From 5bd1e7d52b8cba0d97e5dadc6d939cf60dc91b5d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 05:04:21 -0800 Subject: [PATCH 03/11] Fix and test `align_val_t`. --- stl/inc/new | 8 +------- tests/std/include/test_header_units_and_modules.hpp | 1 + 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/stl/inc/new b/stl/inc/new index 22329d06a6..759cf3411e 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -43,13 +43,7 @@ _EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, const _STD noth #ifdef __cpp_aligned_new _STD_BEGIN -#ifdef __EDG__ // TRANSITION, VSO-1618988 -extern "C++" { -_EXPORT_STD enum class align_val_t : size_t; -} -#else // ^^^ workaround / no workaround vvv -_EXPORT_STD extern "C++" enum class align_val_t : size_t; -#endif // ^^^ no workaround ^^^ +_EXPORT_STD using align_val_t = align_val_t; _STD_END _EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index d334219322..2f8038a0fd 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -478,6 +478,7 @@ void test_new() { static_assert(is_class_v); static_assert(is_class_v); + static_assert(is_same_v, size_t>); static_assert(is_class_v); bool caught_bad_alloc = false; From e7f044565f79e338193b560387aa0d223a0dade0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 05:47:47 -0800 Subject: [PATCH 04/11] Fix the `nothrow` object; we already test it. --- stl/inc/new | 5 ----- stl/modules/std.ixx | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/stl/inc/new b/stl/inc/new index 759cf3411e..fce313935f 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -23,11 +23,6 @@ _STL_DISABLE_CLANG_WARNINGS // Mirroring declarations: -_STD_BEGIN -_EXPORT_STD using nothrow_t = nothrow_t; -_EXPORT_STD extern "C++" const nothrow_t nothrow; -_STD_END - _EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); _EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( size_t, const _STD nothrow_t&) noexcept; diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 7a5fdbf7ce..1c6a0ebf62 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -7,6 +7,12 @@ module; // This named module expects to be built with classic headers, not header units. #define _BUILD_STD_MODULE +// N4971 [module.interface]/6: "A redeclaration of an entity X is implicitly exported +// if X was introduced by an exported declaration; otherwise it shall not be exported." +// Therefore, we'll need to introduce the `nothrow` object with an exported declaration, +// instead of allowing to declare it. +#define __NOTHROW_T_DEFINED + // The subset of "C headers" [tab:c.headers] corresponding to // the "C++ headers for C library facilities" [tab:headers.cpp.c] #include @@ -36,6 +42,16 @@ export module std; #pragma warning(push) #pragma warning(disable : 5244) // '#include ' in the purview of module 'std' appears erroneous. +#include +#pragma pack(push, _CRT_PACKING) +_STD_BEGIN +_EXPORT_STD extern "C++" struct nothrow_t { + explicit nothrow_t() = default; +}; +_EXPORT_STD extern "C++" const nothrow_t nothrow; +_STD_END +#pragma pack(pop) + // "C++ library headers" [tab:headers.cpp] #include #if _HAS_STATIC_RTTI From 748e6d887d42c344b5d075396d3dc45dddca6ac3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 12:47:02 -0800 Subject: [PATCH 05/11] Comment why we're exporting aliases. --- stl/inc/exception | 1 + stl/inc/new | 2 ++ stl/inc/typeinfo | 2 ++ 3 files changed, 5 insertions(+) diff --git a/stl/inc/exception b/stl/inc/exception index 051d2f2dbf..10fd907ec9 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -35,6 +35,7 @@ _STD_END _STD_BEGIN +// Follow N4971 [module.interface]/6 by exporting aliases: _EXPORT_STD using exception = exception; _EXPORT_STD using bad_exception = bad_exception; diff --git a/stl/inc/new b/stl/inc/new index fce313935f..4dc8b48d7a 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -38,6 +38,7 @@ _EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, const _STD noth #ifdef __cpp_aligned_new _STD_BEGIN +// Follow N4971 [module.interface]/6 by exporting aliases: _EXPORT_STD using align_val_t = align_val_t; _STD_END @@ -65,6 +66,7 @@ _EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept _STD_BEGIN #if _HAS_EXCEPTIONS +// Follow N4971 [module.interface]/6 by exporting aliases: _EXPORT_STD using bad_alloc = bad_alloc; _EXPORT_STD using bad_array_new_length = bad_array_new_length; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv diff --git a/stl/inc/typeinfo b/stl/inc/typeinfo index 662bc41433..cd46f32992 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -23,6 +23,7 @@ _STL_DISABLE_CLANG_WARNINGS #include #pragma pop_macro("raw_name") +// Follow N4971 [module.interface]/6 by exporting aliases: _EXPORT_STD using type_info = type_info; // for typeid, MSVC looks for type_info in the global namespace _STD_BEGIN @@ -33,6 +34,7 @@ _INLINE_VAR constexpr int _Small_object_num_ptrs = 6 + 16 / sizeof(void*); _EXPORT_STD using ::type_info; #if _HAS_EXCEPTIONS +// Follow N4971 [module.interface]/6 by exporting aliases: _EXPORT_STD using bad_cast = bad_cast; _EXPORT_STD using bad_typeid = bad_typeid; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv From dd9b6ee64c3921c91ed99a9fb3429330dc47cd41 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 14:43:50 -0800 Subject: [PATCH 06/11] Rework how we mirror ``. `` includes ``. If it emits an upcoming macro `_EXPORT_VCR`, we'll assume that VCRuntime has been updated to export its own machinery. --- stl/inc/new | 47 ------------------------------ stl/modules/std.ixx | 69 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 56 deletions(-) diff --git a/stl/inc/new b/stl/inc/new index 4dc8b48d7a..fa09696272 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -17,53 +17,6 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -#ifdef _BUILD_STD_MODULE -#pragma warning(push) -#pragma warning(disable : 28251) // Inconsistent annotation for 'new': this instance has no annotations. - -// Mirroring declarations: - -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( - size_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( - size_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, const _STD nothrow_t&) noexcept; - -#ifdef __cpp_aligned_new -_STD_BEGIN -// Follow N4971 [module.interface]/6 by exporting aliases: -_EXPORT_STD using align_val_t = align_val_t; -_STD_END - -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( - size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, _STD align_val_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( - size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t, const _STD nothrow_t&) noexcept; -#endif // defined(__cpp_aligned_new) - -_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new(size_t, void*) noexcept; -_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new[](size_t, void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept; - -#pragma warning(pop) -#endif // defined(_BUILD_STD_MODULE) - _STD_BEGIN #if _HAS_EXCEPTIONS // Follow N4971 [module.interface]/6 by exporting aliases: diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 1c6a0ebf62..446aa39ff4 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -7,12 +7,6 @@ module; // This named module expects to be built with classic headers, not header units. #define _BUILD_STD_MODULE -// N4971 [module.interface]/6: "A redeclaration of an entity X is implicitly exported -// if X was introduced by an exported declaration; otherwise it shall not be exported." -// Therefore, we'll need to introduce the `nothrow` object with an exported declaration, -// instead of allowing to declare it. -#define __NOTHROW_T_DEFINED - // The subset of "C headers" [tab:c.headers] corresponding to // the "C++ headers for C library facilities" [tab:headers.cpp.c] #include @@ -43,15 +37,72 @@ export module std; #pragma warning(disable : 5244) // '#include ' in the purview of module 'std' appears erroneous. #include +#ifndef _EXPORT_VCR // TRANSITION, VCRuntime update expected in 17.10 Preview 3 + +// N4971 [module.interface]/6: "A redeclaration of an entity X is implicitly exported +// if X was introduced by an exported declaration; otherwise it shall not be exported." + +// Therefore, we'll need to introduce exported declarations of machinery before including it. + #pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + _STD_BEGIN -_EXPORT_STD extern "C++" struct nothrow_t { - explicit nothrow_t() = default; -}; +_EXPORT_STD extern "C++" struct nothrow_t; + _EXPORT_STD extern "C++" const nothrow_t nothrow; + +#ifdef __cpp_aligned_new +_EXPORT_STD extern "C++" enum class align_val_t : size_t; +#endif // ^^^ defined(__cpp_aligned_new) ^^^ _STD_END + +#pragma warning(disable : 28251) // Inconsistent annotation for 'new': this instance has no annotations. + +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( + size_t, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t); +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( + size_t, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, const _STD nothrow_t&) noexcept; + +#ifdef __cpp_aligned_new +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( + size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, _STD align_val_t); +_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( + size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t, _STD align_val_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t, const _STD nothrow_t&) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t, _STD align_val_t) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t, const _STD nothrow_t&) noexcept; +#endif // ^^^ defined(__cpp_aligned_new) ^^^ + +_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new(size_t, void*) noexcept; +_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new[](size_t, void*) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, void*) noexcept; +_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept; + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) #pragma pack(pop) +#endif // ^^^ workaround ^^^ + // "C++ library headers" [tab:headers.cpp] #include #if _HAS_STATIC_RTTI From 22a372af66b507738004c016dc8a8d790faaec31 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 14:53:30 -0800 Subject: [PATCH 07/11] `std.ixx` can directly `export`, no need for the `_EXPORT_STD` macro. --- stl/modules/std.ixx | 56 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 446aa39ff4..5dccc8d12a 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -52,49 +52,47 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN -_EXPORT_STD extern "C++" struct nothrow_t; +export extern "C++" struct nothrow_t; -_EXPORT_STD extern "C++" const nothrow_t nothrow; +export extern "C++" const nothrow_t nothrow; #ifdef __cpp_aligned_new -_EXPORT_STD extern "C++" enum class align_val_t : size_t; +export extern "C++" enum class align_val_t : size_t; #endif // ^^^ defined(__cpp_aligned_new) ^^^ _STD_END #pragma warning(disable : 28251) // Inconsistent annotation for 'new': this instance has no annotations. -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( - size_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( - size_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t); +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete(void*) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, size_t) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, size_t) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, const _STD nothrow_t&) noexcept; #ifdef __cpp_aligned_new -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, _STD align_val_t); -_EXPORT_STD extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, _STD align_val_t); +export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, size_t, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t, const _STD nothrow_t&) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, size_t, _STD align_val_t) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, size_t, _STD align_val_t) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, size_t, _STD align_val_t) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t, const _STD nothrow_t&) noexcept; #endif // ^^^ defined(__cpp_aligned_new) ^^^ -_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new(size_t, void*) noexcept; -_EXPORT_STD extern "C++" _NODISCARD void* __CRTDECL operator new[](size_t, void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete(void*, void*) noexcept; -_EXPORT_STD extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept; +export extern "C++" _NODISCARD void* __CRTDECL operator new(size_t, void*) noexcept; +export extern "C++" _NODISCARD void* __CRTDECL operator new[](size_t, void*) noexcept; +export extern "C++" void __CRTDECL operator delete(void*, void*) noexcept; +export extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept; #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS From 79a8d8aacc7dfd20b7705e3943b92ab00121bdf0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 15:24:09 -0800 Subject: [PATCH 08/11] Replicate ``'s SAL annotations. `NULL` is unfortunately necessary to avoid warnings C28252 and C28253 "Inconsistent annotation for 'new'". --- stl/modules/std.ixx | 65 +++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 5dccc8d12a..7165890c8d 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -61,36 +61,49 @@ export extern "C++" enum class align_val_t : size_t; #endif // ^^^ defined(__cpp_aligned_new) ^^^ _STD_END -#pragma warning(disable : 28251) // Inconsistent annotation for 'new': this instance has no annotations. - -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t); -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, const _STD nothrow_t&) noexcept; -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t); -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, const _STD nothrow_t&) noexcept; -export extern "C++" void __CRTDECL operator delete(void*) noexcept; -export extern "C++" void __CRTDECL operator delete(void*, size_t) noexcept; -export extern "C++" void __CRTDECL operator delete(void*, const _STD nothrow_t&) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*, size_t) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) +_VCRT_ALLOCATOR void* __CRTDECL operator new(size_t _Size); +export extern "C++" _NODISCARD _Ret_maybenull_ _Success_(return != NULL) + _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR void* __CRTDECL + operator new(size_t _Size, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) +_VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t _Size); +export extern "C++" _NODISCARD _Ret_maybenull_ _Success_(return != NULL) + _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR void* __CRTDECL + operator new[](size_t _Size, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block, size_t _Size) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete[](void* _Block) noexcept; +export extern "C++" void __CRTDECL operator delete[](void* _Block, size_t _Size) noexcept; +export extern "C++" void __CRTDECL operator delete[](void* _Block, const _STD nothrow_t&) noexcept; #ifdef __cpp_aligned_new -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new(size_t, _STD align_val_t); -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new( - size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t, _STD align_val_t); -export extern "C++" _NODISCARD _VCRT_ALLOCATOR void* __CRTDECL operator new[]( - size_t, _STD align_val_t, const _STD nothrow_t&) noexcept; -export extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t) noexcept; -export extern "C++" void __CRTDECL operator delete(void*, size_t, _STD align_val_t) noexcept; -export extern "C++" void __CRTDECL operator delete(void*, _STD align_val_t, const _STD nothrow_t&) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*, size_t, _STD align_val_t) noexcept; -export extern "C++" void __CRTDECL operator delete[](void*, _STD align_val_t, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) +_VCRT_ALLOCATOR void* __CRTDECL operator new(size_t _Size, _STD align_val_t _Al); +export extern "C++" _NODISCARD _Ret_maybenull_ _Success_(return != NULL) + _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR void* __CRTDECL + operator new(size_t _Size, _STD align_val_t _Al, const _STD nothrow_t&) noexcept; +export extern "C++" _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) +_VCRT_ALLOCATOR void* __CRTDECL operator new[](size_t _Size, _STD align_val_t _Al); +export extern "C++" _NODISCARD _Ret_maybenull_ _Success_(return != NULL) + _Post_writable_byte_size_(_Size) _VCRT_ALLOCATOR void* __CRTDECL + operator new[](size_t _Size, _STD align_val_t _Al, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block, _STD align_val_t _Al) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block, size_t _Size, _STD align_val_t _Al) noexcept; +export extern "C++" void __CRTDECL operator delete(void* _Block, _STD align_val_t _Al, const _STD nothrow_t&) noexcept; +export extern "C++" void __CRTDECL operator delete[](void* _Block, _STD align_val_t _Al) noexcept; +export extern "C++" void __CRTDECL operator delete[](void* _Block, size_t _Size, _STD align_val_t _Al) noexcept; +export extern "C++" void __CRTDECL operator delete[]( + void* _Block, _STD align_val_t _Al, const _STD nothrow_t&) noexcept; #endif // ^^^ defined(__cpp_aligned_new) ^^^ -export extern "C++" _NODISCARD void* __CRTDECL operator new(size_t, void*) noexcept; -export extern "C++" _NODISCARD void* __CRTDECL operator new[](size_t, void*) noexcept; +export extern "C++" _NODISCARD _MSVC_CONSTEXPR _Ret_notnull_ _Post_writable_byte_size_(_Size) + _Post_satisfies_(return == _Where) void* __CRTDECL + operator new(size_t _Size, _Writable_bytes_(_Size) void* _Where) noexcept; +export extern "C++" _NODISCARD _Ret_notnull_ _Post_writable_byte_size_(_Size) + _Post_satisfies_(return == _Where) void* __CRTDECL + operator new[](size_t _Size, _Writable_bytes_(_Size) void* _Where) noexcept; export extern "C++" void __CRTDECL operator delete(void*, void*) noexcept; export extern "C++" void __CRTDECL operator delete[](void*, void*) noexcept; From ab7825272d9fcb6b31b713e703c89e6944efbf7a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 15:35:23 -0800 Subject: [PATCH 09/11] MOAR CITATIONS --- stl/inc/exception | 2 +- stl/inc/new | 2 +- stl/inc/typeinfo | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/exception b/stl/inc/exception index 10fd907ec9..5db9285b47 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -35,7 +35,7 @@ _STD_END _STD_BEGIN -// Follow N4971 [module.interface]/6 by exporting aliases: +// Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using exception = exception; _EXPORT_STD using bad_exception = bad_exception; diff --git a/stl/inc/new b/stl/inc/new index fa09696272..04a7795707 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -19,7 +19,7 @@ _STL_DISABLE_CLANG_WARNINGS _STD_BEGIN #if _HAS_EXCEPTIONS -// Follow N4971 [module.interface]/6 by exporting aliases: +// Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using bad_alloc = bad_alloc; _EXPORT_STD using bad_array_new_length = bad_array_new_length; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv diff --git a/stl/inc/typeinfo b/stl/inc/typeinfo index cd46f32992..790a9663ab 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -23,7 +23,7 @@ _STL_DISABLE_CLANG_WARNINGS #include #pragma pop_macro("raw_name") -// Follow N4971 [module.interface]/6 by exporting aliases: +// Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using type_info = type_info; // for typeid, MSVC looks for type_info in the global namespace _STD_BEGIN @@ -34,7 +34,7 @@ _INLINE_VAR constexpr int _Small_object_num_ptrs = 6 + 16 / sizeof(void*); _EXPORT_STD using ::type_info; #if _HAS_EXCEPTIONS -// Follow N4971 [module.interface]/6 by exporting aliases: +// Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using bad_cast = bad_cast; _EXPORT_STD using bad_typeid = bad_typeid; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv From 8f5f0af193933215170bcf96bca87d66b0bf2059 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 8 Feb 2024 15:56:57 -0800 Subject: [PATCH 10/11] `_EXPORT_VCR` => `_VCRT_EXPORT_STD` --- stl/modules/std.ixx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 7165890c8d..df760d7b26 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -37,7 +37,7 @@ export module std; #pragma warning(disable : 5244) // '#include ' in the purview of module 'std' appears erroneous. #include -#ifndef _EXPORT_VCR // TRANSITION, VCRuntime update expected in 17.10 Preview 3 +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 // N4971 [module.interface]/6: "A redeclaration of an entity X is implicitly exported // if X was introduced by an exported declaration; otherwise it shall not be exported." From 5018d329e2bad0dc78a57863a788b5bc7a98e083 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 9 Feb 2024 09:12:47 -0800 Subject: [PATCH 11/11] Use `#ifndef _VCRT_EXPORT_STD` to wrap machinery that VCRuntime will export. --- stl/inc/exception | 2 ++ stl/inc/new | 2 ++ stl/inc/typeinfo | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/stl/inc/exception b/stl/inc/exception index 5db9285b47..6f614dffc0 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -35,9 +35,11 @@ _STD_END _STD_BEGIN +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 // Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using exception = exception; _EXPORT_STD using bad_exception = bad_exception; +#endif // ^^^ workaround ^^^ _EXPORT_STD using ::terminate; diff --git a/stl/inc/new b/stl/inc/new index 04a7795707..1ea651bea7 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -18,6 +18,7 @@ _STL_DISABLE_CLANG_WARNINGS #undef new _STD_BEGIN +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 #if _HAS_EXCEPTIONS // Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using bad_alloc = bad_alloc; @@ -25,6 +26,7 @@ _EXPORT_STD using bad_array_new_length = bad_array_new_length; #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv // exports bad_alloc and bad_array_new_length. #endif // ^^^ !_HAS_EXCEPTIONS ^^^ +#endif // ^^^ workaround ^^^ #if _HAS_CXX20 _EXPORT_STD struct destroying_delete_t { diff --git a/stl/inc/typeinfo b/stl/inc/typeinfo index 790a9663ab..1f9628652e 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -23,20 +23,26 @@ _STL_DISABLE_CLANG_WARNINGS #include #pragma pop_macro("raw_name") +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 // Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using type_info = type_info; // for typeid, MSVC looks for type_info in the global namespace +#endif // ^^^ workaround ^^^ _STD_BEGIN // size in pointers of std::function and std::any (roughly 3 pointers larger than std::string when building debug) _INLINE_VAR constexpr int _Small_object_num_ptrs = 6 + 16 / sizeof(void*); +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 _EXPORT_STD using ::type_info; +#endif // ^^^ workaround ^^^ #if _HAS_EXCEPTIONS +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 // Follow N4971 [module.interface]/6 by exporting aliases (a type alias is not an entity, N4971 [basic.pre]/3): _EXPORT_STD using bad_cast = bad_cast; _EXPORT_STD using bad_typeid = bad_typeid; +#endif // ^^^ workaround ^^^ #else // ^^^ _HAS_EXCEPTIONS / !_HAS_EXCEPTIONS vvv _EXPORT_STD class bad_cast : public exception { // base of all bad cast exceptions public: