stdexcept.cpp revision 227825
1227825Stheraven//===------------------------ stdexcept.cpp -------------------------------===//
2227825Stheraven//
3227825Stheraven//                     The LLVM Compiler Infrastructure
4227825Stheraven//
5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
6227825Stheraven// Source Licenses. See LICENSE.TXT for details.
7227825Stheraven//
8227825Stheraven//===----------------------------------------------------------------------===//
9227825Stheraven
10227825Stheraven#include "stdexcept"
11227825Stheraven#include "new"
12227825Stheraven#include "string"
13227825Stheraven#include <cstdlib>
14227825Stheraven#include <cstring>
15227825Stheraven#include <cstdint>
16227825Stheraven#include <cstddef>
17227825Stheraven#include "system_error"
18234976Stheraven
19241903Sdim// Note:  optimize for size
20241903Sdim
21241903Sdim#pragma GCC visibility push(hidden)
22241903Sdim
23241903Sdimnamespace
24232950Stheraven{
25241903Sdim
26241903Sdimclass __libcpp_nmstr
27234976Stheraven{
28227825Stheravenprivate:
29227825Stheraven    const char* str_;
30227825Stheraven
31227825Stheraven    typedef std::size_t unused_t;
32227825Stheraven    typedef std::int32_t count_t;
33227825Stheraven
34227825Stheraven    static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
35227825Stheraven                                                                       sizeof(count_t));
36227825Stheraven
37227825Stheraven    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
38227825Stheravenpublic:
39227825Stheraven    explicit __libcpp_nmstr(const char* msg);
40227825Stheraven    __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
41227825Stheraven    __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
42241903Sdim    ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
43227825Stheraven    const char* c_str() const _NOEXCEPT {return str_;}
44227825Stheraven};
45227825Stheraven
46227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg)
47227825Stheraven{
48227825Stheraven    std::size_t len = strlen(msg);
49227825Stheraven    str_ = new char[len + 1 + offset];
50227825Stheraven    unused_t* c = (unused_t*)str_;
51227825Stheraven    c[0] = c[1] = len;
52227825Stheraven    str_ += offset;
53227825Stheraven    count() = 0;
54227825Stheraven    std::strcpy(const_cast<char*>(c_str()), msg);
55227825Stheraven}
56227825Stheraven
57227825Stheraveninline
58227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
59227825Stheraven    : str_(s.str_)
60227825Stheraven{
61227825Stheraven    __sync_add_and_fetch(&count(), 1);
62227825Stheraven}
63227825Stheraven
64227825Stheraven__libcpp_nmstr&
65227825Stheraven__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
66227825Stheraven{
67227825Stheraven    const char* p = str_;
68227825Stheraven    str_ = s.str_;
69227825Stheraven    __sync_add_and_fetch(&count(), 1);
70227825Stheraven    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
71227825Stheraven        delete [] (p-offset);
72227825Stheraven    return *this;
73227825Stheraven}
74227825Stheraven
75227825Stheraveninline
76227825Stheraven__libcpp_nmstr::~__libcpp_nmstr()
77227825Stheraven{
78227825Stheraven    if (__sync_add_and_fetch(&count(), -1) < 0)
79227825Stheraven        delete [] (str_ - offset);
80241903Sdim}
81227825Stheraven
82227825Stheraven}
83227825Stheraven
84227825Stheraven#pragma GCC visibility pop
85227825Stheraven
86227825Stheravennamespace std  // purposefully not using versioning namespace
87227825Stheraven{
88241903Sdim
89227825Stheravenlogic_error::logic_error(const string& msg)
90227825Stheraven{
91227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
92227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
93227825Stheraven}
94227825Stheraven
95227825Stheravenlogic_error::logic_error(const char* msg)
96227825Stheraven{
97227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
98227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
99227825Stheraven}
100227825Stheraven
101227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT
102227825Stheraven{
103227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
104227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
105227825Stheraven}
106227825Stheraven
107227825Stheravenlogic_error&
108227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT
109227825Stheraven{
110227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
111227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
112227825Stheraven    s1 = s2;
113227825Stheraven    return *this;
114227825Stheraven}
115227825Stheraven
116227825Stheravenlogic_error::~logic_error() _NOEXCEPT
117227825Stheraven{
118227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
119227825Stheraven    s.~__libcpp_nmstr();
120227825Stheraven}
121227825Stheraven
122227825Stheravenconst char*
123227825Stheravenlogic_error::what() const _NOEXCEPT
124227825Stheraven{
125227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
126232950Stheraven    return s.c_str();
127232950Stheraven}
128227825Stheraven
129227825Stheravenruntime_error::runtime_error(const string& msg)
130227825Stheraven{
131227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
132227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
133227825Stheraven}
134227825Stheraven
135227825Stheravenruntime_error::runtime_error(const char* msg)
136227825Stheraven{
137227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
138227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
139227825Stheraven}
140227825Stheraven
141232950Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT
142232950Stheraven{
143227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
144227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
145227825Stheraven}
146227825Stheraven
147227825Stheravenruntime_error&
148227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT
149227825Stheraven{
150227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
151227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
152227825Stheraven    s1 = s2;
153227825Stheraven    return *this;
154227825Stheraven}
155227825Stheraven
156227825Stheravenruntime_error::~runtime_error() _NOEXCEPT
157227825Stheraven{
158227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
159227825Stheraven    s.~__libcpp_nmstr();
160227825Stheraven}
161227825Stheraven
162227825Stheravenconst char*
163227825Stheravenruntime_error::what() const _NOEXCEPT
164227825Stheraven{
165227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166227825Stheraven    return s.c_str();
167227825Stheraven}
168227825Stheraven
169227825Stheravendomain_error::~domain_error() _NOEXCEPT {}
170232950Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {}
171232950Stheravenlength_error::~length_error() _NOEXCEPT {}
172227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {}
173227825Stheraven
174227825Stheravenrange_error::~range_error() _NOEXCEPT {}
175227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {}
176227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {}
177227825Stheraven
178227825Stheraven}  // std
179227825Stheraven