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