stdexcept.cpp revision 262801
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
31262801Sdim#if ! defined(_LIBCPP_MSVC)
32227825Stheraven#pragma GCC visibility push(hidden)
33262801Sdim#endif
34227825Stheraven
35227825Stheravennamespace
36227825Stheraven{
37227825Stheraven
38227825Stheravenclass __libcpp_nmstr
39227825Stheraven{
40227825Stheravenprivate:
41227825Stheraven    const char* str_;
42227825Stheraven
43227825Stheraven    typedef std::size_t unused_t;
44241903Sdim    typedef std::ptrdiff_t count_t;
45227825Stheraven
46227825Stheraven    static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
47227825Stheraven                                                                       sizeof(count_t));
48227825Stheraven
49227825Stheraven    count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
50227825Stheravenpublic:
51227825Stheraven    explicit __libcpp_nmstr(const char* msg);
52262801Sdim    __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT;
53262801Sdim    __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT;
54262801Sdim    ~__libcpp_nmstr();
55227825Stheraven    const char* c_str() const _NOEXCEPT {return str_;}
56227825Stheraven};
57227825Stheraven
58227825Stheraven__libcpp_nmstr::__libcpp_nmstr(const char* msg)
59227825Stheraven{
60227825Stheraven    std::size_t len = strlen(msg);
61227825Stheraven    str_ = new char[len + 1 + offset];
62227825Stheraven    unused_t* c = (unused_t*)str_;
63227825Stheraven    c[0] = c[1] = len;
64227825Stheraven    str_ += offset;
65227825Stheraven    count() = 0;
66253159Stheraven    std::memcpy(const_cast<char*>(c_str()), msg, len + 1);
67227825Stheraven}
68227825Stheraven
69227825Stheraveninline
70262801Sdim__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT
71227825Stheraven    : str_(s.str_)
72227825Stheraven{
73227825Stheraven    __sync_add_and_fetch(&count(), 1);
74227825Stheraven}
75227825Stheraven
76227825Stheraven__libcpp_nmstr&
77262801Sdim__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT
78227825Stheraven{
79227825Stheraven    const char* p = str_;
80227825Stheraven    str_ = s.str_;
81227825Stheraven    __sync_add_and_fetch(&count(), 1);
82241903Sdim    if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0)
83227825Stheraven        delete [] (p-offset);
84227825Stheraven    return *this;
85227825Stheraven}
86227825Stheraven
87227825Stheraveninline
88227825Stheraven__libcpp_nmstr::~__libcpp_nmstr()
89227825Stheraven{
90241903Sdim    if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
91227825Stheraven        delete [] (str_ - offset);
92227825Stheraven}
93227825Stheraven
94227825Stheraven}
95227825Stheraven
96262801Sdim#if ! defined(_LIBCPP_MSVC)
97227825Stheraven#pragma GCC visibility pop
98262801Sdim#endif
99227825Stheraven
100227825Stheravennamespace std  // purposefully not using versioning namespace
101227825Stheraven{
102227825Stheraven
103227825Stheravenlogic_error::logic_error(const string& msg)
104227825Stheraven{
105227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
106227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
107227825Stheraven}
108227825Stheraven
109227825Stheravenlogic_error::logic_error(const char* msg)
110227825Stheraven{
111227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
112227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
113227825Stheraven}
114227825Stheraven
115227825Stheravenlogic_error::logic_error(const logic_error& le) _NOEXCEPT
116227825Stheraven{
117227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
118227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
119227825Stheraven}
120227825Stheraven
121227825Stheravenlogic_error&
122227825Stheravenlogic_error::operator=(const logic_error& le) _NOEXCEPT
123227825Stheraven{
124227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
125227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
126227825Stheraven    s1 = s2;
127227825Stheraven    return *this;
128227825Stheraven}
129227825Stheraven
130262801Sdim#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX)
131232950Stheraven
132227825Stheravenlogic_error::~logic_error() _NOEXCEPT
133227825Stheraven{
134227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
135227825Stheraven    s.~__libcpp_nmstr();
136227825Stheraven}
137227825Stheraven
138227825Stheravenconst char*
139227825Stheravenlogic_error::what() const _NOEXCEPT
140227825Stheraven{
141227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
142227825Stheraven    return s.c_str();
143227825Stheraven}
144227825Stheraven
145232950Stheraven#endif
146232950Stheraven
147227825Stheravenruntime_error::runtime_error(const string& msg)
148227825Stheraven{
149227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
150227825Stheraven    ::new(&s) __libcpp_nmstr(msg.c_str());
151227825Stheraven}
152227825Stheraven
153227825Stheravenruntime_error::runtime_error(const char* msg)
154227825Stheraven{
155227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
156227825Stheraven    ::new(&s) __libcpp_nmstr(msg);
157227825Stheraven}
158227825Stheraven
159227825Stheravenruntime_error::runtime_error(const runtime_error& le) _NOEXCEPT
160227825Stheraven{
161227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
162227825Stheraven    ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
163227825Stheraven}
164227825Stheraven
165227825Stheravenruntime_error&
166227825Stheravenruntime_error::operator=(const runtime_error& le) _NOEXCEPT
167227825Stheraven{
168227825Stheraven    __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
169227825Stheraven    const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
170227825Stheraven    s1 = s2;
171227825Stheraven    return *this;
172227825Stheraven}
173227825Stheraven
174262801Sdim#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX)
175232950Stheraven
176227825Stheravenruntime_error::~runtime_error() _NOEXCEPT
177227825Stheraven{
178227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
179227825Stheraven    s.~__libcpp_nmstr();
180227825Stheraven}
181227825Stheraven
182227825Stheravenconst char*
183227825Stheravenruntime_error::what() const _NOEXCEPT
184227825Stheraven{
185227825Stheraven    __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
186227825Stheraven    return s.c_str();
187227825Stheraven}
188227825Stheraven
189227825Stheravendomain_error::~domain_error() _NOEXCEPT {}
190227825Stheraveninvalid_argument::~invalid_argument() _NOEXCEPT {}
191227825Stheravenlength_error::~length_error() _NOEXCEPT {}
192227825Stheravenout_of_range::~out_of_range() _NOEXCEPT {}
193227825Stheraven
194227825Stheravenrange_error::~range_error() _NOEXCEPT {}
195227825Stheravenoverflow_error::~overflow_error() _NOEXCEPT {}
196227825Stheravenunderflow_error::~underflow_error() _NOEXCEPT {}
197227825Stheraven
198232950Stheraven#endif
199232950Stheraven
200227825Stheraven}  // std
201