forked from OSchip/llvm-project
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
This commit is contained in:
parent
1de7ec8c7c
commit
e115af2777
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue