forked from OSchip/llvm-project
[libc++] Support Microsoft ABI without vcruntime headers
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. Certain operator new/delete replacement scenarios are not currently supported in this mode, which requires some tests to be marked XFAIL. The added documentation has more details. Differential Revision: https://reviews.llvm.org/D38522 llvm-svn: 315234
This commit is contained in:
parent
6ab4d075ff
commit
492d7134f3
|
@ -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)
|
||||
|
|
|
@ -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**:
|
||||
|
|
|
@ -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@
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// test operator new[] replacement by replacing only operator new
|
||||
|
||||
// UNSUPPORTED: sanitizer-new-delete
|
||||
// XFAIL: libcpp-no-vcruntime
|
||||
|
||||
|
||||
#include <new>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue