]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/src/system_error.cpp
Update llvm to trunk r290819 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / libc++ / src / system_error.cpp
1 //===---------------------- system_error.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 "__config"
11
12 #define _LIBCPP_BUILDING_SYSTEM_ERROR
13 #include "system_error"
14
15 #include "include/config_elast.h"
16 #include "cerrno"
17 #include "cstring"
18 #include "cstdio"
19 #include "cstdlib"
20 #include "cassert"
21 #include "string"
22 #include "string.h"
23
24 #if defined(__ANDROID__)
25 #include <android/api-level.h>
26 #endif
27
28 _LIBCPP_BEGIN_NAMESPACE_STD
29
30 // class error_category
31
32 error_category::error_category() _NOEXCEPT
33 {
34 }
35
36 error_category::~error_category() _NOEXCEPT
37 {
38 }
39
40 error_condition
41 error_category::default_error_condition(int ev) const _NOEXCEPT
42 {
43     return error_condition(ev, *this);
44 }
45
46 bool
47 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
48 {
49     return default_error_condition(code) == condition;
50 }
51
52 bool
53 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
54 {
55     return *this == code.category() && code.value() == condition;
56 }
57
58 namespace {
59
60 //  GLIBC also uses 1024 as the maximum buffer size internally.
61 constexpr size_t strerror_buff_size = 1024;
62
63 string do_strerror_r(int ev);
64
65 #if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC)                      \
66     && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
67 // GNU Extended version
68 string do_strerror_r(int ev) {
69     char buffer[strerror_buff_size];
70     char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
71     return string(ret);
72 }
73 #else
74 // POSIX version
75 string do_strerror_r(int ev) {
76     char buffer[strerror_buff_size];
77     const int old_errno = errno;
78     int ret;
79     if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
80         // If `ret == -1` then the error is specified using `errno`, otherwise
81         // `ret` represents the error.
82         const int new_errno = ret == -1 ? errno : ret;
83         errno = old_errno;
84         if (new_errno == EINVAL) {
85             std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
86             return string(buffer);
87         } else {
88             assert(new_errno == ERANGE);
89             // FIXME maybe? 'strerror_buff_size' is likely to exceed the
90             // maximum error size so ERANGE shouldn't be returned.
91             std::abort();
92         }
93     }
94     return string(buffer);
95 }
96 #endif
97
98 } // end namespace
99
100 string
101 __do_message::message(int ev) const
102 {
103 #if defined(_LIBCPP_HAS_NO_THREADS)
104     return string(::strerror(ev));
105 #else
106     return do_strerror_r(ev);
107 #endif
108 }
109
110 class _LIBCPP_HIDDEN __generic_error_category
111     : public __do_message
112 {
113 public:
114     virtual const char* name() const _NOEXCEPT;
115     virtual string message(int ev) const;
116 };
117
118 const char*
119 __generic_error_category::name() const _NOEXCEPT
120 {
121     return "generic";
122 }
123
124 string
125 __generic_error_category::message(int ev) const
126 {
127 #ifdef _LIBCPP_ELAST
128     if (ev > _LIBCPP_ELAST)
129       return string("unspecified generic_category error");
130 #endif  // _LIBCPP_ELAST
131     return __do_message::message(ev);
132 }
133
134 const error_category&
135 generic_category() _NOEXCEPT
136 {
137     static __generic_error_category s;
138     return s;
139 }
140
141 class _LIBCPP_HIDDEN __system_error_category
142     : public __do_message
143 {
144 public:
145     virtual const char* name() const _NOEXCEPT;
146     virtual string message(int ev) const;
147     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
148 };
149
150 const char*
151 __system_error_category::name() const _NOEXCEPT
152 {
153     return "system";
154 }
155
156 string
157 __system_error_category::message(int ev) const
158 {
159 #ifdef _LIBCPP_ELAST
160     if (ev > _LIBCPP_ELAST)
161       return string("unspecified system_category error");
162 #endif  // _LIBCPP_ELAST
163     return __do_message::message(ev);
164 }
165
166 error_condition
167 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
168 {
169 #ifdef _LIBCPP_ELAST
170     if (ev > _LIBCPP_ELAST)
171       return error_condition(ev, system_category());
172 #endif  // _LIBCPP_ELAST
173     return error_condition(ev, generic_category());
174 }
175
176 const error_category&
177 system_category() _NOEXCEPT
178 {
179     static __system_error_category s;
180     return s;
181 }
182
183 // error_condition
184
185 string
186 error_condition::message() const
187 {
188     return __cat_->message(__val_);
189 }
190
191 // error_code
192
193 string
194 error_code::message() const
195 {
196     return __cat_->message(__val_);
197 }
198
199 // system_error
200
201 string
202 system_error::__init(const error_code& ec, string what_arg)
203 {
204     if (ec)
205     {
206         if (!what_arg.empty())
207             what_arg += ": ";
208         what_arg += ec.message();
209     }
210     return what_arg;
211 }
212
213 system_error::system_error(error_code ec, const string& what_arg)
214     : runtime_error(__init(ec, what_arg)),
215       __ec_(ec)
216 {
217 }
218
219 system_error::system_error(error_code ec, const char* what_arg)
220     : runtime_error(__init(ec, what_arg)),
221       __ec_(ec)
222 {
223 }
224
225 system_error::system_error(error_code ec)
226     : runtime_error(__init(ec, "")),
227       __ec_(ec)
228 {
229 }
230
231 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
232     : runtime_error(__init(error_code(ev, ecat), what_arg)),
233       __ec_(error_code(ev, ecat))
234 {
235 }
236
237 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
238     : runtime_error(__init(error_code(ev, ecat), what_arg)),
239       __ec_(error_code(ev, ecat))
240 {
241 }
242
243 system_error::system_error(int ev, const error_category& ecat)
244     : runtime_error(__init(error_code(ev, ecat), "")),
245       __ec_(error_code(ev, ecat))
246 {
247 }
248
249 system_error::~system_error() _NOEXCEPT
250 {
251 }
252
253 void
254 __throw_system_error(int ev, const char* what_arg)
255 {
256 #ifndef _LIBCPP_NO_EXCEPTIONS
257     throw system_error(error_code(ev, system_category()), what_arg);
258 #else
259     (void)ev;
260     (void)what_arg;
261 #endif
262 }
263
264 _LIBCPP_END_NAMESPACE_STD