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 "string"
13 #include <cstdlib>
14 #include <cstring>
15 #include <cstdint>
16 #include <cstddef>
17 #include "system_error"
18 #include <cxxabi.h>
19 
20 // Note:  optimize for size
21 
22 #pragma GCC visibility push(hidden)
23 
24 namespace
25 {
26 
27 class __libcpp_nmstr
28 {
29 private:
30     const char* str_;
31 
32     typedef std::size_t unused_t;
33     typedef std::int32_t count_t;
34 
35     static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
36                                                                        sizeof(count_t));
37 
38     count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
39 public:
40     explicit __libcpp_nmstr(const char* msg);
41     __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
42     __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
43     ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
44     const char* c_str() const _NOEXCEPT {return str_;}
45 };
46 
47 __libcpp_nmstr::__libcpp_nmstr(const char* msg)
48 {
49     std::size_t len = strlen(msg);
50     str_ = new char[len + 1 + offset];
51     unused_t* c = (unused_t*)str_;
52     c[0] = c[1] = len;
53     str_ += offset;
54     count() = 0;
55     std::strcpy(const_cast<char*>(c_str()), msg);
56 }
57 
58 inline
59 __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
60     : str_(s.str_)
61 {
62     __sync_add_and_fetch(&count(), 1);
63 }
64 
65 __libcpp_nmstr&
66 __libcpp_nmstr::operator=(const __libcpp_nmstr& s)
67 {
68     const char* p = str_;
69     str_ = s.str_;
70     __sync_add_and_fetch(&count(), 1);
71     if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
72         delete [] (p-offset);
73     return *this;
74 }
75 
76 inline
77 __libcpp_nmstr::~__libcpp_nmstr()
78 {
79     if (__sync_add_and_fetch(&count(), -1) < 0)
80         delete [] (str_ - offset);
81 }
82 
83 }
84 
85 #pragma GCC visibility pop
86 
87 namespace std  // purposefully not using versioning namespace
88 {
89 
90 logic_error::logic_error(const string& msg)
91 {
92     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
93     ::new(&s) __libcpp_nmstr(msg.c_str());
94 }
95 
96 logic_error::logic_error(const char* msg)
97 {
98     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
99     ::new(&s) __libcpp_nmstr(msg);
100 }
101 
102 logic_error::logic_error(const logic_error& le) _NOEXCEPT
103 {
104     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
105     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
106 }
107 
108 logic_error&
109 logic_error::operator=(const logic_error& le) _NOEXCEPT
110 {
111     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
112     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
113     s1 = s2;
114     return *this;
115 }
116 
117 #ifndef _LIBCPPABI_VERSION
118 
119 logic_error::~logic_error() _NOEXCEPT
120 {
121     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
122     s.~__libcpp_nmstr();
123 }
124 
125 const char*
126 logic_error::what() const _NOEXCEPT
127 {
128     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
129     return s.c_str();
130 }
131 
132 #endif
133 
134 runtime_error::runtime_error(const string& msg)
135 {
136     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
137     ::new(&s) __libcpp_nmstr(msg.c_str());
138 }
139 
140 runtime_error::runtime_error(const char* msg)
141 {
142     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
143     ::new(&s) __libcpp_nmstr(msg);
144 }
145 
146 runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
147 {
148     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
149     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
150 }
151 
152 runtime_error&
153 runtime_error::operator=(const runtime_error& le) _NOEXCEPT
154 {
155     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
156     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
157     s1 = s2;
158     return *this;
159 }
160 
161 #ifndef _LIBCPPABI_VERSION
162 
163 runtime_error::~runtime_error() _NOEXCEPT
164 {
165     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166     s.~__libcpp_nmstr();
167 }
168 
169 const char*
170 runtime_error::what() const _NOEXCEPT
171 {
172     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
173     return s.c_str();
174 }
175 
176 domain_error::~domain_error() _NOEXCEPT {}
177 invalid_argument::~invalid_argument() _NOEXCEPT {}
178 length_error::~length_error() _NOEXCEPT {}
179 out_of_range::~out_of_range() _NOEXCEPT {}
180 
181 range_error::~range_error() _NOEXCEPT {}
182 overflow_error::~overflow_error() _NOEXCEPT {}
183 underflow_error::~underflow_error() _NOEXCEPT {}
184 
185 #endif
186 
187 }  // std
188