From e115af2777f6532c8943e95baf7011e2f92f781a Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Tue, 18 Sep 2012 21:34:12 +0000 Subject: [PATCH] I've added Apple-only behavior that looks for libstdc++ in the same process and if found, checks the string stored in exception objects to see if it is the gcc empty string singleton before manipulating the reference count. This is done so that if such an exception is created with a zero-length string in libstdc++, libc++abi won't try to delete the memory. This is part of a ongoing process to make libc++ exceptions ABI-compatible with libstdc++-4.2 exceptions, to the point that each library can catch exceptions thrown by the other. If other parties would also like this behavior, the #if __APPLE__ can be broadened. llvm-svn: 164170 --- libcxxabi/src/stdexcept.cpp | 50 ++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/libcxxabi/src/stdexcept.cpp b/libcxxabi/src/stdexcept.cpp index 5ea92fb5744a..7071915addba 100644 --- a/libcxxabi/src/stdexcept.cpp +++ b/libcxxabi/src/stdexcept.cpp @@ -14,6 +14,11 @@ #include #include +#if __APPLE__ +#include +#include +#endif + // Note: optimize for size #pragma GCC visibility push(hidden) @@ -33,6 +38,27 @@ private: sizeof(count_t)); count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} + +#if __APPLE__ + static + const void* + compute_gcc_empty_string_storage() _LIBCPP_CANTTHROW + { + void* handle = dlopen("libstdc++.dylib", RTLD_LAZY); + if (handle == 0) + return 0; + return (const char*)dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE") + offset; + } + + static + const void* + get_gcc_empty_string_storage() _LIBCPP_CANTTHROW + { + static const void* p = compute_gcc_empty_string_storage(); + return p; + } +#endif + public: explicit __libcpp_nmstr(const char* msg); __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; @@ -56,7 +82,10 @@ inline __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) : str_(s.str_) { - __sync_add_and_fetch(&count(), 1); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + __sync_add_and_fetch(&count(), 1); } __libcpp_nmstr& @@ -64,17 +93,26 @@ __libcpp_nmstr::operator=(const __libcpp_nmstr& s) { const char* p = str_; str_ = s.str_; - __sync_add_and_fetch(&count(), 1); - if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) - delete [] (p-offset); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + __sync_add_and_fetch(&count(), 1); +#if __APPLE__ + if (p != get_gcc_empty_string_storage()) +#endif + if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) + delete [] (p-offset); return *this; } inline __libcpp_nmstr::~__libcpp_nmstr() { - if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) - delete [] (str_ - offset); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) + delete [] (str_ - offset); } }