diff --git a/libcxx/src/include/refstring.h b/libcxx/src/include/refstring.h index e464b79ba89c0a..cefd7caf0f2087 100644 --- a/libcxx/src/include/refstring.h +++ b/libcxx/src/include/refstring.h @@ -13,12 +13,25 @@ #include #include #include -#ifdef __APPLE__ -#include -#include -#endif #include "atomic_support.h" +// MacOS and iOS used to ship with libstdc++, and still support old applications +// linking against libstdc++. The libc++ and libstdc++ exceptions are supposed +// to be ABI compatible, such that they can be thrown from one library and caught +// in the other. +// +// For that reason, we must look for libstdc++ in the same process and if found, +// check the string stored in the exception object to see if it is the GCC empty +// string singleton before manipulating the reference count. This is done so that +// if an exception is created with a zero-length string in libstdc++, libc++abi +// won't try to delete the memory. +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \ + defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +# define _LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE +# include +# include +#endif + _LIBCPP_BEGIN_NAMESPACE_STD namespace __refstring_imp { namespace { @@ -40,7 +53,7 @@ inline char * data_from_rep(_Rep_base *rep) noexcept { return data + sizeof(*rep); } -#if defined(__APPLE__) +#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) inline const char* compute_gcc_empty_string_storage() _NOEXCEPT { @@ -115,7 +128,7 @@ __libcpp_refstring::~__libcpp_refstring() { inline bool __libcpp_refstring::__uses_refcount() const { -#ifdef __APPLE__ +#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) return __imp_ != get_gcc_empty_string_storage(); #else return true;