stdexcept.cpp revision 253159
1314564Sdim//===------------------------ stdexcept.cpp -------------------------------===// 2287514Sdim// 3353358Sdim// The LLVM Compiler Infrastructure 4353358Sdim// 5353358Sdim// This file is dual licensed under the MIT and the University of Illinois Open 6287514Sdim// Source Licenses. See LICENSE.TXT for details. 7287514Sdim// 8287514Sdim//===----------------------------------------------------------------------===// 9287514Sdim 10287514Sdim#include "stdexcept" 11287514Sdim#include "new" 12314564Sdim#include "string" 13314564Sdim#include <cstdlib> 14287514Sdim#include <cstring> 15314564Sdim#include <cstdint> 16314564Sdim#include <cstddef> 17314564Sdim#include "system_error" 18314564Sdim 19314564Sdim#ifndef __has_include 20314564Sdim#define __has_include(inc) 0 21314564Sdim#endif 22314564Sdim 23314564Sdim#ifdef __APPLE__ 24314564Sdim#include <cxxabi.h> 25314564Sdim#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 26314564Sdim#include <cxxabi.h> 27314564Sdim#endif 28314564Sdim 29314564Sdim// Note: optimize for size 30314564Sdim 31314564Sdim#pragma GCC visibility push(hidden) 32314564Sdim 33314564Sdimnamespace 34314564Sdim{ 35314564Sdim 36314564Sdimclass __libcpp_nmstr 37314564Sdim{ 38314564Sdimprivate: 39314564Sdim const char* str_; 40314564Sdim 41314564Sdim typedef std::size_t unused_t; 42314564Sdim typedef std::ptrdiff_t count_t; 43314564Sdim 44314564Sdim static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 45314564Sdim sizeof(count_t)); 46314564Sdim 47314564Sdim count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 48314564Sdimpublic: 49314564Sdim explicit __libcpp_nmstr(const char* msg); 50314564Sdim __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 51314564Sdim __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 52314564Sdim ~__libcpp_nmstr() _LIBCPP_CANTTHROW; 53314564Sdim const char* c_str() const _NOEXCEPT {return str_;} 54314564Sdim}; 55314564Sdim 56314564Sdim__libcpp_nmstr::__libcpp_nmstr(const char* msg) 57314564Sdim{ 58314564Sdim std::size_t len = strlen(msg); 59287514Sdim str_ = new char[len + 1 + offset]; 60314564Sdim unused_t* c = (unused_t*)str_; 61287514Sdim c[0] = c[1] = len; 62314564Sdim str_ += offset; 63314564Sdim count() = 0; 64287514Sdim std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 65287514Sdim} 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