blob: 28917887587ecf666a3340837cdbb2ba129d85e3 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------ stdexcept.cpp -------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
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"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000018
19// Note: optimize for size
20
21#pragma GCC visibility push(hidden)
22
23namespace
24{
25
26class __libcpp_nmstr
27{
28private:
29 const char* str_;
30
31 typedef std::size_t unused_t;
32 typedef std::int32_t count_t;
33
34 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
35 sizeof(count_t));
36
Howard Hinnant1e15fd12011-05-26 19:48:01 +000037 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038public:
39 explicit __libcpp_nmstr(const char* msg);
40 __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
41 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
42 ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
Howard Hinnant1e15fd12011-05-26 19:48:01 +000043 const char* c_str() const _NOEXCEPT {return str_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000044};
45
46__libcpp_nmstr::__libcpp_nmstr(const char* msg)
47{
48 std::size_t len = strlen(msg);
49 str_ = new char[len + 1 + offset];
50 unused_t* c = (unused_t*)str_;
51 c[0] = c[1] = len;
52 str_ += offset;
53 count() = 0;
54 std::strcpy(const_cast<char*>(c_str()), msg);
55}
56
57inline
58__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
59 : str_(s.str_)
60{
Howard Hinnantadff4892010-05-24 17:49:41 +000061 __sync_add_and_fetch(&count(), 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000062}
63
64__libcpp_nmstr&
65__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
66{
67 const char* p = str_;
68 str_ = s.str_;
Howard Hinnantadff4892010-05-24 17:49:41 +000069 __sync_add_and_fetch(&count(), 1);
70 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000071 delete [] (p-offset);
72 return *this;
73}
74
75inline
76__libcpp_nmstr::~__libcpp_nmstr()
77{
Howard Hinnantadff4892010-05-24 17:49:41 +000078 if (__sync_add_and_fetch(&count(), -1) < 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000079 delete [] (str_ - offset);
80}
81
82}
83
Daniel Dunbar04acaca2010-09-04 03:15:51 +000084#pragma GCC visibility pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000085
86namespace std // purposefully not using versioning namespace
87{
88
89logic_error::logic_error(const string& msg)
90{
91 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
92 ::new(&s) __libcpp_nmstr(msg.c_str());
93}
94
95logic_error::logic_error(const char* msg)
96{
97 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
98 ::new(&s) __libcpp_nmstr(msg);
99}
100
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000101logic_error::logic_error(const logic_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000102{
103 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
104 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
105}
106
107logic_error&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000108logic_error::operator=(const logic_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000109{
110 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
111 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
112 s1 = s2;
113 return *this;
114}
115
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000116logic_error::~logic_error() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000117{
118 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
119 s.~__libcpp_nmstr();
120}
121
122const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000123logic_error::what() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124{
125 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
126 return s.c_str();
127}
128
129runtime_error::runtime_error(const string& msg)
130{
131 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
132 ::new(&s) __libcpp_nmstr(msg.c_str());
133}
134
135runtime_error::runtime_error(const char* msg)
136{
137 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
138 ::new(&s) __libcpp_nmstr(msg);
139}
140
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000141runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000142{
143 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
144 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
145}
146
147runtime_error&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000148runtime_error::operator=(const runtime_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000149{
150 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
151 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
152 s1 = s2;
153 return *this;
154}
155
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000156runtime_error::~runtime_error() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000157{
158 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
159 s.~__libcpp_nmstr();
160}
161
162const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000163runtime_error::what() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164{
165 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166 return s.c_str();
167}
168
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000169domain_error::~domain_error() _NOEXCEPT {}
170invalid_argument::~invalid_argument() _NOEXCEPT {}
171length_error::~length_error() _NOEXCEPT {}
172out_of_range::~out_of_range() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000173
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000174range_error::~range_error() _NOEXCEPT {}
175overflow_error::~overflow_error() _NOEXCEPT {}
176underflow_error::~underflow_error() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000177
178} // std