1227825Stheraven//===------------------------ stdexcept.cpp -------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven 10227825Stheraven#include "stdexcept" 11227825Stheraven#include "new" 12227825Stheraven#include "string" 13227825Stheraven#include <cstdlib> 14227825Stheraven#include <cstring> 15227825Stheraven#include <cstdint> 16227825Stheraven#include <cstddef> 17227825Stheraven#include "system_error" 18234976Stheraven 19241903Sdim#ifndef __has_include 20241903Sdim#define __has_include(inc) 0 21241903Sdim#endif 22241903Sdim 23249998Sdim#ifdef __APPLE__ 24232950Stheraven#include <cxxabi.h> 25241903Sdim#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 26241903Sdim#include <cxxabi.h> 27234976Stheraven#endif 28227825Stheraven 29227825Stheraven// Note: optimize for size 30227825Stheraven 31227825Stheraven#pragma GCC visibility push(hidden) 32227825Stheraven 33227825Stheravennamespace 34227825Stheraven{ 35227825Stheraven 36227825Stheravenclass __libcpp_nmstr 37227825Stheraven{ 38227825Stheravenprivate: 39227825Stheraven const char* str_; 40227825Stheraven 41227825Stheraven typedef std::size_t unused_t; 42241903Sdim typedef std::ptrdiff_t count_t; 43227825Stheraven 44227825Stheraven static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 45227825Stheraven sizeof(count_t)); 46227825Stheraven 47227825Stheraven count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 48227825Stheravenpublic: 49227825Stheraven explicit __libcpp_nmstr(const char* msg); 50227825Stheraven __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 51227825Stheraven __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 52227825Stheraven ~__libcpp_nmstr() _LIBCPP_CANTTHROW; 53227825Stheraven const char* c_str() const _NOEXCEPT {return str_;} 54227825Stheraven}; 55227825Stheraven 56227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg) 57227825Stheraven{ 58227825Stheraven std::size_t len = strlen(msg); 59227825Stheraven str_ = new char[len + 1 + offset]; 60227825Stheraven unused_t* c = (unused_t*)str_; 61227825Stheraven c[0] = c[1] = len; 62227825Stheraven str_ += offset; 63227825Stheraven count() = 0; 64253159Stheraven std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 65227825Stheraven} 66227825Stheraven 67227825Stheraveninline 68227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) 69227825Stheraven : str_(s.str_) 70227825Stheraven{ 71227825Stheraven __sync_add_and_fetch(&count(), 1); 72227825Stheraven} 73227825Stheraven 74227825Stheraven__libcpp_nmstr& 75227825Stheraven__libcpp_nmstr::operator=(const __libcpp_nmstr& s) 76227825Stheraven{ 77227825Stheraven const char* p = str_; 78227825Stheraven str_ = s.str_; 79227825Stheraven __sync_add_and_fetch(&count(), 1); 80241903Sdim if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) 81227825Stheraven delete [] (p-offset); 82227825Stheraven return *this; 83227825Stheraven} 84227825Stheraven 85227825Stheraveninline 86227825Stheraven__libcpp_nmstr::~__libcpp_nmstr() 87227825Stheraven{ 88241903Sdim if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) 89227825Stheraven delete [] (str_ - offset); 90227825Stheraven} 91227825Stheraven 92227825Stheraven} 93227825Stheraven 94227825Stheraven#pragma GCC visibility pop 95227825Stheraven 96227825Stheravennamespace std // purposefully not using versioning namespace 97227825Stheraven{ 98227825Stheraven 99227825Stheravenlogic_error::logic_error(const string& msg) 100227825Stheraven{ 101227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 102227825Stheraven ::new(&s) __libcpp_nmstr(msg.c_str()); 103227825Stheraven} 104227825Stheraven 105227825Stheravenlogic_error::logic_error(const char* msg) 106227825Stheraven{ 107227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 108227825Stheraven ::new(&s) __libcpp_nmstr(msg); 109227825Stheraven} 110227825Stheraven 111227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT 112227825Stheraven{ 113227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 114227825Stheraven ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 115227825Stheraven} 116227825Stheraven 117227825Stheravenlogic_error& 118227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT 119227825Stheraven{ 120227825Stheraven __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 121227825Stheraven const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 122227825Stheraven s1 = s2; 123227825Stheraven return *this; 124227825Stheraven} 125227825Stheraven 126232950Stheraven#ifndef _LIBCPPABI_VERSION 127232950Stheraven 128227825Stheravenlogic_error::~logic_error() _NOEXCEPT 129227825Stheraven{ 130227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 131227825Stheraven s.~__libcpp_nmstr(); 132227825Stheraven} 133227825Stheraven 134227825Stheravenconst char* 135227825Stheravenlogic_error::what() const _NOEXCEPT 136227825Stheraven{ 137227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 138227825Stheraven return s.c_str(); 139227825Stheraven} 140227825Stheraven 141232950Stheraven#endif 142232950Stheraven 143227825Stheravenruntime_error::runtime_error(const string& msg) 144227825Stheraven{ 145227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 146227825Stheraven ::new(&s) __libcpp_nmstr(msg.c_str()); 147227825Stheraven} 148227825Stheraven 149227825Stheravenruntime_error::runtime_error(const char* msg) 150227825Stheraven{ 151227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 152227825Stheraven ::new(&s) __libcpp_nmstr(msg); 153227825Stheraven} 154227825Stheraven 155227825Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT 156227825Stheraven{ 157227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 158227825Stheraven ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 159227825Stheraven} 160227825Stheraven 161227825Stheravenruntime_error& 162227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT 163227825Stheraven{ 164227825Stheraven __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 165227825Stheraven const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 166227825Stheraven s1 = s2; 167227825Stheraven return *this; 168227825Stheraven} 169227825Stheraven 170232950Stheraven#ifndef _LIBCPPABI_VERSION 171232950Stheraven 172227825Stheravenruntime_error::~runtime_error() _NOEXCEPT 173227825Stheraven{ 174227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 175227825Stheraven s.~__libcpp_nmstr(); 176227825Stheraven} 177227825Stheraven 178227825Stheravenconst char* 179227825Stheravenruntime_error::what() const _NOEXCEPT 180227825Stheraven{ 181227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 182227825Stheraven return s.c_str(); 183227825Stheraven} 184227825Stheraven 185227825Stheravendomain_error::~domain_error() _NOEXCEPT {} 186227825Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {} 187227825Stheravenlength_error::~length_error() _NOEXCEPT {} 188227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {} 189227825Stheraven 190227825Stheravenrange_error::~range_error() _NOEXCEPT {} 191227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {} 192227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {} 193227825Stheraven 194232950Stheraven#endif 195232950Stheraven 196227825Stheraven} // std 197