smeenai created this revision. Herald added a subscriber: mgorny. The vcruntime headers are hairy and clash with both libc++ headers themselves and other libraries. libc++ normally deals with the clashes by deferring to the vcruntime headers and silencing its own definitions, but for clients which don't want to depend on vcruntime headers, it's desirable to support the opposite, i.e. have libc++ provide its own definitions.
https://reviews.llvm.org/D38522 Files: CMakeLists.txt docs/UsingLibcxx.rst include/__config_site.in include/exception include/new src/new.cpp src/support/runtime/exception_msvc.ipp src/support/runtime/exception_pointer_msvc.ipp test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp utils/libcxx/test/config.py
Index: utils/libcxx/test/config.py =================================================================== --- utils/libcxx/test/config.py +++ utils/libcxx/test/config.py @@ -668,6 +668,9 @@ 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 == '_LIBCPP_ABI_UNSTABLE' m = m.lower()[1:].replace('_', '-') self.config.available_features.add(m) Index: test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp =================================================================== --- test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp +++ 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> Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp =================================================================== --- test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp +++ 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> Index: test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp =================================================================== --- test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp +++ 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> Index: src/support/runtime/exception_pointer_msvc.ipp =================================================================== --- src/support/runtime/exception_pointer_msvc.ipp +++ src/support/runtime/exception_pointer_msvc.ipp @@ -10,7 +10,14 @@ #include <stdio.h> #include <stdlib.h> -#include <yvals.h> // for _CRTIMP2_PURE + +#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(_Out_ void*); _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL __ExceptionPtrDestroy(_Inout_ void*); Index: src/support/runtime/exception_msvc.ipp =================================================================== --- src/support/runtime/exception_msvc.ipp +++ 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( + _In_opt_ terminate_handler _NewTerminateHandler) throw(); +_ACRTIMP terminate_handler __cdecl _get_terminate(); + +typedef void(__CRTDECL* unexpected_handler)(); +_VCRTIMP unexpected_handler __cdecl set_unexpected( + _In_opt_ 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 @@ 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 Index: src/new.cpp =================================================================== --- src/new.cpp +++ 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 @@ } // 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 @@ } #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 Index: include/new =================================================================== --- include/new +++ include/new @@ -92,7 +92,7 @@ #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 @@ 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 @@ _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 @@ #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 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 Index: include/exception =================================================================== --- include/exception +++ include/exception @@ -82,7 +82,7 @@ #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 @@ 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 @@ 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) \ Index: include/__config_site.in =================================================================== --- include/__config_site.in +++ include/__config_site.in @@ -23,5 +23,6 @@ #cmakedefine _LIBCPP_HAS_THREAD_API_EXTERNAL #cmakedefine _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL #cmakedefine _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS +#cmakedefine _LIBCPP_NO_VCRUNTIME #endif // _LIBCPP_CONFIG_SITE Index: docs/UsingLibcxx.rst =================================================================== --- docs/UsingLibcxx.rst +++ docs/UsingLibcxx.rst @@ -185,6 +185,26 @@ * 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**: Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -606,6 +606,7 @@ 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) # By default libc++ on Windows expects to use a shared library, which requires # the headers to use DLL import/export semantics. However when building a
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits