1 //===------------------------ stdexcept.cpp -------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #if defined(LIBCXXABI) 11 12 #include "stdexcept" 13 #include "new" 14 #include <cstdlib> 15 #include <cstring> 16 #include <cstdint> 17 #include <cstddef> 18 19 #if __APPLE__ 20 #include <dlfcn.h> 21 #include <mach-o/dyld.h> 22 #endif 23 24 // Note: optimize for size 25 26 #pragma GCC visibility push(hidden) 27 28 namespace 29 { 30 31 class __libcpp_nmstr 32 { 33 private: 34 const char* str_; 35 36 typedef int count_t; 37 38 struct _Rep_base 39 { 40 std::size_t len; 41 std::size_t cap; 42 count_t count; 43 }; 44 45 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(sizeof(_Rep_base)); 46 count() const47 count_t& count() const _NOEXCEPT {return ((_Rep_base*)(str_ - offset))->count;} 48 49 #if __APPLE__ 50 static 51 const void* compute_gcc_empty_string_storage()52 compute_gcc_empty_string_storage() _NOEXCEPT 53 { 54 void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 55 if (handle == 0) 56 return 0; 57 return (const char*)dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE") + offset; 58 } 59 60 static 61 const void* get_gcc_empty_string_storage()62 get_gcc_empty_string_storage() _NOEXCEPT 63 { 64 static const void* p = compute_gcc_empty_string_storage(); 65 return p; 66 } 67 #endif 68 69 public: 70 explicit __libcpp_nmstr(const char* msg); 71 __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT; 72 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT; 73 ~__libcpp_nmstr(); c_str() const74 const char* c_str() const _NOEXCEPT {return str_;} 75 }; 76 __libcpp_nmstr(const char * msg)77__libcpp_nmstr::__libcpp_nmstr(const char* msg) 78 { 79 std::size_t len = strlen(msg); 80 str_ = static_cast<const char*>(::operator new(len + 1 + offset)); 81 _Rep_base* c = (_Rep_base*)str_; 82 c->len = c->cap = len; 83 str_ += offset; 84 count() = 0; 85 std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 86 } 87 88 inline __libcpp_nmstr(const __libcpp_nmstr & s)89__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT 90 : str_(s.str_) 91 { 92 #if __APPLE__ 93 if (str_ != get_gcc_empty_string_storage()) 94 #endif 95 __sync_add_and_fetch(&count(), 1); 96 } 97 98 __libcpp_nmstr& operator =(const __libcpp_nmstr & s)99__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT 100 { 101 const char* p = str_; 102 str_ = s.str_; 103 #if __APPLE__ 104 if (str_ != get_gcc_empty_string_storage()) 105 #endif 106 __sync_add_and_fetch(&count(), 1); 107 #if __APPLE__ 108 if (p != get_gcc_empty_string_storage()) 109 #endif 110 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) 111 { 112 ::operator delete(const_cast<char*>(p-offset)); 113 } 114 return *this; 115 } 116 117 inline ~__libcpp_nmstr()118__libcpp_nmstr::~__libcpp_nmstr() 119 { 120 #if __APPLE__ 121 if (str_ != get_gcc_empty_string_storage()) 122 #endif 123 if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) 124 { 125 ::operator delete(const_cast<char*>(str_ - offset)); 126 } 127 } 128 129 } 130 131 #pragma GCC visibility pop 132 133 namespace std // purposefully not using versioning namespace 134 { 135 ~logic_error()136logic_error::~logic_error() _NOEXCEPT 137 { 138 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 139 s.~__libcpp_nmstr(); 140 } 141 142 const char* what() const143logic_error::what() const _NOEXCEPT 144 { 145 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 146 return s.c_str(); 147 } 148 ~runtime_error()149runtime_error::~runtime_error() _NOEXCEPT 150 { 151 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 152 s.~__libcpp_nmstr(); 153 } 154 155 const char* what() const156runtime_error::what() const _NOEXCEPT 157 { 158 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 159 return s.c_str(); 160 } 161 ~domain_error()162domain_error::~domain_error() _NOEXCEPT {} ~invalid_argument()163invalid_argument::~invalid_argument() _NOEXCEPT {} ~length_error()164length_error::~length_error() _NOEXCEPT {} ~out_of_range()165out_of_range::~out_of_range() _NOEXCEPT {} 166 ~range_error()167range_error::~range_error() _NOEXCEPT {} ~overflow_error()168overflow_error::~overflow_error() _NOEXCEPT {} ~underflow_error()169underflow_error::~underflow_error() _NOEXCEPT {} 170 171 } // std 172 173 #endif // LIBCXXABI 174