stdexcept.cpp revision 262801
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 31262801Sdim#if ! defined(_LIBCPP_MSVC) 32227825Stheraven#pragma GCC visibility push(hidden) 33262801Sdim#endif 34227825Stheraven 35227825Stheravennamespace 36227825Stheraven{ 37227825Stheraven 38227825Stheravenclass __libcpp_nmstr 39227825Stheraven{ 40227825Stheravenprivate: 41227825Stheraven const char* str_; 42227825Stheraven 43227825Stheraven typedef std::size_t unused_t; 44241903Sdim typedef std::ptrdiff_t count_t; 45227825Stheraven 46227825Stheraven static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 47227825Stheraven sizeof(count_t)); 48227825Stheraven 49227825Stheraven count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 50227825Stheravenpublic: 51227825Stheraven explicit __libcpp_nmstr(const char* msg); 52262801Sdim __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT; 53262801Sdim __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT; 54262801Sdim ~__libcpp_nmstr(); 55227825Stheraven const char* c_str() const _NOEXCEPT {return str_;} 56227825Stheraven}; 57227825Stheraven 58227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg) 59227825Stheraven{ 60227825Stheraven std::size_t len = strlen(msg); 61227825Stheraven str_ = new char[len + 1 + offset]; 62227825Stheraven unused_t* c = (unused_t*)str_; 63227825Stheraven c[0] = c[1] = len; 64227825Stheraven str_ += offset; 65227825Stheraven count() = 0; 66253159Stheraven std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 67227825Stheraven} 68227825Stheraven 69227825Stheraveninline 70262801Sdim__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT 71227825Stheraven : str_(s.str_) 72227825Stheraven{ 73227825Stheraven __sync_add_and_fetch(&count(), 1); 74227825Stheraven} 75227825Stheraven 76227825Stheraven__libcpp_nmstr& 77262801Sdim__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT 78227825Stheraven{ 79227825Stheraven const char* p = str_; 80227825Stheraven str_ = s.str_; 81227825Stheraven __sync_add_and_fetch(&count(), 1); 82241903Sdim if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) 83227825Stheraven delete [] (p-offset); 84227825Stheraven return *this; 85227825Stheraven} 86227825Stheraven 87227825Stheraveninline 88227825Stheraven__libcpp_nmstr::~__libcpp_nmstr() 89227825Stheraven{ 90241903Sdim if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) 91227825Stheraven delete [] (str_ - offset); 92227825Stheraven} 93227825Stheraven 94227825Stheraven} 95227825Stheraven 96262801Sdim#if ! defined(_LIBCPP_MSVC) 97227825Stheraven#pragma GCC visibility pop 98262801Sdim#endif 99227825Stheraven 100227825Stheravennamespace std // purposefully not using versioning namespace 101227825Stheraven{ 102227825Stheraven 103227825Stheravenlogic_error::logic_error(const string& msg) 104227825Stheraven{ 105227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 106227825Stheraven ::new(&s) __libcpp_nmstr(msg.c_str()); 107227825Stheraven} 108227825Stheraven 109227825Stheravenlogic_error::logic_error(const char* msg) 110227825Stheraven{ 111227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 112227825Stheraven ::new(&s) __libcpp_nmstr(msg); 113227825Stheraven} 114227825Stheraven 115227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT 116227825Stheraven{ 117227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 118227825Stheraven ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 119227825Stheraven} 120227825Stheraven 121227825Stheravenlogic_error& 122227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT 123227825Stheraven{ 124227825Stheraven __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 125227825Stheraven const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 126227825Stheraven s1 = s2; 127227825Stheraven return *this; 128227825Stheraven} 129227825Stheraven 130262801Sdim#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) 131232950Stheraven 132227825Stheravenlogic_error::~logic_error() _NOEXCEPT 133227825Stheraven{ 134227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 135227825Stheraven s.~__libcpp_nmstr(); 136227825Stheraven} 137227825Stheraven 138227825Stheravenconst char* 139227825Stheravenlogic_error::what() const _NOEXCEPT 140227825Stheraven{ 141227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 142227825Stheraven return s.c_str(); 143227825Stheraven} 144227825Stheraven 145232950Stheraven#endif 146232950Stheraven 147227825Stheravenruntime_error::runtime_error(const string& msg) 148227825Stheraven{ 149227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 150227825Stheraven ::new(&s) __libcpp_nmstr(msg.c_str()); 151227825Stheraven} 152227825Stheraven 153227825Stheravenruntime_error::runtime_error(const char* msg) 154227825Stheraven{ 155227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 156227825Stheraven ::new(&s) __libcpp_nmstr(msg); 157227825Stheraven} 158227825Stheraven 159227825Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT 160227825Stheraven{ 161227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 162227825Stheraven ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 163227825Stheraven} 164227825Stheraven 165227825Stheravenruntime_error& 166227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT 167227825Stheraven{ 168227825Stheraven __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 169227825Stheraven const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 170227825Stheraven s1 = s2; 171227825Stheraven return *this; 172227825Stheraven} 173227825Stheraven 174262801Sdim#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX) 175232950Stheraven 176227825Stheravenruntime_error::~runtime_error() _NOEXCEPT 177227825Stheraven{ 178227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 179227825Stheraven s.~__libcpp_nmstr(); 180227825Stheraven} 181227825Stheraven 182227825Stheravenconst char* 183227825Stheravenruntime_error::what() const _NOEXCEPT 184227825Stheraven{ 185227825Stheraven __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 186227825Stheraven return s.c_str(); 187227825Stheraven} 188227825Stheraven 189227825Stheravendomain_error::~domain_error() _NOEXCEPT {} 190227825Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {} 191227825Stheravenlength_error::~length_error() _NOEXCEPT {} 192227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {} 193227825Stheraven 194227825Stheravenrange_error::~range_error() _NOEXCEPT {} 195227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {} 196227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {} 197227825Stheraven 198232950Stheraven#endif 199232950Stheraven 200227825Stheraven} // std 201