summaryrefslogtreecommitdiffstats
path: root/libcxxabi/src/stdexcept.cpp
diff options
context:
space:
mode:
authorHoward Hinnant <hhinnant@apple.com>2012-09-18 21:34:12 +0000
committerHoward Hinnant <hhinnant@apple.com>2012-09-18 21:34:12 +0000
commite115af2777f6532c8943e95baf7011e2f92f781a (patch)
tree98669c11702707521b6a2805fce3cfcd03ffcb79 /libcxxabi/src/stdexcept.cpp
parent1de7ec8c7caa59c8a1c3862b3cda9b0f17481bca (diff)
downloadbcm5719-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.cpp50
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);
}
}
OpenPOWER on IntegriCloud