[cfe-commits] [libcxxabi] r164170 - /libcxxabi/trunk/src/stdexcept.cpp

Howard Hinnant hhinnant at apple.com
Tue Sep 18 14:34:12 PDT 2012


Author: hhinnant
Date: Tue Sep 18 16:34:12 2012
New Revision: 164170

URL: http://llvm.org/viewvc/llvm-project?rev=164170&view=rev
Log:
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.

Modified:
    libcxxabi/trunk/src/stdexcept.cpp

Modified: libcxxabi/trunk/src/stdexcept.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/stdexcept.cpp?rev=164170&r1=164169&r2=164170&view=diff
==============================================================================
--- libcxxabi/trunk/src/stdexcept.cpp (original)
+++ libcxxabi/trunk/src/stdexcept.cpp Tue Sep 18 16:34:12 2012
@@ -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 @@
                                                                        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 @@
 __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 @@
 {
     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);
 }
 
 }





More information about the cfe-commits mailing list