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 #include "stdexcept" 11 #include "new" 12 #include "string" 13 #include <cstdlib> 14 #include <cstring> 15 #include <cstdint> 16 #include <cstddef> 17 #include "system_error" 18 19 // Use <cxxabi.h> to determine whether we're linking against libc++abi. 20 #if __has_include(<cxxabi.h>) 21 #include <cxxabi.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 std::size_t unused_t; 37 typedef std::int32_t count_t; 38 39 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 40 sizeof(count_t)); 41 42 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 43 public: 44 explicit __libcpp_nmstr(const char* msg); 45 __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 46 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 47 ~__libcpp_nmstr() _LIBCPP_CANTTHROW; 48 const char* c_str() const _NOEXCEPT {return str_;} 49 }; 50 51 __libcpp_nmstr::__libcpp_nmstr(const char* msg) 52 { 53 std::size_t len = strlen(msg); 54 str_ = new char[len + 1 + offset]; 55 unused_t* c = (unused_t*)str_; 56 c[0] = c[1] = len; 57 str_ += offset; 58 count() = 0; 59 std::strcpy(const_cast<char*>(c_str()), msg); 60 } 61 62 inline 63 __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) 64 : str_(s.str_) 65 { 66 __sync_add_and_fetch(&count(), 1); 67 } 68 69 __libcpp_nmstr& 70 __libcpp_nmstr::operator=(const __libcpp_nmstr& s) 71 { 72 const char* p = str_; 73 str_ = s.str_; 74 __sync_add_and_fetch(&count(), 1); 75 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0) 76 delete [] (p-offset); 77 return *this; 78 } 79 80 inline 81 __libcpp_nmstr::~__libcpp_nmstr() 82 { 83 if (__sync_add_and_fetch(&count(), -1) < 0) 84 delete [] (str_ - offset); 85 } 86 87 } 88 89 #pragma GCC visibility pop 90 91 namespace std // purposefully not using versioning namespace 92 { 93 94 logic_error::logic_error(const string& msg) 95 { 96 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 97 ::new(&s) __libcpp_nmstr(msg.c_str()); 98 } 99 100 logic_error::logic_error(const char* msg) 101 { 102 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 103 ::new(&s) __libcpp_nmstr(msg); 104 } 105 106 logic_error::logic_error(const logic_error& le) _NOEXCEPT 107 { 108 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 109 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 110 } 111 112 logic_error& 113 logic_error::operator=(const logic_error& le) _NOEXCEPT 114 { 115 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 116 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 117 s1 = s2; 118 return *this; 119 } 120 121 #ifndef _LIBCPPABI_VERSION 122 123 logic_error::~logic_error() _NOEXCEPT 124 { 125 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 126 s.~__libcpp_nmstr(); 127 } 128 129 const char* 130 logic_error::what() const _NOEXCEPT 131 { 132 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 133 return s.c_str(); 134 } 135 136 #endif 137 138 runtime_error::runtime_error(const string& msg) 139 { 140 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 141 ::new(&s) __libcpp_nmstr(msg.c_str()); 142 } 143 144 runtime_error::runtime_error(const char* msg) 145 { 146 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 147 ::new(&s) __libcpp_nmstr(msg); 148 } 149 150 runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT 151 { 152 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 153 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 154 } 155 156 runtime_error& 157 runtime_error::operator=(const runtime_error& le) _NOEXCEPT 158 { 159 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 160 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 161 s1 = s2; 162 return *this; 163 } 164 165 #ifndef _LIBCPPABI_VERSION 166 167 runtime_error::~runtime_error() _NOEXCEPT 168 { 169 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 170 s.~__libcpp_nmstr(); 171 } 172 173 const char* 174 runtime_error::what() const _NOEXCEPT 175 { 176 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 177 return s.c_str(); 178 } 179 180 domain_error::~domain_error() _NOEXCEPT {} 181 invalid_argument::~invalid_argument() _NOEXCEPT {} 182 length_error::~length_error() _NOEXCEPT {} 183 out_of_range::~out_of_range() _NOEXCEPT {} 184 185 range_error::~range_error() _NOEXCEPT {} 186 overflow_error::~overflow_error() _NOEXCEPT {} 187 underflow_error::~underflow_error() _NOEXCEPT {} 188 189 #endif 190 191 } // std 192