stdexcept.cpp revision 234976
1275970Scy//===------------------------ stdexcept.cpp -------------------------------===//
2275970Scy//
3275970Scy//                     The LLVM Compiler Infrastructure
4275970Scy//
5275970Scy// This file is dual licensed under the MIT and the University of Illinois Open
6275970Scy// Source Licenses. See LICENSE.TXT for details.
7275970Scy//
8275970Scy//===----------------------------------------------------------------------===//
9275970Scy
10275970Scy#include "stdexcept"
11275970Scy#include "new"
12275970Scy#include "string"
13275970Scy#include <cstdlib>
14275970Scy#include <cstring>
15275970Scy#include <cstdint>
16275970Scy#include <cstddef>
17275970Scy#include "system_error"
18275970Scy
19275970Scy// Use <cxxabi.h> to determine whether we're linking against libc++abi.
20275970Scy#if __has_include(<cxxabi.h>)
21275970Scy#include <cxxabi.h>
22275970Scy#endif
23275970Scy
24275970Scy// Note:  optimize for size
25275970Scy
26275970Scy#pragma GCC visibility push(hidden)
27275970Scy
28275970Scynamespace
29275970Scy{
30275970Scy
31275970Scyclass __libcpp_nmstr
32275970Scy{
33275970Scyprivate:
34275970Scy    const char* str_;
35275970Scy
36301301Sdelphij    typedef std::size_t unused_t;
37275970Scy    typedef std::int32_t count_t;
38275970Scy
39275970Scy    static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
40275970Scy                                                                       sizeof(count_t));
41275970Scy
42275970Scy    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
43275970Scypublic:
44275970Scy    explicit __libcpp_nmstr(const char* msg);
45275970Scy    __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
46275970Scy    __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
47275970Scy    ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
48275970Scy    const char* c_str() const _NOEXCEPT {return str_;}
49275970Scy};
50275970Scy
51275970Scy__libcpp_nmstr::__libcpp_nmstr(const char* msg)
52275970Scy{
53275970Scy    std::size_t len = strlen(msg);
54275970Scy    str_ = new char[len + 1 + offset];
55275970Scy    unused_t* c = (unused_t*)str_;
56275970Scy    c[0] = c[1] = len;
57275970Scy    str_ += offset;
58275970Scy    count() = 0;
59275970Scy    std::strcpy(const_cast<char*>(c_str()), msg);
60275970Scy}
61275970Scy
62275970Scyinline
63275970Scy__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
64275970Scy    : str_(s.str_)
65275970Scy{
66275970Scy    __sync_add_and_fetch(&count(), 1);
67}
68
69__libcpp_nmstr&
70__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
71{
72    const char* p = str_;
73    str_ = s.str_;
74    __sync_add_and_fetch(&count(), 1);
75    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
76        delete [] (p-offset);
77    return *this;
78}
79
80inline
81__libcpp_nmstr::~__libcpp_nmstr()
82{
83    if (__sync_add_and_fetch(&count(), -1) < 0)
84        delete [] (str_ - offset);
85}
86
87}
88
89#pragma GCC visibility pop
90
91namespace std  // purposefully not using versioning namespace
92{
93
94logic_error::logic_error(const string& msg)
95{
96    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
97    ::new(&s) __libcpp_nmstr(msg.c_str());
98}
99
100logic_error::logic_error(const char* msg)
101{
102    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
103    ::new(&s) __libcpp_nmstr(msg);
104}
105
106logic_error::logic_error(const logic_error& le) _NOEXCEPT
107{
108    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
109    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
110}
111
112logic_error&
113logic_error::operator=(const logic_error& le) _NOEXCEPT
114{
115    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
116    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
117    s1 = s2;
118    return *this;
119}
120
121#ifndef _LIBCPPABI_VERSION
122
123logic_error::~logic_error() _NOEXCEPT
124{
125    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
126    s.~__libcpp_nmstr();
127}
128
129const char*
130logic_error::what() const _NOEXCEPT
131{
132    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
133    return s.c_str();
134}
135
136#endif
137
138runtime_error::runtime_error(const string& msg)
139{
140    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
141    ::new(&s) __libcpp_nmstr(msg.c_str());
142}
143
144runtime_error::runtime_error(const char* msg)
145{
146    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
147    ::new(&s) __libcpp_nmstr(msg);
148}
149
150runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
151{
152    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
153    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
154}
155
156runtime_error&
157runtime_error::operator=(const runtime_error& le) _NOEXCEPT
158{
159    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
160    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
161    s1 = s2;
162    return *this;
163}
164
165#ifndef _LIBCPPABI_VERSION
166
167runtime_error::~runtime_error() _NOEXCEPT
168{
169    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
170    s.~__libcpp_nmstr();
171}
172
173const char*
174runtime_error::what() const _NOEXCEPT
175{
176    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
177    return s.c_str();
178}
179
180domain_error::~domain_error() _NOEXCEPT {}
181invalid_argument::~invalid_argument() _NOEXCEPT {}
182length_error::~length_error() _NOEXCEPT {}
183out_of_range::~out_of_range() _NOEXCEPT {}
184
185range_error::~range_error() _NOEXCEPT {}
186overflow_error::~overflow_error() _NOEXCEPT {}
187underflow_error::~underflow_error() _NOEXCEPT {}
188
189#endif
190
191}  // std
192