stdexcept.cpp revision 232950
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 24namespace 25{ 26 27class __libcpp_nmstr 28{ 29private: 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)));} 39public: 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 58inline 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 76inline 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 87namespace std // purposefully not using versioning namespace 88{ 89 90logic_error::logic_error(const string& msg) 91{ 92 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 93 ::new(&s) __libcpp_nmstr(msg.c_str()); 94} 95 96logic_error::logic_error(const char* msg) 97{ 98 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 99 ::new(&s) __libcpp_nmstr(msg); 100} 101 102logic_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 108logic_error& 109logic_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 119logic_error::~logic_error() _NOEXCEPT 120{ 121 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 122 s.~__libcpp_nmstr(); 123} 124 125const char* 126logic_error::what() const _NOEXCEPT 127{ 128 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 129 return s.c_str(); 130} 131 132#endif 133 134runtime_error::runtime_error(const string& msg) 135{ 136 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 137 ::new(&s) __libcpp_nmstr(msg.c_str()); 138} 139 140runtime_error::runtime_error(const char* msg) 141{ 142 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 143 ::new(&s) __libcpp_nmstr(msg); 144} 145 146runtime_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 152runtime_error& 153runtime_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 163runtime_error::~runtime_error() _NOEXCEPT 164{ 165 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 166 s.~__libcpp_nmstr(); 167} 168 169const char* 170runtime_error::what() const _NOEXCEPT 171{ 172 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 173 return s.c_str(); 174} 175 176domain_error::~domain_error() _NOEXCEPT {} 177invalid_argument::~invalid_argument() _NOEXCEPT {} 178length_error::~length_error() _NOEXCEPT {} 179out_of_range::~out_of_range() _NOEXCEPT {} 180 181range_error::~range_error() _NOEXCEPT {} 182overflow_error::~overflow_error() _NOEXCEPT {} 183underflow_error::~underflow_error() _NOEXCEPT {} 184 185#endif 186 187} // std 188