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

Reply via email to