13e519524SHoward Hinnant //===------------------------ stdexcept.cpp -------------------------------===//
23e519524SHoward Hinnant //
35b08a8a4SHoward Hinnant //                     The LLVM Compiler Infrastructure
43e519524SHoward Hinnant //
5*412dbebeSHoward Hinnant // This file is dual licensed under the MIT and the University of Illinois Open
6*412dbebeSHoward 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"
183e519524SHoward Hinnant 
193e519524SHoward Hinnant // Note:  optimize for size
203e519524SHoward Hinnant 
213e519524SHoward Hinnant #pragma GCC visibility push(hidden)
223e519524SHoward Hinnant 
233e519524SHoward Hinnant namespace
243e519524SHoward Hinnant {
253e519524SHoward Hinnant 
263e519524SHoward Hinnant class __libcpp_nmstr
273e519524SHoward Hinnant {
283e519524SHoward Hinnant private:
293e519524SHoward Hinnant     const char* str_;
303e519524SHoward Hinnant 
313e519524SHoward Hinnant     typedef std::size_t unused_t;
323e519524SHoward Hinnant     typedef std::int32_t count_t;
333e519524SHoward Hinnant 
343e519524SHoward Hinnant     static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
353e519524SHoward Hinnant                                                                        sizeof(count_t));
363e519524SHoward Hinnant 
373e519524SHoward Hinnant     count_t& count() const throw() {return (count_t&)(*(str_ - sizeof(count_t)));}
383e519524SHoward Hinnant public:
393e519524SHoward Hinnant     explicit __libcpp_nmstr(const char* msg);
403e519524SHoward Hinnant     __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
413e519524SHoward Hinnant     __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
423e519524SHoward Hinnant     ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
433e519524SHoward Hinnant     const char* c_str() const throw() {return str_;}
443e519524SHoward Hinnant };
453e519524SHoward Hinnant 
463e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const char* msg)
473e519524SHoward Hinnant {
483e519524SHoward Hinnant     std::size_t len = strlen(msg);
493e519524SHoward Hinnant     str_ = new char[len + 1 + offset];
503e519524SHoward Hinnant     unused_t* c = (unused_t*)str_;
513e519524SHoward Hinnant     c[0] = c[1] = len;
523e519524SHoward Hinnant     str_ += offset;
533e519524SHoward Hinnant     count() = 0;
543e519524SHoward Hinnant     std::strcpy(const_cast<char*>(c_str()), msg);
553e519524SHoward Hinnant }
563e519524SHoward Hinnant 
573e519524SHoward Hinnant inline
583e519524SHoward Hinnant __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
593e519524SHoward Hinnant     : str_(s.str_)
603e519524SHoward Hinnant {
61128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
623e519524SHoward Hinnant }
633e519524SHoward Hinnant 
643e519524SHoward Hinnant __libcpp_nmstr&
653e519524SHoward Hinnant __libcpp_nmstr::operator=(const __libcpp_nmstr& s)
663e519524SHoward Hinnant {
673e519524SHoward Hinnant     const char* p = str_;
683e519524SHoward Hinnant     str_ = s.str_;
69128ba719SHoward Hinnant     __sync_add_and_fetch(&count(), 1);
70128ba719SHoward Hinnant     if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
713e519524SHoward Hinnant         delete [] (p-offset);
723e519524SHoward Hinnant     return *this;
733e519524SHoward Hinnant }
743e519524SHoward Hinnant 
753e519524SHoward Hinnant inline
763e519524SHoward Hinnant __libcpp_nmstr::~__libcpp_nmstr()
773e519524SHoward Hinnant {
78128ba719SHoward Hinnant     if (__sync_add_and_fetch(&count(), -1) < 0)
793e519524SHoward Hinnant         delete [] (str_ - offset);
803e519524SHoward Hinnant }
813e519524SHoward Hinnant 
823e519524SHoward Hinnant }
833e519524SHoward Hinnant 
840a779b97SDaniel Dunbar #pragma GCC visibility pop
853e519524SHoward Hinnant 
863e519524SHoward Hinnant namespace std  // purposefully not using versioning namespace
873e519524SHoward Hinnant {
883e519524SHoward Hinnant 
893e519524SHoward Hinnant logic_error::logic_error(const string& msg)
903e519524SHoward Hinnant {
913e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
923e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
933e519524SHoward Hinnant }
943e519524SHoward Hinnant 
953e519524SHoward Hinnant logic_error::logic_error(const char* msg)
963e519524SHoward Hinnant {
973e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
983e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
993e519524SHoward Hinnant }
1003e519524SHoward Hinnant 
1013e519524SHoward Hinnant logic_error::logic_error(const logic_error& le) throw()
1023e519524SHoward Hinnant {
1033e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1043e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1053e519524SHoward Hinnant }
1063e519524SHoward Hinnant 
1073e519524SHoward Hinnant logic_error&
1083e519524SHoward Hinnant logic_error::operator=(const logic_error& le) throw()
1093e519524SHoward Hinnant {
1103e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1113e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1123e519524SHoward Hinnant     s1 = s2;
1133e519524SHoward Hinnant     return *this;
1143e519524SHoward Hinnant }
1153e519524SHoward Hinnant 
1163e519524SHoward Hinnant logic_error::~logic_error() throw()
1173e519524SHoward Hinnant {
1183e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1193e519524SHoward Hinnant     s.~__libcpp_nmstr();
1203e519524SHoward Hinnant }
1213e519524SHoward Hinnant 
1223e519524SHoward Hinnant const char*
1233e519524SHoward Hinnant logic_error::what() const throw()
1243e519524SHoward Hinnant {
1253e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1263e519524SHoward Hinnant     return s.c_str();
1273e519524SHoward Hinnant }
1283e519524SHoward Hinnant 
1293e519524SHoward Hinnant runtime_error::runtime_error(const string& msg)
1303e519524SHoward Hinnant {
1313e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1323e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg.c_str());
1333e519524SHoward Hinnant }
1343e519524SHoward Hinnant 
1353e519524SHoward Hinnant runtime_error::runtime_error(const char* msg)
1363e519524SHoward Hinnant {
1373e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1383e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr(msg);
1393e519524SHoward Hinnant }
1403e519524SHoward Hinnant 
1413e519524SHoward Hinnant runtime_error::runtime_error(const runtime_error& le) throw()
1423e519524SHoward Hinnant {
1433e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1443e519524SHoward Hinnant     ::new(&s) __libcpp_nmstr((const __libcpp_nmstr&)le.__imp_);
1453e519524SHoward Hinnant }
1463e519524SHoward Hinnant 
1473e519524SHoward Hinnant runtime_error&
1483e519524SHoward Hinnant runtime_error::operator=(const runtime_error& le) throw()
1493e519524SHoward Hinnant {
1503e519524SHoward Hinnant     __libcpp_nmstr& s1 = (__libcpp_nmstr&)__imp_;
1513e519524SHoward Hinnant     const __libcpp_nmstr& s2 = (const __libcpp_nmstr&)le.__imp_;
1523e519524SHoward Hinnant     s1 = s2;
1533e519524SHoward Hinnant     return *this;
1543e519524SHoward Hinnant }
1553e519524SHoward Hinnant 
1563e519524SHoward Hinnant runtime_error::~runtime_error() throw()
1573e519524SHoward Hinnant {
1583e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1593e519524SHoward Hinnant     s.~__libcpp_nmstr();
1603e519524SHoward Hinnant }
1613e519524SHoward Hinnant 
1623e519524SHoward Hinnant const char*
1633e519524SHoward Hinnant runtime_error::what() const throw()
1643e519524SHoward Hinnant {
1653e519524SHoward Hinnant     __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
1663e519524SHoward Hinnant     return s.c_str();
1673e519524SHoward Hinnant }
1683e519524SHoward Hinnant 
1693e519524SHoward Hinnant domain_error::~domain_error() throw() {}
1703e519524SHoward Hinnant invalid_argument::~invalid_argument() throw() {}
1713e519524SHoward Hinnant length_error::~length_error() throw() {}
1723e519524SHoward Hinnant out_of_range::~out_of_range() throw() {}
1733e519524SHoward Hinnant 
1743e519524SHoward Hinnant range_error::~range_error() throw() {}
1753e519524SHoward Hinnant overflow_error::~overflow_error() throw() {}
1763e519524SHoward Hinnant underflow_error::~underflow_error() throw() {}
1773e519524SHoward Hinnant 
1783e519524SHoward Hinnant }  // std
179