185909Simp//===------------------------ stdexcept.cpp -------------------------------===// 285909Simp// 385909Simp// The LLVM Compiler Infrastructure 485909Simp// 585909Simp// This file is dual licensed under the MIT and the University of Illinois Open 685909Simp// Source Licenses. See LICENSE.TXT for details. 785909Simp// 885909Simp//===----------------------------------------------------------------------===// 985909Simp 1085909Simp#include "stdexcept" 1185909Simp#include "new" 1285909Simp#include "string" 1385909Simp#include <cstdlib> 1485909Simp#include <cstring> 1585909Simp#include <cstdint> 1685909Simp#include <cstddef> 1785909Simp#include "system_error" 1885909Simp 1985909Simp#ifndef __has_include 2085909Simp#define __has_include(inc) 0 2185909Simp#endif 2285909Simp 2385909Simp#ifdef __APPLE__ 2485909Simp#include <cxxabi.h> 2585909Simp#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 2685909Simp#include <cxxabi.h> 2785909Simp#endif 2885909Simp 2985909Simp// Note: optimize for size 3085909Simp 3185909Simp#pragma GCC visibility push(hidden) 3285909Simp 3385909Simpnamespace 3485909Simp{ 3585909Simp 3685909Simpclass __libcpp_nmstr 3785909Simp{ 3885909Simpprivate: 3985909Simp const char* str_; 4087451Sobrien 4189180Smsmith typedef std::size_t unused_t; 4285909Simp typedef std::ptrdiff_t count_t; 4385909Simp 4485909Simp static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 4585909Simp sizeof(count_t)); 4685909Simp 4785909Simp count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 4885909Simppublic: 4985909Simp explicit __libcpp_nmstr(const char* msg); 5085909Simp __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 5185909Simp __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 5285909Simp ~__libcpp_nmstr() _LIBCPP_CANTTHROW; 5385909Simp const char* c_str() const _NOEXCEPT {return str_;} 5485909Simp}; 5585909Simp 5685909Simp__libcpp_nmstr::__libcpp_nmstr(const char* msg) 5785909Simp{ 5885909Simp std::size_t len = strlen(msg); 5985909Simp str_ = new char[len + 1 + offset]; 6085909Simp unused_t* c = (unused_t*)str_; 6185909Simp c[0] = c[1] = len; 6285909Simp str_ += offset; 6385909Simp count() = 0; 6485909Simp std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 6585909Simp} 6685909Simp 6785909Simpinline 6885909Simp__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) 6985909Simp : str_(s.str_) 7085909Simp{ 7185909Simp __sync_add_and_fetch(&count(), 1); 7285909Simp} 7385909Simp 7485909Simp__libcpp_nmstr& 7585909Simp__libcpp_nmstr::operator=(const __libcpp_nmstr& s) 7685909Simp{ 7785909Simp const char* p = str_; 7885909Simp str_ = s.str_; 7989180Smsmith __sync_add_and_fetch(&count(), 1); 8085909Simp if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) 8185909Simp delete [] (p-offset); 8285909Simp return *this; 8385909Simp} 8485909Simp 8588893Simpinline 8688893Simp__libcpp_nmstr::~__libcpp_nmstr() 8788893Simp{ 8888893Simp if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) 8988893Simp delete [] (str_ - offset); 9088893Simp} 9188893Simp 9288893Simp} 9388893Simp 9488893Simp#pragma GCC visibility pop 9588893Simp 9686253Simpnamespace 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