blob: 246eea4bcea01260e3d5a7d532f857090effbc29 [file] [log] [blame]
Howard Hinnant3e7d1552012-02-17 19:23:47 +00001//===------------------------ 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
Howard Hinnante115af22012-09-18 21:34:12 +000017#if __APPLE__
18#include <dlfcn.h>
19#include <mach-o/dyld.h>
20#endif
21
Howard Hinnant3e7d1552012-02-17 19:23:47 +000022// 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
Howard Hinnant2d0352c2012-09-28 00:05:34 +000034 typedef int count_t;
Howard Hinnant3e7d1552012-02-17 19:23:47 +000035
Howard Hinnant2d0352c2012-09-28 00:05:34 +000036 struct _Rep_base
37 {
38 std::size_t len;
39 std::size_t cap;
40 count_t count;
41 };
Howard Hinnant3e7d1552012-02-17 19:23:47 +000042
Howard Hinnant2d0352c2012-09-28 00:05:34 +000043 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;}
Howard Hinnante115af22012-09-18 21:34:12 +000046
47#if __APPLE__
48 static
49 const void*
Jean-Daniel Dupas8d362a92013-08-29 19:19:27 +000050 compute_gcc_empty_string_storage() _NOEXCEPT
Howard Hinnante115af22012-09-18 21:34:12 +000051 {
Howard Hinnanted3d6902012-09-21 19:12:56 +000052 void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
Howard Hinnante115af22012-09-18 21:34:12 +000053 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*
Jean-Daniel Dupas8d362a92013-08-29 19:19:27 +000060 get_gcc_empty_string_storage() _NOEXCEPT
Howard Hinnante115af22012-09-18 21:34:12 +000061 {
62 static const void* p = compute_gcc_empty_string_storage();
63 return p;
64 }
65#endif
66
Howard Hinnant3e7d1552012-02-17 19:23:47 +000067public:
68 explicit __libcpp_nmstr(const char* msg);
Howard Hinnant59a5a952013-08-25 17:00:57 +000069 __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT;
70 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT;
71 ~__libcpp_nmstr();
Howard Hinnant3e7d1552012-02-17 19:23:47 +000072 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);
Howard Hinnant2d0352c2012-09-28 00:05:34 +000078 str_ = static_cast<const char*>(::operator new(len + 1 + offset));
79 _Rep_base* c = (_Rep_base*)str_;
80 c->len = c->cap = len;
Howard Hinnant3e7d1552012-02-17 19:23:47 +000081 str_ += offset;
82 count() = 0;
Howard Hinnant862c4a02013-06-17 18:10:34 +000083 std::memcpy(const_cast<char*>(c_str()), msg, len + 1);
Howard Hinnant3e7d1552012-02-17 19:23:47 +000084}
85
86inline
Howard Hinnant59a5a952013-08-25 17:00:57 +000087__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT
Howard Hinnant3e7d1552012-02-17 19:23:47 +000088 : str_(s.str_)
89{
Howard Hinnante115af22012-09-18 21:34:12 +000090#if __APPLE__
91 if (str_ != get_gcc_empty_string_storage())
92#endif
93 __sync_add_and_fetch(&count(), 1);
Howard Hinnant3e7d1552012-02-17 19:23:47 +000094}
95
96__libcpp_nmstr&
Howard Hinnant59a5a952013-08-25 17:00:57 +000097__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT
Howard Hinnant3e7d1552012-02-17 19:23:47 +000098{
99 const char* p = str_;
100 str_ = s.str_;
Howard Hinnante115af22012-09-18 21:34:12 +0000101#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)
Howard Hinnant2d0352c2012-09-28 00:05:34 +0000109 {
110 ::operator delete(const_cast<char*>(p-offset));
111 }
Howard Hinnant3e7d1552012-02-17 19:23:47 +0000112 return *this;
113}
114
115inline
116__libcpp_nmstr::~__libcpp_nmstr()
117{
Howard Hinnante115af22012-09-18 21:34:12 +0000118#if __APPLE__
119 if (str_ != get_gcc_empty_string_storage())
120#endif
121 if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
Howard Hinnant2d0352c2012-09-28 00:05:34 +0000122 {
123 ::operator delete(const_cast<char*>(str_ - offset));
124 }
Howard Hinnant3e7d1552012-02-17 19:23:47 +0000125}
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