blob: 4aa962d0a2045405055638957f9123bc2a5a6b6d [file] [log] [blame]
Howard Hinnant3e7d1552012-02-17 19:23:47 +00001//===------------------------ stdexcept.cpp -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "stdexcept"
11#include "new"
12#include <cstdlib>
13#include <cstring>
14#include <cstdint>
15#include <cstddef>
16
17// Note: optimize for size
18
19#pragma GCC visibility push(hidden)
20
21namespace
22{
23
24class __libcpp_nmstr
25{
26private:
27 const char* str_;
28
29 typedef std::size_t unused_t;
30 typedef std::int32_t count_t;
31
32 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
33 sizeof(count_t));
34
35 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
36public:
37 explicit __libcpp_nmstr(const char* msg);
38 __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
39 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
40 ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
41 const char* c_str() const _NOEXCEPT {return str_;}
42};
43
44__libcpp_nmstr::__libcpp_nmstr(const char* msg)
45{
46 std::size_t len = strlen(msg);
47 str_ = new char[len + 1 + offset];
48 unused_t* c = (unused_t*)str_;
49 c[0] = c[1] = len;
50 str_ += offset;
51 count() = 0;
52 std::strcpy(const_cast<char*>(c_str()), msg);
53}
54
55inline
56__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
57 : str_(s.str_)
58{
59 __sync_add_and_fetch(&count(), 1);
60}
61
62__libcpp_nmstr&
63__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
64{
65 const char* p = str_;
66 str_ = s.str_;
67 __sync_add_and_fetch(&count(), 1);
68 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0)
69 delete [] (p-offset);
70 return *this;
71}
72
73inline
74__libcpp_nmstr::~__libcpp_nmstr()
75{
76 if (__sync_add_and_fetch(&count(), -1) < 0)
77 delete [] (str_ - offset);
78}
79
80}
81
82#pragma GCC visibility pop
83
84namespace std // purposefully not using versioning namespace
85{
86
87logic_error::~logic_error() _NOEXCEPT
88{
89 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
90 s.~__libcpp_nmstr();
91}
92
93const char*
94logic_error::what() const _NOEXCEPT
95{
96 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
97 return s.c_str();
98}
99
100runtime_error::~runtime_error() _NOEXCEPT
101{
102 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
103 s.~__libcpp_nmstr();
104}
105
106const char*
107runtime_error::what() const _NOEXCEPT
108{
109 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
110 return s.c_str();
111}
112
113domain_error::~domain_error() _NOEXCEPT {}
114invalid_argument::~invalid_argument() _NOEXCEPT {}
115length_error::~length_error() _NOEXCEPT {}
116out_of_range::~out_of_range() _NOEXCEPT {}
117
118range_error::~range_error() _NOEXCEPT {}
119overflow_error::~overflow_error() _NOEXCEPT {}
120underflow_error::~underflow_error() _NOEXCEPT {}
121
122} // std