diff options
author | Howard Hinnant <hhinnant@apple.com> | 2012-09-18 21:34:12 +0000 |
---|---|---|
committer | Howard Hinnant <hhinnant@apple.com> | 2012-09-18 21:34:12 +0000 |
commit | e115af2777f6532c8943e95baf7011e2f92f781a (patch) | |
tree | 98669c11702707521b6a2805fce3cfcd03ffcb79 /libcxxabi/src/stdexcept.cpp | |
parent | 1de7ec8c7caa59c8a1c3862b3cda9b0f17481bca (diff) | |
download | bcm5719-llvm-e115af2777f6532c8943e95baf7011e2f92f781a.tar.gz bcm5719-llvm-e115af2777f6532c8943e95baf7011e2f92f781a.zip |
I've added Apple-only behavior that looks for libstdc++ in the same process and if found, checks the string stored in <stdexcept> 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
Diffstat (limited to 'libcxxabi/src/stdexcept.cpp')
-rw-r--r-- | libcxxabi/src/stdexcept.cpp | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/libcxxabi/src/stdexcept.cpp b/libcxxabi/src/stdexcept.cpp index 5ea92fb5744..7071915addb 100644 --- a/libcxxabi/src/stdexcept.cpp +++ b/libcxxabi/src/stdexcept.cpp @@ -14,6 +14,11 @@ #include <cstdint> #include <cstddef> +#if __APPLE__ +#include <dlfcn.h> +#include <mach-o/dyld.h> +#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); } } |