stdexcept.cpp revision 227825
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
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
37    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
38public:
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;
43    const char* c_str() const _NOEXCEPT {return str_;}
44};
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{
61    __sync_add_and_fetch(&count(), 1);
62}
63
64__libcpp_nmstr&
65__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
66{
67    const char* p = str_;
68    str_ = s.str_;
69    __sync_add_and_fetch(&count(), 1);
70    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
71        delete [] (p-offset);
72    return *this;
73}
74
75inline
76__libcpp_nmstr::~__libcpp_nmstr()
77{
78    if (__sync_add_and_fetch(&count(), -1) < 0)
79        delete [] (str_ - offset);
80}
81
82}
83
84#pragma GCC visibility pop
85
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
101logic_error::logic_error(const logic_error& le) _NOEXCEPT
102{
103    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
104    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
105}
106
107logic_error&
108logic_error::operator=(const logic_error& le) _NOEXCEPT
109{
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
116logic_error::~logic_error() _NOEXCEPT
117{
118    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
119    s.~__libcpp_nmstr();
120}
121
122const char*
123logic_error::what() const _NOEXCEPT
124{
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
141runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
142{
143    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
144    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
145}
146
147runtime_error&
148runtime_error::operator=(const runtime_error& le) _NOEXCEPT
149{
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
156runtime_error::~runtime_error() _NOEXCEPT
157{
158    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
159    s.~__libcpp_nmstr();
160}
161
162const char*
163runtime_error::what() const _NOEXCEPT
164{
165    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166    return s.c_str();
167}
168
169domain_error::~domain_error() _NOEXCEPT {}
170invalid_argument::~invalid_argument() _NOEXCEPT {}
171length_error::~length_error() _NOEXCEPT {}
172out_of_range::~out_of_range() _NOEXCEPT {}
173
174range_error::~range_error() _NOEXCEPT {}
175overflow_error::~overflow_error() _NOEXCEPT {}
176underflow_error::~underflow_error() _NOEXCEPT {}
177
178}  // std
179