blob: 7071915addba0a49842c87fcbdff1dc21a8698c7 [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
Howard Hinnante115af22012-09-18 21:34:12 +000017#if __APPLE__
18#include <dlfcn.h>
19#include <mach-o/dyld.h>
20#endif
21
Howard Hinnant3e7d1552012-02-17 19:23:47 +000022// Note: optimize for size
23
24#pragma GCC visibility push(hidden)
25
26namespace
27{
28
29class __libcpp_nmstr
30{
31private:
32 const char* str_;
33
34 typedef std::size_t unused_t;
Howard Hinnant2c2b55f2012-08-08 16:15:16 +000035 typedef std::ptrdiff_t count_t;
Howard Hinnant3e7d1552012-02-17 19:23:47 +000036
37 static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) +
38 sizeof(count_t));
39
40 count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));}
Howard Hinnante115af22012-09-18 21:34:12 +000041
42#if __APPLE__
43 static
44 const void*
45 compute_gcc_empty_string_storage() _LIBCPP_CANTTHROW
46 {
47 void* handle = dlopen("libstdc++.dylib", RTLD_LAZY);
48 if (handle == 0)
49 return 0;
50 return (const char*)dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE") + offset;
51 }
52
53 static
54 const void*
55 get_gcc_empty_string_storage() _LIBCPP_CANTTHROW
56 {
57 static const void* p = compute_gcc_empty_string_storage();
58 return p;
59 }
60#endif
61
Howard Hinnant3e7d1552012-02-17 19:23:47 +000062public:
63 explicit __libcpp_nmstr(const char* msg);
64 __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
65 __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW;
66 ~__libcpp_nmstr() _LIBCPP_CANTTHROW;
67 const char* c_str() const _NOEXCEPT {return str_;}
68};
69
70__libcpp_nmstr::__libcpp_nmstr(const char* msg)
71{
72 std::size_t len = strlen(msg);
73 str_ = new char[len + 1 + offset];
74 unused_t* c = (unused_t*)str_;
75 c[0] = c[1] = len;
76 str_ += offset;
77 count() = 0;
78 std::strcpy(const_cast<char*>(c_str()), msg);
79}
80
81inline
82__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s)
83 : str_(s.str_)
84{
Howard Hinnante115af22012-09-18 21:34:12 +000085#if __APPLE__
86 if (str_ != get_gcc_empty_string_storage())
87#endif
88 __sync_add_and_fetch(&count(), 1);
Howard Hinnant3e7d1552012-02-17 19:23:47 +000089}
90
91__libcpp_nmstr&
92__libcpp_nmstr::operator=(const __libcpp_nmstr& s)
93{
94 const char* p = str_;
95 str_ = s.str_;
Howard Hinnante115af22012-09-18 21:34:12 +000096#if __APPLE__
97 if (str_ != get_gcc_empty_string_storage())
98#endif
99 __sync_add_and_fetch(&count(), 1);
100#if __APPLE__
101 if (p != get_gcc_empty_string_storage())
102#endif
103 if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0)
104 delete [] (p-offset);
Howard Hinnant3e7d1552012-02-17 19:23:47 +0000105 return *this;
106}
107
108inline
109__libcpp_nmstr::~__libcpp_nmstr()
110{
Howard Hinnante115af22012-09-18 21:34:12 +0000111#if __APPLE__
112 if (str_ != get_gcc_empty_string_storage())
113#endif
114 if (__sync_add_and_fetch(&count(), count_t(-1)) < 0)
115 delete [] (str_ - offset);
Howard Hinnant3e7d1552012-02-17 19:23:47 +0000116}
117
118}
119
120#pragma GCC visibility pop
121
122namespace std // purposefully not using versioning namespace
123{
124
125logic_error::~logic_error() _NOEXCEPT
126{
127 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
128 s.~__libcpp_nmstr();
129}
130
131const char*
132logic_error::what() const _NOEXCEPT
133{
134 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
135 return s.c_str();
136}
137
138runtime_error::~runtime_error() _NOEXCEPT
139{
140 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
141 s.~__libcpp_nmstr();
142}
143
144const char*
145runtime_error::what() const _NOEXCEPT
146{
147 __libcpp_nmstr& s = (__libcpp_nmstr&)__imp_;
148 return s.c_str();
149}
150
151domain_error::~domain_error() _NOEXCEPT {}
152invalid_argument::~invalid_argument() _NOEXCEPT {}
153length_error::~length_error() _NOEXCEPT {}
154out_of_range::~out_of_range() _NOEXCEPT {}
155
156range_error::~range_error() _NOEXCEPT {}
157overflow_error::~overflow_error() _NOEXCEPT {}
158underflow_error::~underflow_error() _NOEXCEPT {}
159
160} // std