stdexcept.cpp revision 241903
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#if __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 33namespace 34{ 35 36class __libcpp_nmstr 37{ 38private: 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)));} 48public: 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::strcpy(const_cast<char*>(c_str()), msg); 65} 66 67inline 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 85inline 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 96namespace std // purposefully not using versioning namespace 97{ 98 99logic_error::logic_error(const string& msg) 100{ 101 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 102 ::new(&s) __libcpp_nmstr(msg.c_str()); 103} 104 105logic_error::logic_error(const char* msg) 106{ 107 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 108 ::new(&s) __libcpp_nmstr(msg); 109} 110 111logic_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 117logic_error& 118logic_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 128logic_error::~logic_error() _NOEXCEPT 129{ 130 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 131 s.~__libcpp_nmstr(); 132} 133 134const char* 135logic_error::what() const _NOEXCEPT 136{ 137 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 138 return s.c_str(); 139} 140 141#endif 142 143runtime_error::runtime_error(const string& msg) 144{ 145 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 146 ::new(&s) __libcpp_nmstr(msg.c_str()); 147} 148 149runtime_error::runtime_error(const char* msg) 150{ 151 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 152 ::new(&s) __libcpp_nmstr(msg); 153} 154 155runtime_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 161runtime_error& 162runtime_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 172runtime_error::~runtime_error() _NOEXCEPT 173{ 174 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 175 s.~__libcpp_nmstr(); 176} 177 178const char* 179runtime_error::what() const _NOEXCEPT 180{ 181 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 182 return s.c_str(); 183} 184 185domain_error::~domain_error() _NOEXCEPT {} 186invalid_argument::~invalid_argument() _NOEXCEPT {} 187length_error::~length_error() _NOEXCEPT {} 188out_of_range::~out_of_range() _NOEXCEPT {} 189 190range_error::~range_error() _NOEXCEPT {} 191overflow_error::~overflow_error() _NOEXCEPT {} 192underflow_error::~underflow_error() _NOEXCEPT {} 193 194#endif 195 196} // std 197