13e519524SHoward Hinnant //===------------------------ stdexcept.cpp -------------------------------===//
23e519524SHoward Hinnant //
35b08a8a4SHoward Hinnant //                     The LLVM Compiler Infrastructure
43e519524SHoward Hinnant //
5412dbebeSHoward Hinnant // This file is dual licensed under the MIT and the University of Illinois Open
6412dbebeSHoward Hinnant // Source Licenses. See LICENSE.TXT for details.
73e519524SHoward Hinnant //
83e519524SHoward Hinnant //===----------------------------------------------------------------------===//
93e519524SHoward Hinnant 
103e519524SHoward Hinnant #include "stdexcept"
113e519524SHoward Hinnant #include "new"
123e519524SHoward Hinnant #include "string"
133e519524SHoward Hinnant #include <cstdlib>
143e519524SHoward Hinnant #include <cstring>
153e519524SHoward Hinnant #include <cstdint>
163e519524SHoward Hinnant #include <cstddef>
173e519524SHoward Hinnant #include "system_error"
18*11ffde3dSRichard Smith 
19*11ffde3dSRichard Smith // Use <cxxabi.h> to determine whether we're linking against libc++abi.
20*11ffde3dSRichard Smith #if __has_include(<cxxabi.h>)
21f95d9f0aSHoward Hinnant #include <cxxabi.h>
22*11ffde3dSRichard Smith #endif
233e519524SHoward Hinnant 
243e519524SHoward Hinnant // Note:  optimize for size
253e519524SHoward Hinnant 
263e519524SHoward Hinnant #pragma GCC visibility push(hidden)
273e519524SHoward Hinnant 
283e519524SHoward Hinnant namespace
293e519524SHoward Hinnant {
303e519524SHoward Hinnant 
313e519524SHoward Hinnant class __libcpp_nmstr
323e519524SHoward Hinnant {
333e519524SHoward Hinnant private:
343e519524SHoward Hinnant     const char* str_;
353e519524SHoward Hinnant 
363e519524SHoward Hinnant     typedef std::size_t unused_t;
373e519524SHoward Hinnant     typedef std::int32_t count_t;
383e519524SHoward Hinnant 
393e519524SHoward Hinnant     static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
403e519524SHoward Hinnant                                                                        sizeof(count_t));
413e519524SHoward Hinnant 
42a62f2899SHoward Hinnant     count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
433e519524SHoward Hinnant public:
443e519524SHoward Hinnant     explicit __libcpp_nmstr(const char* msg);
453e519524SHoward Hinnant     __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
463e519524SHoward Hinnant     __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
473e519524SHoward Hinnant     ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
48a62f2899SHoward Hinnant     const char* c_str() const _NOEXCEPT {return str_;}
493e519524SHoward Hinnant };
503e519524SHoward Hinnant 
513e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const char* msg)
523e519524SHoward Hinnant {
533e519524SHoward Hinnant     std::size_t len = strlen(msg);
543e519524SHoward Hinnant     str_ = new char[len + 1 + offset];
553e519524SHoward Hinnant     unused_t* c = (unused_t*)str_;
563e519524SHoward Hinnant     c[0] = c[1] = len;
573e519524SHoward Hinnant     str_ += offset;
583e519524SHoward Hinnant     count() = 0;
593e519524SHoward Hinnant     std::strcpy(const_cast<char*>(c_str()), msg);
603e519524SHoward Hinnant }
613e519524SHoward Hinnant 
623e519524SHoward Hinnant inline
633e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
643e519524SHoward Hinnant     : str_(s.str_)
653e519524SHoward Hinnant {
66128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
673e519524SHoward Hinnant }
683e519524SHoward Hinnant 
693e519524SHoward Hinnant __libcpp_nmstr&
703e519524SHoward Hinnant __libcpp_nmstr::operator=(const __libcpp_nmstr& s)
713e519524SHoward Hinnant {
723e519524SHoward Hinnant     const char* p = str_;
733e519524SHoward Hinnant     str_ = s.str_;
74128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
75128ba719SHoward Hinnant     if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
763e519524SHoward Hinnant         delete [] (p-offset);
773e519524SHoward Hinnant     return *this;
783e519524SHoward Hinnant }
793e519524SHoward Hinnant 
803e519524SHoward Hinnant inline
813e519524SHoward Hinnant __libcpp_nmstr::~__libcpp_nmstr()
823e519524SHoward Hinnant {
83128ba719SHoward Hinnant     if (__sync_add_and_fetch(&count(), -1) < 0)
843e519524SHoward Hinnant         delete [] (str_ - offset);
853e519524SHoward Hinnant }
863e519524SHoward Hinnant 
873e519524SHoward Hinnant }
883e519524SHoward Hinnant 
890a779b97SDaniel Dunbar #pragma GCC visibility pop
903e519524SHoward Hinnant 
913e519524SHoward Hinnant namespace std  // purposefully not using versioning namespace
923e519524SHoward Hinnant {
933e519524SHoward Hinnant 
943e519524SHoward Hinnant logic_error::logic_error(const string& msg)
953e519524SHoward Hinnant {
963e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
973e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
983e519524SHoward Hinnant }
993e519524SHoward Hinnant 
1003e519524SHoward Hinnant logic_error::logic_error(const char* msg)
1013e519524SHoward Hinnant {
1023e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1033e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
1043e519524SHoward Hinnant }
1053e519524SHoward Hinnant 
106a62f2899SHoward Hinnant logic_error::logic_error(const logic_error& le) _NOEXCEPT
1073e519524SHoward Hinnant {
1083e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1093e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1103e519524SHoward Hinnant }
1113e519524SHoward Hinnant 
1123e519524SHoward Hinnant logic_error&
113a62f2899SHoward Hinnant logic_error::operator=(const logic_error& le) _NOEXCEPT
1143e519524SHoward Hinnant {
1153e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1163e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1173e519524SHoward Hinnant     s1 = s2;
1183e519524SHoward Hinnant     return *this;
1193e519524SHoward Hinnant }
1203e519524SHoward Hinnant 
121f95d9f0aSHoward Hinnant #ifndef _LIBCPPABI_VERSION
122f95d9f0aSHoward Hinnant 
123a62f2899SHoward Hinnant logic_error::~logic_error() _NOEXCEPT
1243e519524SHoward Hinnant {
1253e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1263e519524SHoward Hinnant     s.~__libcpp_nmstr();
1273e519524SHoward Hinnant }
1283e519524SHoward Hinnant 
1293e519524SHoward Hinnant const char*
130a62f2899SHoward Hinnant logic_error::what() const _NOEXCEPT
1313e519524SHoward Hinnant {
1323e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1333e519524SHoward Hinnant     return s.c_str();
1343e519524SHoward Hinnant }
1353e519524SHoward Hinnant 
136f95d9f0aSHoward Hinnant #endif
137f95d9f0aSHoward Hinnant 
1383e519524SHoward Hinnant runtime_error::runtime_error(const string& msg)
1393e519524SHoward Hinnant {
1403e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1413e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
1423e519524SHoward Hinnant }
1433e519524SHoward Hinnant 
1443e519524SHoward Hinnant runtime_error::runtime_error(const char* msg)
1453e519524SHoward Hinnant {
1463e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1473e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
1483e519524SHoward Hinnant }
1493e519524SHoward Hinnant 
150a62f2899SHoward Hinnant runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
1513e519524SHoward Hinnant {
1523e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1533e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1543e519524SHoward Hinnant }
1553e519524SHoward Hinnant 
1563e519524SHoward Hinnant runtime_error&
157a62f2899SHoward Hinnant runtime_error::operator=(const runtime_error& le) _NOEXCEPT
1583e519524SHoward Hinnant {
1593e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1603e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1613e519524SHoward Hinnant     s1 = s2;
1623e519524SHoward Hinnant     return *this;
1633e519524SHoward Hinnant }
1643e519524SHoward Hinnant 
165f95d9f0aSHoward Hinnant #ifndef _LIBCPPABI_VERSION
166f95d9f0aSHoward Hinnant 
167a62f2899SHoward Hinnant runtime_error::~runtime_error() _NOEXCEPT
1683e519524SHoward Hinnant {
1693e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1703e519524SHoward Hinnant     s.~__libcpp_nmstr();
1713e519524SHoward Hinnant }
1723e519524SHoward Hinnant 
1733e519524SHoward Hinnant const char*
174a62f2899SHoward Hinnant runtime_error::what() const _NOEXCEPT
1753e519524SHoward Hinnant {
1763e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1773e519524SHoward Hinnant     return s.c_str();
1783e519524SHoward Hinnant }
1793e519524SHoward Hinnant 
180a62f2899SHoward Hinnant domain_error::~domain_error() _NOEXCEPT {}
181a62f2899SHoward Hinnant invalid_argument::~invalid_argument() _NOEXCEPT {}
182a62f2899SHoward Hinnant length_error::~length_error() _NOEXCEPT {}
183a62f2899SHoward Hinnant out_of_range::~out_of_range() _NOEXCEPT {}
1843e519524SHoward Hinnant 
185a62f2899SHoward Hinnant range_error::~range_error() _NOEXCEPT {}
186a62f2899SHoward Hinnant overflow_error::~overflow_error() _NOEXCEPT {}
187a62f2899SHoward Hinnant underflow_error::~underflow_error() _NOEXCEPT {}
1883e519524SHoward Hinnant 
189f95d9f0aSHoward Hinnant #endif
190f95d9f0aSHoward Hinnant 
1913e519524SHoward Hinnant }  // std
192