diff --git a/stl/inc/exception b/stl/inc/exception index bb34e333cf..6f614dffc0 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -35,8 +35,11 @@ _STD_END _STD_BEGIN -_EXPORT_STD class exception; -_EXPORT_STD class bad_exception; +#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 6b6a8164e3..1ea651bea7 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -17,70 +17,16 @@ _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: - -_STD_BEGIN -_EXPORT_STD extern "C++" struct 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; -_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 -#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 ^^^ -_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 +#ifndef _VCRT_EXPORT_STD // TRANSITION, VCRuntime update expected in 17.10 Preview 3 #if _HAS_EXCEPTIONS -_EXPORT_STD class bad_alloc; -_EXPORT_STD class bad_array_new_length; +// 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 // 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 de903e92e1..1f9628652e 100644 --- a/stl/inc/typeinfo +++ b/stl/inc/typeinfo @@ -23,18 +23,26 @@ _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 +#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 -_EXPORT_STD class bad_cast; -_EXPORT_STD class bad_typeid; +#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: diff --git a/stl/modules/std.ixx b/stl/modules/std.ixx index 7a5fdbf7ce..df760d7b26 100644 --- a/stl/modules/std.ixx +++ b/stl/modules/std.ixx @@ -36,6 +36,84 @@ export module std; #pragma warning(push) #pragma warning(disable : 5244) // '#include ' in the purview of module 'std' appears erroneous. +#include +#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." + +// 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 extern "C++" struct nothrow_t; + +export extern "C++" const nothrow_t nothrow; + +#ifdef __cpp_aligned_new +export extern "C++" enum class align_val_t : size_t; +#endif // ^^^ defined(__cpp_aligned_new) ^^^ +_STD_END + +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 _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 _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; + +#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 diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index ae0e81eda4..2f8038a0fd 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,12 @@ void test_mutex() { void test_new() { using namespace std; puts("Testing ."); + + 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; try { @@ -988,6 +998,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);