blob: 9fa4f593137a2cc693b13852780ec8c32b826b97 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:161//===------------------------ stdexcept.cpp -------------------------------===//
2//
Howard Hinnant5b08a8a2010-05-11 21:36:013// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:164//
Howard Hinnant412dbeb2010-11-16 22:09:025// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnant3e519522010-05-11 19:42:167//
8//===----------------------------------------------------------------------===//
9
10#include "stdexcept"
11#include "new"
12#include "string"
13#include <cstdlib>
14#include <cstring>
15#include <cstdint>
16#include <cstddef>
17#include "system_error"
Richard Smith11ffde32012-04-19 01:36:1218
19// Use <cxxabi.h> to determine whether we're linking against libc++abi.
20#if __has_include(<cxxabi.h>)
Howard Hinnantf95d9f02012-02-17 19:24:4221#include <cxxabi.h>
Richard Smith11ffde32012-04-19 01:36:1222#endif
Howard Hinnant3e519522010-05-11 19:42:1623
24// Note: optimize for size
25
26#pragma GCC visibility push(hidden)
27
28namespace
29{
30
31class __libcpp_nmstr
32{
33private:
34 const char* str_;
35
36 typedef std::size_t unused_t;
37 typedef std::int32_t count_t;
38
39 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
40 sizeof(count_t));
41
Howard Hinnanta62f2892011-05-26 19:48:0142 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
Howard Hinnant3e519522010-05-11 19:42:1643public:
44 explicit __libcpp_nmstr(const char* msg);
45 __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
46 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
47 ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
Howard Hinnanta62f2892011-05-26 19:48:0148 const char* c_str() const _NOEXCEPT {return str_;}
Howard Hinnant3e519522010-05-11 19:42:1649};
50
51__libcpp_nmstr::__libcpp_nmstr(const char* msg)
52{
53 std::size_t len = strlen(msg);
54 str_ = new char[len + 1 + offset];
55 unused_t* c = (unused_t*)str_;
56 c[0] = c[1] = len;
57 str_ += offset;
58 count() = 0;
59 std::strcpy(const_cast<char*>(c_str()), msg);
60}
61
62inline
63__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
64 : str_(s.str_)
65{
Howard Hinnant128ba712010-05-24 17:49:4166 __sync_add_and_fetch(&count(), 1);
Howard Hinnant3e519522010-05-11 19:42:1667}
68
69__libcpp_nmstr&
70__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
71{
72 const char* p = str_;
73 str_ = s.str_;
Howard Hinnant128ba712010-05-24 17:49:4174 __sync_add_and_fetch(&count(), 1);
75 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
Howard Hinnant3e519522010-05-11 19:42:1676 delete [] (p-offset);
77 return *this;
78}
79
80inline
81__libcpp_nmstr::~__libcpp_nmstr()
82{
Howard Hinnant128ba712010-05-24 17:49:4183 if (__sync_add_and_fetch(&count(), -1) < 0)
Howard Hinnant3e519522010-05-11 19:42:1684 delete [] (str_ - offset);
85}
86
87}
88
Daniel Dunbar0a779b92010-09-04 03:15:5189#pragma GCC visibility pop
Howard Hinnant3e519522010-05-11 19:42:1690
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
Howard Hinnanta62f2892011-05-26 19:48:01106logic_error::logic_error(const logic_error& le) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16107{
108 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
109 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
110}
111
112logic_error&
Howard Hinnanta62f2892011-05-26 19:48:01113logic_error::operator=(const logic_error& le) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16114{
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
Howard Hinnantf95d9f02012-02-17 19:24:42121#ifndef _LIBCPPABI_VERSION
122
Howard Hinnanta62f2892011-05-26 19:48:01123logic_error::~logic_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16124{
125 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
126 s.~__libcpp_nmstr();
127}
128
129const char*
Howard Hinnanta62f2892011-05-26 19:48:01130logic_error::what() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16131{
132 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
133 return s.c_str();
134}
135
Howard Hinnantf95d9f02012-02-17 19:24:42136#endif
137
Howard Hinnant3e519522010-05-11 19:42:16138runtime_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
Howard Hinnanta62f2892011-05-26 19:48:01150runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16151{
152 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
153 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
154}
155
156runtime_error&
Howard Hinnanta62f2892011-05-26 19:48:01157runtime_error::operator=(const runtime_error& le) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16158{
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
Howard Hinnantf95d9f02012-02-17 19:24:42165#ifndef _LIBCPPABI_VERSION
166
Howard Hinnanta62f2892011-05-26 19:48:01167runtime_error::~runtime_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16168{
169 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
170 s.~__libcpp_nmstr();
171}
172
173const char*
Howard Hinnanta62f2892011-05-26 19:48:01174runtime_error::what() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16175{
176 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
177 return s.c_str();
178}
179
Howard Hinnanta62f2892011-05-26 19:48:01180domain_error::~domain_error() _NOEXCEPT {}
181invalid_argument::~invalid_argument() _NOEXCEPT {}
182length_error::~length_error() _NOEXCEPT {}
183out_of_range::~out_of_range() _NOEXCEPT {}
Howard Hinnant3e519522010-05-11 19:42:16184
Howard Hinnanta62f2892011-05-26 19:48:01185range_error::~range_error() _NOEXCEPT {}
186overflow_error::~overflow_error() _NOEXCEPT {}
187underflow_error::~underflow_error() _NOEXCEPT {}
Howard Hinnant3e519522010-05-11 19:42:16188
Howard Hinnantf95d9f02012-02-17 19:24:42189#endif
190
Howard Hinnant3e519522010-05-11 19:42:16191} // std