blob: e936188895a4998485136ee4b9a8e9c3093b0769 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------ stdexcept.cpp -------------------------------===//
2//
3// ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊThe LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. 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 <libkern/OSAtomic.h>
19
20// Note: optimize for size
21
22#pragma GCC visibility push(hidden)
23
24namespace
25{
26
27class __libcpp_nmstr
28{
29private:
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 throw() {return (count_t&)(*(str_ - sizeof(count_t)));}
39public:
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 throw() {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
58inline
59__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
60 : str_(s.str_)
61{
62 OSAtomicIncrement32Barrier(&count());
63}
64
65__libcpp_nmstr&
66__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
67{
68 const char* p = str_;
69 str_ = s.str_;
70 OSAtomicIncrement32Barrier(&count());
71 if (OSAtomicDecrement32((count_t*)(p-sizeof(count_t))) < 0)
72 delete [] (p-offset);
73 return *this;
74}
75
76inline
77__libcpp_nmstr::~__libcpp_nmstr()
78{
79 if (OSAtomicDecrement32(&count()) < 0)
80 delete [] (str_ - offset);
81}
82
83}
84
85#pragma GCC visiblity pop
86
87namespace std // purposefully not using versioning namespace
88{
89
90logic_error::logic_error(const string& msg)
91{
92 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
93 ::new(&s) __libcpp_nmstr(msg.c_str());
94}
95
96logic_error::logic_error(const char* msg)
97{
98 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
99 ::new(&s) __libcpp_nmstr(msg);
100}
101
102logic_error::logic_error(const logic_error& le) throw()
103{
104 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
105 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
106}
107
108logic_error&
109logic_error::operator=(const logic_error& le) throw()
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
117logic_error::~logic_error() throw()
118{
119 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
120 s.~__libcpp_nmstr();
121}
122
123const char*
124logic_error::what() const throw()
125{
126 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
127 return s.c_str();
128}
129
130runtime_error::runtime_error(const string& msg)
131{
132 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
133 ::new(&s) __libcpp_nmstr(msg.c_str());
134}
135
136runtime_error::runtime_error(const char* msg)
137{
138 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
139 ::new(&s) __libcpp_nmstr(msg);
140}
141
142runtime_error::runtime_error(const runtime_error& le) throw()
143{
144 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
145 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
146}
147
148runtime_error&
149runtime_error::operator=(const runtime_error& le) throw()
150{
151 __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
152 const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
153 s1 = s2;
154 return *this;
155}
156
157runtime_error::~runtime_error() throw()
158{
159 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
160 s.~__libcpp_nmstr();
161}
162
163const char*
164runtime_error::what() const throw()
165{
166 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
167 return s.c_str();
168}
169
170domain_error::~domain_error() throw() {}
171invalid_argument::~invalid_argument() throw() {}
172length_error::~length_error() throw() {}
173out_of_range::~out_of_range() throw() {}
174
175range_error::~range_error() throw() {}
176overflow_error::~overflow_error() throw() {}
177underflow_error::~underflow_error() throw() {}
178
179} // std