blob: ec7f666dc6d90f8c5c4f3a84aa99fd58c32bc05e [file] [log] [blame]
Howard Hinnantc51e1022010-05-11 19:42:16 +00001//===------------------------ stdexcept.cpp -------------------------------===//
2//
Howard Hinnantc566dc32010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantc51e1022010-05-11 19:42:16 +00004//
Howard Hinnantee11c312010-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 Hinnantc51e1022010-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 Smithfc88dae2012-04-19 01:36:12 +000018
Howard Hinnant986a51f2012-09-03 18:13:11 +000019#ifndef __has_include
20#define __has_include(inc) 0
21#endif
22
Marshall Clowdde4bfe2013-03-18 17:45:34 +000023#ifdef __APPLE__
Howard Hinnant986a51f2012-09-03 18:13:11 +000024#include <cxxabi.h>
25#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
Howard Hinnantbaef2cc2012-02-17 19:24:42 +000026#include <cxxabi.h>
Richard Smithfc88dae2012-04-19 01:36:12 +000027#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000028
29// Note: optimize for size
30
Howard Hinnant0d9aa9d2013-10-04 22:12:59 +000031#if ! defined(_LIBCPP_MSVC)
Howard Hinnantc51e1022010-05-11 19:42:16 +000032#pragma GCC visibility push(hidden)
Howard Hinnant0d9aa9d2013-10-04 22:12:59 +000033#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000034
35namespace
36{
37
38class __libcpp_nmstr
39{
40private:
41 const char* str_;
42
43 typedef std::size_t unused_t;
Howard Hinnant49c61522012-08-08 16:17:31 +000044 typedef std::ptrdiff_t count_t;
Howard Hinnantc51e1022010-05-11 19:42:16 +000045
46 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
47 sizeof(count_t));
48
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000049 count_t& count() const _NOEXCEPT {return *const_cast<count_t *>(reinterpret_cast<const count_t *>(str_ - sizeof(count_t)));}
Howard Hinnantc51e1022010-05-11 19:42:16 +000050public:
51 explicit __libcpp_nmstr(const char* msg);
Howard Hinnant8ad3f702013-08-22 19:39:03 +000052 __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT;
53 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT;
54 ~__libcpp_nmstr();
Howard Hinnant1f098bc2011-05-26 19:48:01 +000055 const char* c_str() const _NOEXCEPT {return str_;}
Howard Hinnantc51e1022010-05-11 19:42:16 +000056};
57
58__libcpp_nmstr::__libcpp_nmstr(const char* msg)
59{
60 std::size_t len = strlen(msg);
61 str_ = new char[len + 1 + offset];
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +000062 unused_t* c = reinterpret_cast<unused_t*>(const_cast<char *>(str_));
Howard Hinnantc51e1022010-05-11 19:42:16 +000063 c[0] = c[1] = len;
64 str_ += offset;
65 count() = 0;
Howard Hinnant55835352013-06-29 23:53:20 +000066 std::memcpy(const_cast<char*>(c_str()), msg, len + 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +000067}
68
69inline
Howard Hinnant8ad3f702013-08-22 19:39:03 +000070__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +000071 : str_(s.str_)
72{
Howard Hinnant155c2af2010-05-24 17:49:41 +000073 __sync_add_and_fetch(&count(), 1);
Howard Hinnantc51e1022010-05-11 19:42:16 +000074}
75
76__libcpp_nmstr&
Howard Hinnant8ad3f702013-08-22 19:39:03 +000077__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +000078{
79 const char* p = str_;
80 str_ = s.str_;
Howard Hinnant155c2af2010-05-24 17:49:41 +000081 __sync_add_and_fetch(&count(), 1);
Alp Toker5cc08f12014-01-17 16:17:24 +000082 if (__sync_add_and_fetch(reinterpret_cast<count_t*>(const_cast<char*>(p)-sizeof(count_t)), count_t(-1)) < 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +000083 delete [] (p-offset);
84 return *this;
85}
86
87inline
88__libcpp_nmstr::~__libcpp_nmstr()
89{
Howard Hinnant49c61522012-08-08 16:17:31 +000090 if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
Howard Hinnantc51e1022010-05-11 19:42:16 +000091 delete [] (str_ - offset);
92}
93
94}
95
Howard Hinnant0d9aa9d2013-10-04 22:12:59 +000096#if ! defined(_LIBCPP_MSVC)
Daniel Dunbar063d0732010-09-04 03:15:51 +000097#pragma GCC visibility pop
Howard Hinnant0d9aa9d2013-10-04 22:12:59 +000098#endif
Howard Hinnantc51e1022010-05-11 19:42:16 +000099
100namespace std // purposefully not using versioning namespace
101{
102
103logic_error::logic_error(const string& msg)
104{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000105 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000106 ::new(s) __libcpp_nmstr(msg.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +0000107}
108
109logic_error::logic_error(const char* msg)
110{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000111 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000112 ::new(s) __libcpp_nmstr(msg);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000113}
114
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000115logic_error::logic_error(const logic_error& le) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000116{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000117 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
118 const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000119 ::new(s) __libcpp_nmstr(*s2);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000120}
121
122logic_error&
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000123logic_error::operator=(const logic_error& le) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000124{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000125 __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
126 const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000127 *s1 = *s2;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000128 return *this;
129}
130
Peter Collingbourne22dc63b2013-10-06 22:13:19 +0000131#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX)
Howard Hinnantbaef2cc2012-02-17 19:24:42 +0000132
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000133logic_error::~logic_error() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000134{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000135 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000136 s->~__libcpp_nmstr();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000137}
138
139const char*
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000140logic_error::what() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000141{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000142 const __libcpp_nmstr *s = reinterpret_cast<const __libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000143 return s->c_str();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000144}
145
Howard Hinnantbaef2cc2012-02-17 19:24:42 +0000146#endif
147
Howard Hinnantc51e1022010-05-11 19:42:16 +0000148runtime_error::runtime_error(const string& msg)
149{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000150 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000151 ::new(s) __libcpp_nmstr(msg.c_str());
Howard Hinnantc51e1022010-05-11 19:42:16 +0000152}
153
154runtime_error::runtime_error(const char* msg)
155{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000156 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000157 ::new(s) __libcpp_nmstr(msg);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000158}
159
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000160runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000161{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000162 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
163 const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000164 ::new(s) __libcpp_nmstr(*s2);
Howard Hinnantc51e1022010-05-11 19:42:16 +0000165}
166
167runtime_error&
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000168runtime_error::operator=(const runtime_error& le) _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000169{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000170 __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
171 const __libcpp_nmstr *s2 = reinterpret_cast<const __libcpp_nmstr *>(&le.__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000172 *s1 = *s2;
Howard Hinnantc51e1022010-05-11 19:42:16 +0000173 return *this;
174}
175
Peter Collingbourne22dc63b2013-10-06 22:13:19 +0000176#if !defined(_LIBCPPABI_VERSION) && !defined(LIBSTDCXX)
Howard Hinnantbaef2cc2012-02-17 19:24:42 +0000177
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000178runtime_error::~runtime_error() _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000179{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000180 __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000181 s->~__libcpp_nmstr();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000182}
183
184const char*
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000185runtime_error::what() const _NOEXCEPT
Howard Hinnantc51e1022010-05-11 19:42:16 +0000186{
Joerg Sonnenberger254e49e2014-01-07 19:21:13 +0000187 const __libcpp_nmstr *s = reinterpret_cast<const __libcpp_nmstr *>(&__imp_);
Joerg Sonnenbergerc7655a22014-01-04 17:43:00 +0000188 return s->c_str();
Howard Hinnantc51e1022010-05-11 19:42:16 +0000189}
190
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000191domain_error::~domain_error() _NOEXCEPT {}
192invalid_argument::~invalid_argument() _NOEXCEPT {}
193length_error::~length_error() _NOEXCEPT {}
194out_of_range::~out_of_range() _NOEXCEPT {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000195
Howard Hinnant1f098bc2011-05-26 19:48:01 +0000196range_error::~range_error() _NOEXCEPT {}
197overflow_error::~overflow_error() _NOEXCEPT {}
198underflow_error::~underflow_error() _NOEXCEPT {}
Howard Hinnantc51e1022010-05-11 19:42:16 +0000199
Howard Hinnantbaef2cc2012-02-17 19:24:42 +0000200#endif
201
Howard Hinnantc51e1022010-05-11 19:42:16 +0000202} // std