diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | docs/UsingLibcxx.rst | 20 | ||||
-rw-r--r-- | include/__config_site.in | 1 | ||||
-rw-r--r-- | include/exception | 6 | ||||
-rw-r--r-- | include/new | 10 | ||||
-rw-r--r-- | src/new.cpp | 9 | ||||
-rw-r--r-- | src/support/runtime/exception_msvc.ipp | 79 | ||||
-rw-r--r-- | src/support/runtime/exception_pointer_msvc.ipp | 32 | ||||
-rw-r--r-- | test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp | 1 | ||||
-rw-r--r-- | test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp | 1 | ||||
-rw-r--r-- | test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp | 1 | ||||
-rw-r--r-- | utils/libcxx/test/config.py | 3 |
12 files changed, 137 insertions, 27 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f87711c7..f0c4d1efb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -615,6 +615,7 @@ config_define_if(LIBCXX_HAS_PTHREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD) config_define_if(LIBCXX_HAS_EXTERNAL_THREAD_API _LIBCPP_HAS_THREAD_API_EXTERNAL) config_define_if(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC) +config_define_if(LIBCXX_NO_VCRUNTIME _LIBCPP_NO_VCRUNTIME) if (LIBCXX_ABI_DEFINES) set(abi_defines) diff --git a/docs/UsingLibcxx.rst b/docs/UsingLibcxx.rst index 183664655..f54234d6a 100644 --- a/docs/UsingLibcxx.rst +++ b/docs/UsingLibcxx.rst @@ -185,6 +185,26 @@ thread safety annotations. * Giving `set`, `map`, `multiset`, `multimap` a comparator which is not const callable. +**_LIBCPP_NO_VCRUNTIME**: + Microsoft's C and C++ headers are fairly entangled, and some of their C++ + headers are fairly hard to avoid. In particular, `vcruntime_new.h` gets pulled + in from a lot of other headers and provides definitions which clash with + libc++ headers, such as `nothrow_t` (note that `nothrow_t` is a struct, so + there's no way for libc++ to provide a compatible definition, since you can't + have multiple definitions). + + By default, libc++ solves this problem by deferring to Microsoft's vcruntime + headers where needed. However, it may be undesirable to depend on vcruntime + headers, since they may not always be available in cross-compilation setups, + or they may clash with other headers. The `_LIBCPP_NO_VCRUNTIME` macro + prevents libc++ from depending on vcruntime headers. Consequently, it also + prevents libc++ headers from being interoperable with vcruntime headers (from + the aforementioned clashes), so users of this macro are promising to not + attempt to combine libc++ headers with the problematic vcruntime headers. This + macro also currently prevents certain `operator new`/`operator delete` + replacement scenarios from working, e.g. replacing `operator new` and + expecting a non-replaced `operator new[]` to call the replaced `operator new`. + C++17 Specific Configuration Macros ----------------------------------- **_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES**: diff --git a/include/__config_site.in b/include/__config_site.in index b2c9d6307..86418a3e1 100644 --- a/include/__config_site.in +++ b/include/__config_site.in @@ -25,6 +25,7 @@ #cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL #cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL #cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS +#cmakedefine _LIBCPP_NO_VCRUNTIME @_LIBCPP_ABI_DEFINES@ diff --git a/include/exception b/include/exception index ca2eaf5c6..79bd6ac2a 100644 --- a/include/exception +++ b/include/exception @@ -82,7 +82,7 @@ template <class E> void rethrow_if_nested(const E& e); #include <cstdlib> #include <type_traits> -#if defined(_LIBCPP_ABI_MICROSOFT) +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) #include <vcruntime_exception.h> #endif @@ -93,7 +93,7 @@ template <class E> void rethrow_if_nested(const E& e); namespace std // purposefully not using versioning namespace { -#if !defined(_LIBCPP_ABI_MICROSOFT) +#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME) class _LIBCPP_EXCEPTION_ABI exception { public: @@ -110,7 +110,7 @@ public: virtual ~bad_exception() _NOEXCEPT; virtual const char* what() const _NOEXCEPT; }; -#endif // !_LIBCPP_ABI_MICROSOFT +#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME #if _LIBCPP_STD_VER <= 14 \ || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \ diff --git a/include/new b/include/new index 34df2efee..06cf4a3e1 100644 --- a/include/new +++ b/include/new @@ -92,7 +92,7 @@ void operator delete[](void* ptr, void*) noexcept; #include <cstdlib> #endif -#if defined(_LIBCPP_ABI_MICROSOFT) +#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) #include <new.h> #endif @@ -114,7 +114,7 @@ void operator delete[](void* ptr, void*) noexcept; namespace std // purposefully not using versioning namespace { -#if !defined(_LIBCPP_ABI_MICROSOFT) +#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME) struct _LIBCPP_TYPE_VIS nothrow_t {}; extern _LIBCPP_FUNC_VIS const nothrow_t nothrow; @@ -140,7 +140,7 @@ typedef void (*new_handler)(); _LIBCPP_FUNC_VIS new_handler set_new_handler(new_handler) _NOEXCEPT; _LIBCPP_FUNC_VIS new_handler get_new_handler() _NOEXCEPT; -#endif // !_LIBCPP_ABI_MICROSOFT +#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_bad_alloc(); // not in C++ spec @@ -174,7 +174,7 @@ enum align_val_t { __zero = 0, __max = (size_t)-1 }; #define _THROW_BAD_ALLOC #endif -#if !defined(_LIBCPP_ABI_MICROSOFT) +#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME) _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz) _THROW_BAD_ALLOC; _LIBCPP_OVERRIDABLE_FUNC_VIS void* operator new(std::size_t __sz, const std::nothrow_t&) _NOEXCEPT _NOALIAS; @@ -215,7 +215,7 @@ inline _LIBCPP_INLINE_VISIBILITY void* operator new[](std::size_t, void* __p) _N inline _LIBCPP_INLINE_VISIBILITY void operator delete (void*, void*) _NOEXCEPT {} inline _LIBCPP_INLINE_VISIBILITY void operator delete[](void*, void*) _NOEXCEPT {} -#endif // !_LIBCPP_ABI_MICROSOFT +#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/src/new.cpp b/src/new.cpp index 01df25121..e228a0d83 100644 --- a/src/new.cpp +++ b/src/new.cpp @@ -15,7 +15,9 @@ #include "include/atomic_support.h" #if defined(_LIBCPP_ABI_MICROSOFT) -// nothing todo +#if defined(_LIBCPP_NO_VCRUNTIME) +#include "support/runtime/new_handler_fallback.ipp" +#endif #elif defined(LIBCXX_BUILDING_LIBCXXABI) #include <cxxabi.h> #elif defined(LIBCXXRT) @@ -54,7 +56,8 @@ __throw_bad_alloc() } // std -#if !defined(__GLIBCXX__) && !defined(_LIBCPP_ABI_MICROSOFT) && \ +#if !defined(__GLIBCXX__) && \ + (!defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)) && \ !defined(_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS) // Implement all new and delete operators as weak definitions @@ -300,4 +303,4 @@ operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT } #endif // !_LIBCPP_HAS_NO_ALIGNED_ALLOCATION -#endif // !__GLIBCXX__ && !_LIBCPP_ABI_MICROSOFT && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS +#endif // !__GLIBCXX__ && (!_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME) && !_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS diff --git a/src/support/runtime/exception_msvc.ipp b/src/support/runtime/exception_msvc.ipp index 443961ebf..d5bf5b726 100644 --- a/src/support/runtime/exception_msvc.ipp +++ b/src/support/runtime/exception_msvc.ipp @@ -14,12 +14,35 @@ #include <stdio.h> #include <stdlib.h> -#include <eh.h> -#include <corecrt_terminate.h> + +#if !defined(_ACRTIMP) +#define _ACRTIMP __declspec(dllimport) +#endif + +#if !defined(_VCRTIMP) +#define _VCRTIMP __declspec(dllimport) +#endif + +#if !defined(__CRTDECL) +#define __CRTDECL __cdecl +#endif + +extern "C" { +typedef void (__CRTDECL* terminate_handler)(); +_ACRTIMP terminate_handler __cdecl set_terminate( + terminate_handler _NewTerminateHandler) throw(); +_ACRTIMP terminate_handler __cdecl _get_terminate(); + +typedef void (__CRTDECL* unexpected_handler)(); +_VCRTIMP unexpected_handler __cdecl set_unexpected( + unexpected_handler _NewUnexpectedHandler) throw(); +_VCRTIMP unexpected_handler __cdecl _get_unexpected(); + +_VCRTIMP int __cdecl __uncaught_exceptions(); +} namespace std { -// libcxxrt provides implementations of these functions itself. unexpected_handler set_unexpected(unexpected_handler func) _NOEXCEPT { return ::set_unexpected(func); @@ -114,4 +137,54 @@ bad_typeid::what() const _NOEXCEPT return "std::bad_typeid"; } +#if defined(_LIBCPP_NO_VCRUNTIME) +exception::~exception() _NOEXCEPT +{ +} + +const char* exception::what() const _NOEXCEPT +{ + return "std::exception"; +} + + +bad_exception::~bad_exception() _NOEXCEPT +{ +} + +const char* bad_exception::what() const _NOEXCEPT +{ + return "std::bad_exception"; +} + + +bad_alloc::bad_alloc() _NOEXCEPT +{ +} + +bad_alloc::~bad_alloc() _NOEXCEPT +{ +} + +const char* +bad_alloc::what() const _NOEXCEPT +{ + return "std::bad_alloc"; +} + +bad_array_new_length::bad_array_new_length() _NOEXCEPT +{ +} + +bad_array_new_length::~bad_array_new_length() _NOEXCEPT +{ +} + +const char* +bad_array_new_length::what() const _NOEXCEPT +{ + return "bad_array_new_length"; +} +#endif // _LIBCPP_NO_VCRUNTIME + } // namespace std diff --git a/src/support/runtime/exception_pointer_msvc.ipp b/src/support/runtime/exception_pointer_msvc.ipp index eab5d30a9..5ca7519a6 100644 --- a/src/support/runtime/exception_pointer_msvc.ipp +++ b/src/support/runtime/exception_pointer_msvc.ipp @@ -10,26 +10,32 @@ #include <stdio.h> #include <stdlib.h> -#include <yvals.h> // for _CRTIMP2_PURE -_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(_Out_ void*); -_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*); -_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCopy(_Out_ void*, - _In_ const void*); +#if !defined(_CRTIMP2_PURE) +#define _CRTIMP2_PURE __declspec(dllimport) +#endif + +#if !defined(__CLRCALL_PURE_OR_CDECL) +#define __CLRCALL_PURE_OR_CDECL __cdecl +#endif + +_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCreate(void*); +_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(void*); +_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrCopy(void*, + const void*); _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL -__ExceptionPtrAssign(_Inout_ void*, _In_ const void*); +__ExceptionPtrAssign(void*, const void*); _CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL -__ExceptionPtrCompare(_In_ const void*, _In_ const void*); +__ExceptionPtrCompare(const void*, const void*); _CRTIMP2_PURE bool __CLRCALL_PURE_OR_CDECL -__ExceptionPtrToBool(_In_ const void*); -_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrSwap(_Inout_ void*, - _Inout_ void*); +__ExceptionPtrToBool(const void*); +_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrSwap(void*, void*); _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL -__ExceptionPtrCurrentException(_Out_ void*); +__ExceptionPtrCurrentException(void*); [[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL -__ExceptionPtrRethrow(_In_ const void*); +__ExceptionPtrRethrow(const void*); _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL -__ExceptionPtrCopyException(_Inout_ void*, _In_ const void*, _In_ const void*); +__ExceptionPtrCopyException(void*, const void*, const void*); namespace std { diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp index 53e26c99f..ba3f930c5 100644 --- a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp +++ b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp @@ -10,6 +10,7 @@ // test operator new [] nothrow by replacing only operator new // UNSUPPORTED: sanitizer-new-delete +// XFAIL: libcpp-no-vcruntime #include <new> #include <cstddef> diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp index b0820b14f..3f8122745 100644 --- a/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp +++ b/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp @@ -10,6 +10,7 @@ // test operator new[] replacement by replacing only operator new // UNSUPPORTED: sanitizer-new-delete +// XFAIL: libcpp-no-vcruntime #include <new> diff --git a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp index dbc64bace..31e190151 100644 --- a/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp +++ b/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp @@ -10,6 +10,7 @@ // test operator new nothrow by replacing only operator new // UNSUPPORTED: sanitizer-new-delete +// XFAIL: libcpp-no-vcruntime #include <new> #include <cstddef> diff --git a/utils/libcxx/test/config.py b/utils/libcxx/test/config.py index 6f88a3540..67927c912 100644 --- a/utils/libcxx/test/config.py +++ b/utils/libcxx/test/config.py @@ -668,6 +668,9 @@ class Configuration(object): self.config.available_features.add('libcpp-abi-version-v%s' % feature_macros[m]) continue + if m == '_LIBCPP_NO_VCRUNTIME': + self.config.available_features.add('libcpp-no-vcruntime') + continue assert m.startswith('_LIBCPP_HAS_') or m.startswith('_LIBCPP_ABI_') m = m.lower()[1:].replace('_', '-') self.config.available_features.add(m) |