Skip to content
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

Export VCRuntime entities properly #4375

Merged
merged 11 commits into from
Feb 12, 2024
7 changes: 5 additions & 2 deletions stl/inc/exception
Original file line number Diff line number Diff line change
Expand Up @@ -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;
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
#endif // ^^^ workaround ^^^

_EXPORT_STD using ::terminate;

Expand Down
64 changes: 5 additions & 59 deletions stl/inc/new
Original file line number Diff line number Diff line change
Expand Up @@ -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 <vcruntime_new.h> 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
// <exception> exports bad_alloc and bad_array_new_length.
#endif // ^^^ !_HAS_EXCEPTIONS ^^^
#endif // ^^^ workaround ^^^

#if _HAS_CXX20
_EXPORT_STD struct destroying_delete_t {
Expand Down
14 changes: 11 additions & 3 deletions stl/inc/typeinfo
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,26 @@ _STL_DISABLE_CLANG_WARNINGS
#include <vcruntime_typeinfo.h>
#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
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
#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:
Expand Down
78 changes: 78 additions & 0 deletions stl/modules/std.ixx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,84 @@ export module std;
#pragma warning(push)
#pragma warning(disable : 5244) // '#include <meow>' in the purview of module 'std' appears erroneous.

#include <yvals_core.h>
#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 <vcruntime_new.h> machinery before including it.
Copy link
Contributor

Choose a reason for hiding this comment

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

Mega nitpick (not worth resetting testing):

Suggested change
// Therefore, we'll need to introduce exported declarations of <vcruntime_new.h> machinery before including it.
// Therefore, we need to introduce exported declarations of <vcruntime_new.h> machinery before including it.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, I can handle this in a followup. This code is destined to be removed after the 17.10p3 toolset update anyways.


#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;
Copy link
Contributor

Choose a reason for hiding this comment

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

The #ifdef __EDG__ // TRANSITION, VSO-1618988 workaround has gone missing. Is it not needed since the std module is always built with C1XX?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's correct.

#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 <algorithm>
#if _HAS_STATIC_RTTI
Expand Down
15 changes: 15 additions & 0 deletions tests/std/include/test_header_units_and_modules.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ void test_deque() {
void test_exception() {
using namespace std;
puts("Testing <exception>.");

static_assert(is_class_v<exception>);
static_assert(is_class_v<bad_exception>);

assert(uncaught_exceptions() == 0);
const exception_ptr ep = current_exception();
assert(!ep);
Expand Down Expand Up @@ -471,6 +475,12 @@ void test_mutex() {
void test_new() {
using namespace std;
puts("Testing <new>.");

static_assert(is_class_v<bad_alloc>);
static_assert(is_class_v<bad_array_new_length>);
static_assert(is_same_v<underlying_type_t<align_val_t>, size_t>);
static_assert(is_class_v<nothrow_t>);
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved

bool caught_bad_alloc = false;

try {
Expand Down Expand Up @@ -988,6 +998,11 @@ void test_typeindex() {
void test_typeinfo() {
using namespace std;
puts("Testing <typeinfo>.");

static_assert(is_class_v<type_info>);
static_assert(is_class_v<bad_cast>);
static_assert(is_class_v<bad_typeid>);

const type_info& t1 = typeid(int);
const type_info& t2 = typeid(const int&);
const type_info& t3 = typeid(double);
Expand Down
Loading