stdexcept.cpp revision 234976
1275970Scy//===------------------------ stdexcept.cpp -------------------------------===// 2275970Scy// 3275970Scy// The LLVM Compiler Infrastructure 4275970Scy// 5275970Scy// This file is dual licensed under the MIT and the University of Illinois Open 6275970Scy// Source Licenses. See LICENSE.TXT for details. 7275970Scy// 8275970Scy//===----------------------------------------------------------------------===// 9275970Scy 10275970Scy#include "stdexcept" 11275970Scy#include "new" 12275970Scy#include "string" 13275970Scy#include <cstdlib> 14275970Scy#include <cstring> 15275970Scy#include <cstdint> 16275970Scy#include <cstddef> 17275970Scy#include "system_error" 18275970Scy 19275970Scy// Use <cxxabi.h> to determine whether we're linking against libc++abi. 20275970Scy#if __has_include(<cxxabi.h>) 21275970Scy#include <cxxabi.h> 22275970Scy#endif 23275970Scy 24275970Scy// Note: optimize for size 25275970Scy 26275970Scy#pragma GCC visibility push(hidden) 27275970Scy 28275970Scynamespace 29275970Scy{ 30275970Scy 31275970Scyclass __libcpp_nmstr 32275970Scy{ 33275970Scyprivate: 34275970Scy const char* str_; 35275970Scy 36301301Sdelphij typedef std::size_t unused_t; 37275970Scy typedef std::int32_t count_t; 38275970Scy 39275970Scy static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + 40275970Scy sizeof(count_t)); 41275970Scy 42275970Scy count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} 43275970Scypublic: 44275970Scy explicit __libcpp_nmstr(const char* msg); 45275970Scy __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 46275970Scy __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; 47275970Scy ~__libcpp_nmstr() _LIBCPP_CANTTHROW; 48275970Scy const char* c_str() const _NOEXCEPT {return str_;} 49275970Scy}; 50275970Scy 51275970Scy__libcpp_nmstr::__libcpp_nmstr(const char* msg) 52275970Scy{ 53275970Scy std::size_t len = strlen(msg); 54275970Scy str_ = new char[len + 1 + offset]; 55275970Scy unused_t* c = (unused_t*)str_; 56275970Scy c[0] = c[1] = len; 57275970Scy str_ += offset; 58275970Scy count() = 0; 59275970Scy std::strcpy(const_cast<char*>(c_str()), msg); 60275970Scy} 61275970Scy 62275970Scyinline 63275970Scy__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) 64275970Scy : str_(s.str_) 65275970Scy{ 66275970Scy __sync_add_and_fetch(&count(), 1); 67} 68 69__libcpp_nmstr& 70__libcpp_nmstr::operator=(const __libcpp_nmstr& s) 71{ 72 const char* p = str_; 73 str_ = s.str_; 74 __sync_add_and_fetch(&count(), 1); 75 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0) 76 delete [] (p-offset); 77 return *this; 78} 79 80inline 81__libcpp_nmstr::~__libcpp_nmstr() 82{ 83 if (__sync_add_and_fetch(&count(), -1) < 0) 84 delete [] (str_ - offset); 85} 86 87} 88 89#pragma GCC visibility pop 90 91namespace std // purposefully not using versioning namespace 92{ 93 94logic_error::logic_error(const string& msg) 95{ 96 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 97 ::new(&s) __libcpp_nmstr(msg.c_str()); 98} 99 100logic_error::logic_error(const char* msg) 101{ 102 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 103 ::new(&s) __libcpp_nmstr(msg); 104} 105 106logic_error::logic_error(const logic_error& le) _NOEXCEPT 107{ 108 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 109 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 110} 111 112logic_error& 113logic_error::operator=(const logic_error& le) _NOEXCEPT 114{ 115 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 116 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 117 s1 = s2; 118 return *this; 119} 120 121#ifndef _LIBCPPABI_VERSION 122 123logic_error::~logic_error() _NOEXCEPT 124{ 125 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 126 s.~__libcpp_nmstr(); 127} 128 129const char* 130logic_error::what() const _NOEXCEPT 131{ 132 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 133 return s.c_str(); 134} 135 136#endif 137 138runtime_error::runtime_error(const string& msg) 139{ 140 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 141 ::new(&s) __libcpp_nmstr(msg.c_str()); 142} 143 144runtime_error::runtime_error(const char* msg) 145{ 146 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 147 ::new(&s) __libcpp_nmstr(msg); 148} 149 150runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT 151{ 152 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 153 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_); 154} 155 156runtime_error& 157runtime_error::operator=(const runtime_error& le) _NOEXCEPT 158{ 159 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_; 160 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_; 161 s1 = s2; 162 return *this; 163} 164 165#ifndef _LIBCPPABI_VERSION 166 167runtime_error::~runtime_error() _NOEXCEPT 168{ 169 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 170 s.~__libcpp_nmstr(); 171} 172 173const char* 174runtime_error::what() const _NOEXCEPT 175{ 176 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 177 return s.c_str(); 178} 179 180domain_error::~domain_error() _NOEXCEPT {} 181invalid_argument::~invalid_argument() _NOEXCEPT {} 182length_error::~length_error() _NOEXCEPT {} 183out_of_range::~out_of_range() _NOEXCEPT {} 184 185range_error::~range_error() _NOEXCEPT {} 186overflow_error::~overflow_error() _NOEXCEPT {} 187underflow_error::~underflow_error() _NOEXCEPT {} 188 189#endif 190 191} // std 192