Index: include/__refstring =================================================================== --- include/__refstring +++ include/__refstring @@ -11,6 +11,7 @@ #define _LIBCPP___REFSTRING #include <__config> +#include #include #include #ifdef __APPLE__ @@ -20,119 +21,106 @@ _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_HIDDEN __libcpp_refstring -{ -private: - const char* str_; +namespace __refstring_imp { namespace { +typedef int count_t; - typedef int count_t; +struct _Rep_base { + std::size_t len; + std::size_t cap; + count_t count; +}; - struct _Rep_base - { - std::size_t len; - std::size_t cap; - count_t count; - }; - - static - _Rep_base* - rep_from_data(const char *data_) _NOEXCEPT - { - char *data = const_cast(data_); - return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); - } - static - char * - data_from_rep(_Rep_base *rep) _NOEXCEPT - { - char *data = reinterpret_cast(rep); - return data + sizeof(*rep); - } +inline _Rep_base* rep_from_data(const char *data_) noexcept { + char *data = const_cast(data_); + return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); +} -#ifdef __APPLE__ - static - 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)); - } - - static - const char* - get_gcc_empty_string_storage() _NOEXCEPT - { - static const char* p = compute_gcc_empty_string_storage(); - return p; - } +inline char * data_from_rep(_Rep_base *rep) noexcept { + char *data = reinterpret_cast(rep); + return data + sizeof(*rep); +} - bool - uses_refcount() const - { - return str_ != get_gcc_empty_string_storage(); - } -#else - bool - uses_refcount() const - { - return true; - } +#if defined(__APPLE__) +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 -public: - explicit __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); - str_ = data; - } - - __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT : str_(s.str_) - { - if (uses_refcount()) - __sync_add_and_fetch(&rep_from_data(str_)->count, 1); - } - - __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT +}} // 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; +} + +inline +__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT + : __imp_(s.__imp_) +{ + if (__uses_refcount()) + __sync_add_and_fetch(&rep_from_data(__imp_)->count, 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()) + __sync_add_and_fetch(&rep_from_data(__imp_)->count, 1); + if (adjust_old_count) { - bool adjust_old_count = uses_refcount(); - struct _Rep_base *old_rep = rep_from_data(str_); - str_ = s.str_; - if (uses_refcount()) - __sync_add_and_fetch(&rep_from_data(str_)->count, 1); - if (adjust_old_count) + if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) { - if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) - { - ::operator delete(old_rep); - } + ::operator delete(old_rep); } - return *this; } - - ~__libcpp_refstring() - { - if (uses_refcount()) - { - _Rep_base* rep = rep_from_data(str_); - if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) - { - ::operator delete(rep); - } + return *this; +} + +inline +__libcpp_refstring::~__libcpp_refstring() { + if (__uses_refcount()) { + _Rep_base* rep = rep_from_data(__imp_); + if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) { + ::operator delete(rep); } } +} - const char* c_str() const _NOEXCEPT {return str_;} -}; +inline +bool __libcpp_refstring::__uses_refcount() const { +#ifdef __APPLE__ + return __imp_ != get_gcc_empty_string_storage(); +#else + return true; +#endif +} _LIBCPP_END_NAMESPACE_STD Index: include/stdexcept =================================================================== --- include/stdexcept +++ include/stdexcept @@ -53,17 +53,23 @@ #pragma GCC system_header #endif -#ifndef _LIBCPP___REFSTRING _LIBCPP_BEGIN_NAMESPACE_STD -class _LIBCPP_HIDDEN __libcpp_refstring { -#ifdef __clang__ - const char *__imp_ __attribute__((__unused__)); // only clang emits a warning -#else - const char *__imp_; -#endif + +class _LIBCPP_HIDDEN __libcpp_refstring +{ + const char* __imp_; + + bool __uses_refcount() const; +public: + explicit __libcpp_refstring(const char* msg); + __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT; + __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT; + ~__libcpp_refstring(); + + const char* c_str() const _NOEXCEPT {return __imp_;} }; + _LIBCPP_END_NAMESPACE_STD -#endif namespace std // purposefully not using versioning namespace { Index: src/stdexcept.cpp =================================================================== --- src/stdexcept.cpp +++ src/stdexcept.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "__refstring" #include "stdexcept" #include "new" #include "string" #include "system_error" +#include "__refstring" /* For _LIBCPPABI_VERSION */ #if defined(LIBCXX_BUILDING_LIBCXXABI) || defined(__APPLE__) || defined(LIBCXXRT) @@ -20,6 +20,7 @@ static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), ""); + namespace std // purposefully not using versioning namespace {