stdexcept.cpp revision 232950
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
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 _NOEXCEPT {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 _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
58inline
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
76inline
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
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) _NOEXCEPT
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) _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
119logic_error::~logic_error() _NOEXCEPT
120{
121    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
122    s.~__libcpp_nmstr();
123}
124
125const char*
126logic_error::what() const _NOEXCEPT
127{
128    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
129    return s.c_str();
130}
131
132#endif
133
134runtime_error::runtime_error(const string& msg)
135{
136    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
137    ::new(&s) __libcpp_nmstr(msg.c_str());
138}
139
140runtime_error::runtime_error(const char* msg)
141{
142    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
143    ::new(&s) __libcpp_nmstr(msg);
144}
145
146runtime_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
152runtime_error&
153runtime_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
163runtime_error::~runtime_error() _NOEXCEPT
164{
165    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166    s.~__libcpp_nmstr();
167}
168
169const char*
170runtime_error::what() const _NOEXCEPT
171{
172    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
173    return s.c_str();
174}
175
176domain_error::~domain_error() _NOEXCEPT {}
177invalid_argument::~invalid_argument() _NOEXCEPT {}
178length_error::~length_error() _NOEXCEPT {}
179out_of_range::~out_of_range() _NOEXCEPT {}
180
181range_error::~range_error() _NOEXCEPT {}
182overflow_error::~overflow_error() _NOEXCEPT {}
183underflow_error::~underflow_error() _NOEXCEPT {}
184
185#endif
186
187}  // std
188