[libcxx] r315234 - [libc++] Support Microsoft ABI without vcruntime headers

Shoaib Meenai via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 9 12:25:17 PDT 2017


Author: smeenai
Date: Mon Oct  9 12:25:17 2017
New Revision: 315234

URL: http://llvm.org/viewvc/llvm-project?rev=315234&view=rev
Log:
[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

Modified:
    libcxx/trunk/CMakeLists.txt
    libcxx/trunk/docs/UsingLibcxx.rst
    libcxx/trunk/include/__config_site.in
    libcxx/trunk/include/exception
    libcxx/trunk/include/new
    libcxx/trunk/src/new.cpp
    libcxx/trunk/src/support/runtime/exception_msvc.ipp
    libcxx/trunk/src/support/runtime/exception_pointer_msvc.ipp
    libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
    libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
    libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
    libcxx/trunk/utils/libcxx/test/config.py

Modified: libcxx/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/CMakeLists.txt?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/CMakeLists.txt (original)
+++ libcxx/trunk/CMakeLists.txt Mon Oct  9 12:25:17 2017
@@ -615,6 +615,7 @@ config_define_if(LIBCXX_HAS_PTHREAD_API
 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)

Modified: libcxx/trunk/docs/UsingLibcxx.rst
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/docs/UsingLibcxx.rst?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/docs/UsingLibcxx.rst (original)
+++ libcxx/trunk/docs/UsingLibcxx.rst Mon Oct  9 12:25:17 2017
@@ -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**:

Modified: libcxx/trunk/include/__config_site.in
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config_site.in?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/include/__config_site.in (original)
+++ libcxx/trunk/include/__config_site.in Mon Oct  9 12:25:17 2017
@@ -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@
 

Modified: libcxx/trunk/include/exception
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/exception?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/include/exception (original)
+++ libcxx/trunk/include/exception Mon Oct  9 12:25:17 2017
@@ -82,7 +82,7 @@ template <class E> void rethrow_if_neste
 #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_neste
 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) \

Modified: libcxx/trunk/include/new
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/new?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/include/new (original)
+++ libcxx/trunk/include/new Mon Oct  9 12:25:17 2017
@@ -92,7 +92,7 @@ void  operator delete[](void* ptr, void*
 #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*
 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 = (
 #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* o
 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
 

Modified: libcxx/trunk/src/new.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/new.cpp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/src/new.cpp (original)
+++ libcxx/trunk/src/new.cpp Mon Oct  9 12:25:17 2017
@@ -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, st
 }
 
 #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

Modified: libcxx/trunk/src/support/runtime/exception_msvc.ipp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/support/runtime/exception_msvc.ipp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/src/support/runtime/exception_msvc.ipp (original)
+++ libcxx/trunk/src/support/runtime/exception_msvc.ipp Mon Oct  9 12:25:17 2017
@@ -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

Modified: libcxx/trunk/src/support/runtime/exception_pointer_msvc.ipp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/support/runtime/exception_pointer_msvc.ipp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/src/support/runtime/exception_pointer_msvc.ipp (original)
+++ libcxx/trunk/src/support/runtime/exception_pointer_msvc.ipp Mon Oct  9 12:25:17 2017
@@ -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 {
 

Modified: libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_nothrow_replace.pass.cpp Mon Oct  9 12:25:17 2017
@@ -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>

Modified: libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.array/new_array_replace.pass.cpp Mon Oct  9 12:25:17 2017
@@ -10,6 +10,7 @@
 // test operator new[] replacement by replacing only operator new
 
 // UNSUPPORTED: sanitizer-new-delete
+// XFAIL: libcpp-no-vcruntime
 
 
 #include <new>

Modified: libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp (original)
+++ libcxx/trunk/test/std/language.support/support.dynamic/new.delete/new.delete.single/new_nothrow_replace.pass.cpp Mon Oct  9 12:25:17 2017
@@ -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>

Modified: libcxx/trunk/utils/libcxx/test/config.py
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/utils/libcxx/test/config.py?rev=315234&r1=315233&r2=315234&view=diff
==============================================================================
--- libcxx/trunk/utils/libcxx/test/config.py (original)
+++ libcxx/trunk/utils/libcxx/test/config.py Mon Oct  9 12:25:17 2017
@@ -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)




More information about the cfe-commits mailing list