Skip to content

Commit

Permalink
Export VCRuntime entities properly (#4375)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanTLavavej authored Feb 12, 2024
1 parent 192a840 commit 7d5d8c3
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 64 deletions.
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;
#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
#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.

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

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

0 comments on commit 7d5d8c3

Please sign in to comment.