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