stdexcept.cpp revision cdf7d557bd6835f66fe707ca7b1a8f22010ffb66
1//===------------------------ stdexcept.cpp -------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "stdexcept" 11#include "new" 12#include <cstdlib> 13#include <cstring> 14#include <cstdint> 15#include <cstddef> 16 17#if __APPLE__ 18#include <dlfcn.h> 19#include <mach-o/dyld.h> 20#endif 21 22// Note: optimize for size 23 24#pragma GCC visibility push(hidden) 25 26namespace 27{ 28 29class __libcpp_nmstr 30{ 31private: 32 const char* str_; 33 34 typedef int count_t; 35 36 struct _Rep_base 37 { 38 std::size_t len; 39 std::size_t cap; 40 count_t count; 41 }; 42 43 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(sizeof(_Rep_base)); 44 45 count_t& count() const _NOEXCEPT {return ((_Rep_base*)(str_ - offset))->count;} 46 47#if __APPLE__ 48 static 49 const void* 50 compute_gcc_empty_string_storage() _LIBCPP_CANTTHROW 51 { 52 void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 53 if (handle == 0) 54 return 0; 55 return (const char*)dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE") + offset; 56 } 57 58 static 59 const void* 60 get_gcc_empty_string_storage() _LIBCPP_CANTTHROW 61 { 62 static const void* p = compute_gcc_empty_string_storage(); 63 return p; 64 } 65#endif 66 67public: 68 explicit __libcpp_nmstr(const char* msg); 69 __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT; 70 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT; 71 ~__libcpp_nmstr(); 72 const char* c_str() const _NOEXCEPT {return str_;} 73}; 74 75__libcpp_nmstr::__libcpp_nmstr(const char* msg) 76{ 77 std::size_t len = strlen(msg); 78 str_ = static_cast<const char*>(::operator new(len + 1 + offset)); 79 _Rep_base* c = (_Rep_base*)str_; 80 c->len = c->cap = len; 81 str_ += offset; 82 count() = 0; 83 std::memcpy(const_cast<char*>(c_str()), msg, len + 1); 84} 85 86inline 87__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT 88 : str_(s.str_) 89{ 90#if __APPLE__ 91 if (str_ != get_gcc_empty_string_storage()) 92#endif 93 __sync_add_and_fetch(&count(), 1); 94} 95 96__libcpp_nmstr& 97__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT 98{ 99 const char* p = str_; 100 str_ = s.str_; 101#if __APPLE__ 102 if (str_ != get_gcc_empty_string_storage()) 103#endif 104 __sync_add_and_fetch(&count(), 1); 105#if __APPLE__ 106 if (p != get_gcc_empty_string_storage()) 107#endif 108 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) 109 { 110 ::operator delete(const_cast<char*>(p-offset)); 111 } 112 return *this; 113} 114 115inline 116__libcpp_nmstr::~__libcpp_nmstr() 117{ 118#if __APPLE__ 119 if (str_ != get_gcc_empty_string_storage()) 120#endif 121 if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) 122 { 123 ::operator delete(const_cast<char*>(str_ - offset)); 124 } 125} 126 127} 128 129#pragma GCC visibility pop 130 131namespace std // purposefully not using versioning namespace 132{ 133 134logic_error::~logic_error() _NOEXCEPT 135{ 136 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 137 s.~__libcpp_nmstr(); 138} 139 140const char* 141logic_error::what() const _NOEXCEPT 142{ 143 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 144 return s.c_str(); 145} 146 147runtime_error::~runtime_error() _NOEXCEPT 148{ 149 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 150 s.~__libcpp_nmstr(); 151} 152 153const char* 154runtime_error::what() const _NOEXCEPT 155{ 156 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_; 157 return s.c_str(); 158} 159 160domain_error::~domain_error() _NOEXCEPT {} 161invalid_argument::~invalid_argument() _NOEXCEPT {} 162length_error::~length_error() _NOEXCEPT {} 163out_of_range::~out_of_range() _NOEXCEPT {} 164 165range_error::~range_error() _NOEXCEPT {} 166overflow_error::~overflow_error() _NOEXCEPT {} 167underflow_error::~underflow_error() _NOEXCEPT {} 168 169} // std 170