diff --git a/libcxx/include/stdexcept b/libcxx/include/stdexcept index 85e11629bd6e3..8082c4dc8b0fe 100644 --- a/libcxx/include/stdexcept +++ b/libcxx/include/stdexcept @@ -57,9 +57,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD # ifndef _LIBCPP_ABI_VCRUNTIME class _LIBCPP_HIDDEN __libcpp_refstring { - const char* __imp_; - - bool __uses_refcount() const; + struct __rep; + __rep* __imp_; public: explicit __libcpp_refstring(const char* __msg); @@ -67,7 +66,7 @@ public: __libcpp_refstring& operator=(const __libcpp_refstring& __s) _NOEXCEPT; ~__libcpp_refstring(); - _LIBCPP_HIDE_FROM_ABI const char* c_str() const _NOEXCEPT { return __imp_; } + _LIBCPP_HIDE_FROM_ABI const char* c_str() const _NOEXCEPT; }; # endif // !_LIBCPP_ABI_VCRUNTIME diff --git a/libcxx/src/include/refstring.h b/libcxx/src/include/refstring.h index 3e0ec7a97c7be..3c7c5cc5bbf1b 100644 --- a/libcxx/src/include/refstring.h +++ b/libcxx/src/include/refstring.h @@ -15,112 +15,43 @@ #include #include -// 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 { -typedef int count_t; +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc99-extensions") -struct _Rep_base { - std::size_t len; - std::size_t cap; - count_t count; +struct __libcpp_refstring::__rep { + ptrdiff_t refcount; + char data[]; }; -inline _Rep_base* rep_from_data(const char* data_) noexcept { - char* data = const_cast(data_); - return reinterpret_cast<_Rep_base*>(data - sizeof(_Rep_base)); -} - -inline char* data_from_rep(_Rep_base* rep) noexcept { - char* data = reinterpret_cast(rep); - return data + sizeof(*rep); -} - -#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) -inline const char* compute_gcc_empty_string_storage() noexcept { - void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); - if (handle == nullptr) - return nullptr; - void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); - if (sym == nullptr) - return nullptr; - return data_from_rep(reinterpret_cast<_Rep_base*>(sym)); -} - -inline const char* get_gcc_empty_string_storage() noexcept { - static const char* p = compute_gcc_empty_string_storage(); - return p; -} -#endif - -} // namespace -} // namespace __refstring_imp - -using namespace __refstring_imp; - inline __libcpp_refstring::__libcpp_refstring(const char* msg) { std::size_t len = strlen(msg); - _Rep_base* rep = static_cast<_Rep_base*>(::operator new(sizeof(*rep) + len + 1)); - rep->len = len; - rep->cap = len; - rep->count = 0; - char* data = data_from_rep(rep); - std::memcpy(data, msg, len + 1); - __imp_ = data; + auto* rep = static_cast<__rep*>(::operator new(sizeof(__rep) + len + 1)); + rep->refcount = 0; + std::memcpy(rep->data, msg, len + 1); + __imp_ = rep; } inline __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring& s) noexcept : __imp_(s.__imp_) { - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); + __libcpp_atomic_add(&__imp_->refcount, 1); } inline __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept { - bool adjust_old_count = __uses_refcount(); - struct _Rep_base* old_rep = rep_from_data(__imp_); - __imp_ = s.__imp_; - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); - if (adjust_old_count) { - if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) { - ::operator delete(old_rep); - } - } + __rep* old_rep = __imp_; + __imp_ = s.__imp_; + __libcpp_atomic_add(&__imp_->refcount, 1); + + if (__libcpp_atomic_add(&old_rep->refcount, ptrdiff_t(-1)) < 0) + ::operator delete(old_rep); return *this; } inline __libcpp_refstring::~__libcpp_refstring() { - if (__uses_refcount()) { - _Rep_base* rep = rep_from_data(__imp_); - if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { - ::operator delete(rep); - } - } + if (__libcpp_atomic_add(&__imp_->refcount, ptrdiff_t(-1)) < 0) + ::operator delete(__imp_); } -inline bool __libcpp_refstring::__uses_refcount() const { -#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE) - return __imp_ != get_gcc_empty_string_storage(); -#else - return true; -#endif -} +inline const char* __libcpp_refstring::c_str() const noexcept { return __imp_->data; } _LIBCPP_END_NAMESPACE_STD