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#ifndef __has_include
20241903Sdim#define __has_include(inc) 0
21241903Sdim#endif
22241903Sdim
23249998Sdim#ifdef __APPLE__
24232950Stheraven#include <cxxabi.h>
25241903Sdim#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
26241903Sdim#include <cxxabi.h>
27234976Stheraven#endif
28227825Stheraven
29227825Stheraven// Note:  optimize for size
30227825Stheraven
31227825Stheraven#pragma GCC visibility push(hidden)
32227825Stheraven
33227825Stheravennamespace
34227825Stheraven{
35227825Stheraven
36227825Stheravenclass __libcpp_nmstr
37227825Stheraven{
38227825Stheravenprivate:
39227825Stheraven    const char* str_;
40227825Stheraven
41227825Stheraven    typedef std::size_t unused_t;
42241903Sdim    typedef std::ptrdiff_t count_t;
43227825Stheraven
44227825Stheraven    static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
45227825Stheraven                                                                       sizeof(count_t));
46227825Stheraven
47227825Stheraven    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
48227825Stheravenpublic:
49227825Stheraven    explicit __libcpp_nmstr(const char* msg);
50227825Stheraven    __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
51227825Stheraven    __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
52227825Stheraven    ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
53227825Stheraven    const char* c_str() const _NOEXCEPT {return str_;}
54227825Stheraven};
55227825Stheraven
56227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg)
57227825Stheraven{
58227825Stheraven    std::size_t len = strlen(msg);
59227825Stheraven    str_ = new char[len + 1 + offset];
60227825Stheraven    unused_t* c = (unused_t*)str_;
61227825Stheraven    c[0] = c[1] = len;
62227825Stheraven    str_ += offset;
63227825Stheraven    count() = 0;
64253159Stheraven    std::memcpy(const_cast<char*>(c_str()), msg, len + 1);
65227825Stheraven}
66227825Stheraven
67227825Stheraveninline
68227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
69227825Stheraven    : str_(s.str_)
70227825Stheraven{
71227825Stheraven    __sync_add_and_fetch(&count(), 1);
72227825Stheraven}
73227825Stheraven
74227825Stheraven__libcpp_nmstr&
75227825Stheraven__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
76227825Stheraven{
77227825Stheraven    const char* p = str_;
78227825Stheraven    str_ = s.str_;
79227825Stheraven    __sync_add_and_fetch(&count(), 1);
80241903Sdim    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0)
81227825Stheraven        delete [] (p-offset);
82227825Stheraven    return *this;
83227825Stheraven}
84227825Stheraven
85227825Stheraveninline
86227825Stheraven__libcpp_nmstr::~__libcpp_nmstr()
87227825Stheraven{
88241903Sdim    if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
89227825Stheraven        delete [] (str_ - offset);
90227825Stheraven}
91227825Stheraven
92227825Stheraven}
93227825Stheraven
94227825Stheraven#pragma GCC visibility pop
95227825Stheraven
96227825Stheravennamespace std  // purposefully not using versioning namespace
97227825Stheraven{
98227825Stheraven
99227825Stheravenlogic_error::logic_error(const string& msg)
100227825Stheraven{
101227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
102227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
103227825Stheraven}
104227825Stheraven
105227825Stheravenlogic_error::logic_error(const char* msg)
106227825Stheraven{
107227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
108227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
109227825Stheraven}
110227825Stheraven
111227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT
112227825Stheraven{
113227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
114227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
115227825Stheraven}
116227825Stheraven
117227825Stheravenlogic_error&
118227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT
119227825Stheraven{
120227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
121227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
122227825Stheraven    s1 = s2;
123227825Stheraven    return *this;
124227825Stheraven}
125227825Stheraven
126232950Stheraven#ifndef _LIBCPPABI_VERSION
127232950Stheraven
128227825Stheravenlogic_error::~logic_error() _NOEXCEPT
129227825Stheraven{
130227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
131227825Stheraven    s.~__libcpp_nmstr();
132227825Stheraven}
133227825Stheraven
134227825Stheravenconst char*
135227825Stheravenlogic_error::what() const _NOEXCEPT
136227825Stheraven{
137227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
138227825Stheraven    return s.c_str();
139227825Stheraven}
140227825Stheraven
141232950Stheraven#endif
142232950Stheraven
143227825Stheravenruntime_error::runtime_error(const string& msg)
144227825Stheraven{
145227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
146227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
147227825Stheraven}
148227825Stheraven
149227825Stheravenruntime_error::runtime_error(const char* msg)
150227825Stheraven{
151227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
152227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
153227825Stheraven}
154227825Stheraven
155227825Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT
156227825Stheraven{
157227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
158227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
159227825Stheraven}
160227825Stheraven
161227825Stheravenruntime_error&
162227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT
163227825Stheraven{
164227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
165227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
166227825Stheraven    s1 = s2;
167227825Stheraven    return *this;
168227825Stheraven}
169227825Stheraven
170232950Stheraven#ifndef _LIBCPPABI_VERSION
171232950Stheraven
172227825Stheravenruntime_error::~runtime_error() _NOEXCEPT
173227825Stheraven{
174227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
175227825Stheraven    s.~__libcpp_nmstr();
176227825Stheraven}
177227825Stheraven
178227825Stheravenconst char*
179227825Stheravenruntime_error::what() const _NOEXCEPT
180227825Stheraven{
181227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
182227825Stheraven    return s.c_str();
183227825Stheraven}
184227825Stheraven
185227825Stheravendomain_error::~domain_error() _NOEXCEPT {}
186227825Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {}
187227825Stheravenlength_error::~length_error() _NOEXCEPT {}
188227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {}
189227825Stheraven
190227825Stheravenrange_error::~range_error() _NOEXCEPT {}
191227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {}
192227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {}
193227825Stheraven
194232950Stheraven#endif
195232950Stheraven
196227825Stheraven}  // std
197