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