stdexcept.cpp revision 232950
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"
18232950Stheraven#include <cxxabi.h>
19227825Stheraven
20227825Stheraven// Note:  optimize for size
21227825Stheraven
22227825Stheraven#pragma GCC visibility push(hidden)
23227825Stheraven
24227825Stheravennamespace
25227825Stheraven{
26227825Stheraven
27227825Stheravenclass __libcpp_nmstr
28227825Stheraven{
29227825Stheravenprivate:
30227825Stheraven    const char* str_;
31227825Stheraven
32227825Stheraven    typedef std::size_t unused_t;
33227825Stheraven    typedef std::int32_t count_t;
34227825Stheraven
35227825Stheraven    static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
36227825Stheraven                                                                       sizeof(count_t));
37227825Stheraven
38227825Stheraven    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
39227825Stheravenpublic:
40227825Stheraven    explicit __libcpp_nmstr(const char* msg);
41227825Stheraven    __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
42227825Stheraven    __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
43227825Stheraven    ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
44227825Stheraven    const char* c_str() const _NOEXCEPT {return str_;}
45227825Stheraven};
46227825Stheraven
47227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg)
48227825Stheraven{
49227825Stheraven    std::size_t len = strlen(msg);
50227825Stheraven    str_ = new char[len + 1 + offset];
51227825Stheraven    unused_t* c = (unused_t*)str_;
52227825Stheraven    c[0] = c[1] = len;
53227825Stheraven    str_ += offset;
54227825Stheraven    count() = 0;
55227825Stheraven    std::strcpy(const_cast<char*>(c_str()), msg);
56227825Stheraven}
57227825Stheraven
58227825Stheraveninline
59227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
60227825Stheraven    : str_(s.str_)
61227825Stheraven{
62227825Stheraven    __sync_add_and_fetch(&count(), 1);
63227825Stheraven}
64227825Stheraven
65227825Stheraven__libcpp_nmstr&
66227825Stheraven__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
67227825Stheraven{
68227825Stheraven    const char* p = str_;
69227825Stheraven    str_ = s.str_;
70227825Stheraven    __sync_add_and_fetch(&count(), 1);
71227825Stheraven    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
72227825Stheraven        delete [] (p-offset);
73227825Stheraven    return *this;
74227825Stheraven}
75227825Stheraven
76227825Stheraveninline
77227825Stheraven__libcpp_nmstr::~__libcpp_nmstr()
78227825Stheraven{
79227825Stheraven    if (__sync_add_and_fetch(&count(), -1) < 0)
80227825Stheraven        delete [] (str_ - offset);
81227825Stheraven}
82227825Stheraven
83227825Stheraven}
84227825Stheraven
85227825Stheraven#pragma GCC visibility pop
86227825Stheraven
87227825Stheravennamespace std  // purposefully not using versioning namespace
88227825Stheraven{
89227825Stheraven
90227825Stheravenlogic_error::logic_error(const string& msg)
91227825Stheraven{
92227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
93227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
94227825Stheraven}
95227825Stheraven
96227825Stheravenlogic_error::logic_error(const char* msg)
97227825Stheraven{
98227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
99227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
100227825Stheraven}
101227825Stheraven
102227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT
103227825Stheraven{
104227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
105227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
106227825Stheraven}
107227825Stheraven
108227825Stheravenlogic_error&
109227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT
110227825Stheraven{
111227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
112227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
113227825Stheraven    s1 = s2;
114227825Stheraven    return *this;
115227825Stheraven}
116227825Stheraven
117232950Stheraven#ifndef _LIBCPPABI_VERSION
118232950Stheraven
119227825Stheravenlogic_error::~logic_error() _NOEXCEPT
120227825Stheraven{
121227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
122227825Stheraven    s.~__libcpp_nmstr();
123227825Stheraven}
124227825Stheraven
125227825Stheravenconst char*
126227825Stheravenlogic_error::what() const _NOEXCEPT
127227825Stheraven{
128227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
129227825Stheraven    return s.c_str();
130227825Stheraven}
131227825Stheraven
132232950Stheraven#endif
133232950Stheraven
134227825Stheravenruntime_error::runtime_error(const string& msg)
135227825Stheraven{
136227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
137227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
138227825Stheraven}
139227825Stheraven
140227825Stheravenruntime_error::runtime_error(const char* msg)
141227825Stheraven{
142227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
143227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
144227825Stheraven}
145227825Stheraven
146227825Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT
147227825Stheraven{
148227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
149227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
150227825Stheraven}
151227825Stheraven
152227825Stheravenruntime_error&
153227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT
154227825Stheraven{
155227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
156227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
157227825Stheraven    s1 = s2;
158227825Stheraven    return *this;
159227825Stheraven}
160227825Stheraven
161232950Stheraven#ifndef _LIBCPPABI_VERSION
162232950Stheraven
163227825Stheravenruntime_error::~runtime_error() _NOEXCEPT
164227825Stheraven{
165227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
166227825Stheraven    s.~__libcpp_nmstr();
167227825Stheraven}
168227825Stheraven
169227825Stheravenconst char*
170227825Stheravenruntime_error::what() const _NOEXCEPT
171227825Stheraven{
172227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
173227825Stheraven    return s.c_str();
174227825Stheraven}
175227825Stheraven
176227825Stheravendomain_error::~domain_error() _NOEXCEPT {}
177227825Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {}
178227825Stheravenlength_error::~length_error() _NOEXCEPT {}
179227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {}
180227825Stheraven
181227825Stheravenrange_error::~range_error() _NOEXCEPT {}
182227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {}
183227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {}
184227825Stheraven
185232950Stheraven#endif
186232950Stheraven
187227825Stheraven}  // std
188