blob: 9fa4f593137a2cc693b13852780ec8c32b826b97 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===------------------------ stdexcept.cpp -------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
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 Smithc756f5b2012-04-19 01:36:12 +000018
19// Use <cxxabi.h> to determine whether we're linking against libc++abi.
20#if __has_include(<cxxabi.h>)
Howard Hinnante1642e12012-02-17 19:24:42 +000021#include <cxxabi.h>
Richard Smithc756f5b2012-04-19 01:36:12 +000022#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023
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 Hinnant1e15fd12011-05-26 19:48:01 +000042 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000043public:
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 Hinnant1e15fd12011-05-26 19:48:01 +000048 const char* c_str() const _NOEXCEPT {return str_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000049};
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 Hinnantadff4892010-05-24 17:49:41 +000066 __sync_add_and_fetch(&count(), 1);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000067}
68
69__libcpp_nmstr&
70__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
71{
72 const char* p = str_;
73 str_ = s.str_;
Howard Hinnantadff4892010-05-24 17:49:41 +000074 __sync_add_and_fetch(&count(), 1);
75 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000076 delete [] (p-offset);
77 return *this;
78}
79
80inline
81__libcpp_nmstr::~__libcpp_nmstr()
82{
Howard Hinnantadff4892010-05-24 17:49:41 +000083 if (__sync_add_and_fetch(&count(), -1) < 0)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000084 delete [] (str_ - offset);
85}
86
87}
88
Daniel Dunbar04acaca2010-09-04 03:15:51 +000089#pragma GCC visibility pop
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000090
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 Hinnant1e15fd12011-05-26 19:48:01 +0000106logic_error::logic_error(const logic_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000107{
108 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
109 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
110}
111
112logic_error&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000113logic_error::operator=(const logic_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000114{
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 Hinnante1642e12012-02-17 19:24:42 +0000121#ifndef _LIBCPPABI_VERSION
122
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000123logic_error::~logic_error() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124{
125 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
126 s.~__libcpp_nmstr();
127}
128
129const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000130logic_error::what() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000131{
132 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
133 return s.c_str();
134}
135
Howard Hinnante1642e12012-02-17 19:24:42 +0000136#endif
137
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000138runtime_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 Hinnant1e15fd12011-05-26 19:48:01 +0000150runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000151{
152 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
153 ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
154}
155
156runtime_error&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000157runtime_error::operator=(const runtime_error& le) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000158{
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 Hinnante1642e12012-02-17 19:24:42 +0000165#ifndef _LIBCPPABI_VERSION
166
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000167runtime_error::~runtime_error() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000168{
169 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
170 s.~__libcpp_nmstr();
171}
172
173const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000174runtime_error::what() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000175{
176 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
177 return s.c_str();
178}
179
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000180domain_error::~domain_error() _NOEXCEPT {}
181invalid_argument::~invalid_argument() _NOEXCEPT {}
182length_error::~length_error() _NOEXCEPT {}
183out_of_range::~out_of_range() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000184
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000185range_error::~range_error() _NOEXCEPT {}
186overflow_error::~overflow_error() _NOEXCEPT {}
187underflow_error::~underflow_error() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188
Howard Hinnante1642e12012-02-17 19:24:42 +0000189#endif
190
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000191} // std