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*f95d9f0aSHoward Hinnant #include <cxxabi.h>
193e519524SHoward Hinnant 
203e519524SHoward Hinnant // Note:  optimize for size
213e519524SHoward Hinnant 
223e519524SHoward Hinnant #pragma GCC visibility push(hidden)
233e519524SHoward Hinnant 
243e519524SHoward Hinnant namespace
253e519524SHoward Hinnant {
263e519524SHoward Hinnant 
273e519524SHoward Hinnant class __libcpp_nmstr
283e519524SHoward Hinnant {
293e519524SHoward Hinnant private:
303e519524SHoward Hinnant     const char* str_;
313e519524SHoward Hinnant 
323e519524SHoward Hinnant     typedef std::size_t unused_t;
333e519524SHoward Hinnant     typedef std::int32_t count_t;
343e519524SHoward Hinnant 
353e519524SHoward Hinnant     static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
363e519524SHoward Hinnant                                                                        sizeof(count_t));
373e519524SHoward Hinnant 
38a62f2899SHoward Hinnant     count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
393e519524SHoward Hinnant public:
403e519524SHoward Hinnant     explicit __libcpp_nmstr(const char* msg);
413e519524SHoward Hinnant     __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
423e519524SHoward Hinnant     __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
433e519524SHoward Hinnant     ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
44a62f2899SHoward Hinnant     const char* c_str() const _NOEXCEPT {return str_;}
453e519524SHoward Hinnant };
463e519524SHoward Hinnant 
473e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const char* msg)
483e519524SHoward Hinnant {
493e519524SHoward Hinnant     std::size_t len = strlen(msg);
503e519524SHoward Hinnant     str_ = new char[len + 1 + offset];
513e519524SHoward Hinnant     unused_t* c = (unused_t*)str_;
523e519524SHoward Hinnant     c[0] = c[1] = len;
533e519524SHoward Hinnant     str_ += offset;
543e519524SHoward Hinnant     count() = 0;
553e519524SHoward Hinnant     std::strcpy(const_cast<char*>(c_str()), msg);
563e519524SHoward Hinnant }
573e519524SHoward Hinnant 
583e519524SHoward Hinnant inline
593e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
603e519524SHoward Hinnant     : str_(s.str_)
613e519524SHoward Hinnant {
62128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
633e519524SHoward Hinnant }
643e519524SHoward Hinnant 
653e519524SHoward Hinnant __libcpp_nmstr&
663e519524SHoward Hinnant __libcpp_nmstr::operator=(const __libcpp_nmstr& s)
673e519524SHoward Hinnant {
683e519524SHoward Hinnant     const char* p = str_;
693e519524SHoward Hinnant     str_ = s.str_;
70128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
71128ba719SHoward Hinnant     if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
723e519524SHoward Hinnant         delete [] (p-offset);
733e519524SHoward Hinnant     return *this;
743e519524SHoward Hinnant }
753e519524SHoward Hinnant 
763e519524SHoward Hinnant inline
773e519524SHoward Hinnant __libcpp_nmstr::~__libcpp_nmstr()
783e519524SHoward Hinnant {
79128ba719SHoward Hinnant     if (__sync_add_and_fetch(&count(), -1) < 0)
803e519524SHoward Hinnant         delete [] (str_ - offset);
813e519524SHoward Hinnant }
823e519524SHoward Hinnant 
833e519524SHoward Hinnant }
843e519524SHoward Hinnant 
850a779b97SDaniel Dunbar #pragma GCC visibility pop
863e519524SHoward Hinnant 
873e519524SHoward Hinnant namespace std  // purposefully not using versioning namespace
883e519524SHoward Hinnant {
893e519524SHoward Hinnant 
903e519524SHoward Hinnant logic_error::logic_error(const string& msg)
913e519524SHoward Hinnant {
923e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
933e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
943e519524SHoward Hinnant }
953e519524SHoward Hinnant 
963e519524SHoward Hinnant logic_error::logic_error(const char* msg)
973e519524SHoward Hinnant {
983e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
993e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
1003e519524SHoward Hinnant }
1013e519524SHoward Hinnant 
102a62f2899SHoward Hinnant logic_error::logic_error(const logic_error& le) _NOEXCEPT
1033e519524SHoward Hinnant {
1043e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1053e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1063e519524SHoward Hinnant }
1073e519524SHoward Hinnant 
1083e519524SHoward Hinnant logic_error&
109a62f2899SHoward Hinnant logic_error::operator=(const logic_error& le) _NOEXCEPT
1103e519524SHoward Hinnant {
1113e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1123e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1133e519524SHoward Hinnant     s1 = s2;
1143e519524SHoward Hinnant     return *this;
1153e519524SHoward Hinnant }
1163e519524SHoward Hinnant 
117*f95d9f0aSHoward Hinnant #ifndef _LIBCPPABI_VERSION
118*f95d9f0aSHoward Hinnant 
119a62f2899SHoward Hinnant logic_error::~logic_error() _NOEXCEPT
1203e519524SHoward Hinnant {
1213e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1223e519524SHoward Hinnant     s.~__libcpp_nmstr();
1233e519524SHoward Hinnant }
1243e519524SHoward Hinnant 
1253e519524SHoward Hinnant const char*
126a62f2899SHoward Hinnant logic_error::what() const _NOEXCEPT
1273e519524SHoward Hinnant {
1283e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1293e519524SHoward Hinnant     return s.c_str();
1303e519524SHoward Hinnant }
1313e519524SHoward Hinnant 
132*f95d9f0aSHoward Hinnant #endif
133*f95d9f0aSHoward Hinnant 
1343e519524SHoward Hinnant runtime_error::runtime_error(const string& msg)
1353e519524SHoward Hinnant {
1363e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1373e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
1383e519524SHoward Hinnant }
1393e519524SHoward Hinnant 
1403e519524SHoward Hinnant runtime_error::runtime_error(const char* msg)
1413e519524SHoward Hinnant {
1423e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1433e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
1443e519524SHoward Hinnant }
1453e519524SHoward Hinnant 
146a62f2899SHoward Hinnant runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT
1473e519524SHoward Hinnant {
1483e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1493e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1503e519524SHoward Hinnant }
1513e519524SHoward Hinnant 
1523e519524SHoward Hinnant runtime_error&
153a62f2899SHoward Hinnant runtime_error::operator=(const runtime_error& le) _NOEXCEPT
1543e519524SHoward Hinnant {
1553e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1563e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1573e519524SHoward Hinnant     s1 = s2;
1583e519524SHoward Hinnant     return *this;
1593e519524SHoward Hinnant }
1603e519524SHoward Hinnant 
161*f95d9f0aSHoward Hinnant #ifndef _LIBCPPABI_VERSION
162*f95d9f0aSHoward Hinnant 
163a62f2899SHoward Hinnant runtime_error::~runtime_error() _NOEXCEPT
1643e519524SHoward Hinnant {
1653e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1663e519524SHoward Hinnant     s.~__libcpp_nmstr();
1673e519524SHoward Hinnant }
1683e519524SHoward Hinnant 
1693e519524SHoward Hinnant const char*
170a62f2899SHoward Hinnant runtime_error::what() const _NOEXCEPT
1713e519524SHoward Hinnant {
1723e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1733e519524SHoward Hinnant     return s.c_str();
1743e519524SHoward Hinnant }
1753e519524SHoward Hinnant 
176a62f2899SHoward Hinnant domain_error::~domain_error() _NOEXCEPT {}
177a62f2899SHoward Hinnant invalid_argument::~invalid_argument() _NOEXCEPT {}
178a62f2899SHoward Hinnant length_error::~length_error() _NOEXCEPT {}
179a62f2899SHoward Hinnant out_of_range::~out_of_range() _NOEXCEPT {}
1803e519524SHoward Hinnant 
181a62f2899SHoward Hinnant range_error::~range_error() _NOEXCEPT {}
182a62f2899SHoward Hinnant overflow_error::~overflow_error() _NOEXCEPT {}
183a62f2899SHoward Hinnant underflow_error::~underflow_error() _NOEXCEPT {}
1843e519524SHoward Hinnant 
185*f95d9f0aSHoward Hinnant #endif
186*f95d9f0aSHoward Hinnant 
1873e519524SHoward Hinnant }  // std
188