1*58b9f456SAndroid Build Coastguard Worker //===---------------------- system_error.cpp ------------------------------===//
2*58b9f456SAndroid Build Coastguard Worker //
3*58b9f456SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*58b9f456SAndroid Build Coastguard Worker //
5*58b9f456SAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*58b9f456SAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*58b9f456SAndroid Build Coastguard Worker //
8*58b9f456SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*58b9f456SAndroid Build Coastguard Worker
10*58b9f456SAndroid Build Coastguard Worker #include "__config"
11*58b9f456SAndroid Build Coastguard Worker
12*58b9f456SAndroid Build Coastguard Worker #include "system_error"
13*58b9f456SAndroid Build Coastguard Worker
14*58b9f456SAndroid Build Coastguard Worker #include "include/config_elast.h"
15*58b9f456SAndroid Build Coastguard Worker #include "cerrno"
16*58b9f456SAndroid Build Coastguard Worker #include "cstring"
17*58b9f456SAndroid Build Coastguard Worker #include "cstdio"
18*58b9f456SAndroid Build Coastguard Worker #include "cstdlib"
19*58b9f456SAndroid Build Coastguard Worker #include "string"
20*58b9f456SAndroid Build Coastguard Worker #include "string.h"
21*58b9f456SAndroid Build Coastguard Worker #include "__debug"
22*58b9f456SAndroid Build Coastguard Worker
23*58b9f456SAndroid Build Coastguard Worker #if defined(__ANDROID__)
24*58b9f456SAndroid Build Coastguard Worker #include <android/api-level.h>
25*58b9f456SAndroid Build Coastguard Worker #endif
26*58b9f456SAndroid Build Coastguard Worker
27*58b9f456SAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD
28*58b9f456SAndroid Build Coastguard Worker
29*58b9f456SAndroid Build Coastguard Worker // class error_category
30*58b9f456SAndroid Build Coastguard Worker
31*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
error_category()32*58b9f456SAndroid Build Coastguard Worker error_category::error_category() _NOEXCEPT
33*58b9f456SAndroid Build Coastguard Worker {
34*58b9f456SAndroid Build Coastguard Worker }
35*58b9f456SAndroid Build Coastguard Worker #endif
36*58b9f456SAndroid Build Coastguard Worker
~error_category()37*58b9f456SAndroid Build Coastguard Worker error_category::~error_category() _NOEXCEPT
38*58b9f456SAndroid Build Coastguard Worker {
39*58b9f456SAndroid Build Coastguard Worker }
40*58b9f456SAndroid Build Coastguard Worker
41*58b9f456SAndroid Build Coastguard Worker error_condition
default_error_condition(int ev) const42*58b9f456SAndroid Build Coastguard Worker error_category::default_error_condition(int ev) const _NOEXCEPT
43*58b9f456SAndroid Build Coastguard Worker {
44*58b9f456SAndroid Build Coastguard Worker return error_condition(ev, *this);
45*58b9f456SAndroid Build Coastguard Worker }
46*58b9f456SAndroid Build Coastguard Worker
47*58b9f456SAndroid Build Coastguard Worker bool
equivalent(int code,const error_condition & condition) const48*58b9f456SAndroid Build Coastguard Worker error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
49*58b9f456SAndroid Build Coastguard Worker {
50*58b9f456SAndroid Build Coastguard Worker return default_error_condition(code) == condition;
51*58b9f456SAndroid Build Coastguard Worker }
52*58b9f456SAndroid Build Coastguard Worker
53*58b9f456SAndroid Build Coastguard Worker bool
equivalent(const error_code & code,int condition) const54*58b9f456SAndroid Build Coastguard Worker error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
55*58b9f456SAndroid Build Coastguard Worker {
56*58b9f456SAndroid Build Coastguard Worker return *this == code.category() && code.value() == condition;
57*58b9f456SAndroid Build Coastguard Worker }
58*58b9f456SAndroid Build Coastguard Worker
59*58b9f456SAndroid Build Coastguard Worker #if !defined(_LIBCPP_HAS_NO_THREADS)
60*58b9f456SAndroid Build Coastguard Worker namespace {
61*58b9f456SAndroid Build Coastguard Worker
62*58b9f456SAndroid Build Coastguard Worker // GLIBC also uses 1024 as the maximum buffer size internally.
63*58b9f456SAndroid Build Coastguard Worker constexpr size_t strerror_buff_size = 1024;
64*58b9f456SAndroid Build Coastguard Worker
65*58b9f456SAndroid Build Coastguard Worker string do_strerror_r(int ev);
66*58b9f456SAndroid Build Coastguard Worker
67*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_MSVCRT_LIKE)
do_strerror_r(int ev)68*58b9f456SAndroid Build Coastguard Worker string do_strerror_r(int ev) {
69*58b9f456SAndroid Build Coastguard Worker char buffer[strerror_buff_size];
70*58b9f456SAndroid Build Coastguard Worker if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
71*58b9f456SAndroid Build Coastguard Worker return string(buffer);
72*58b9f456SAndroid Build Coastguard Worker std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
73*58b9f456SAndroid Build Coastguard Worker return string(buffer);
74*58b9f456SAndroid Build Coastguard Worker }
75*58b9f456SAndroid Build Coastguard Worker #else
76*58b9f456SAndroid Build Coastguard Worker
77*58b9f456SAndroid Build Coastguard Worker // Only one of the two following functions will be used, depending on
78*58b9f456SAndroid Build Coastguard Worker // the return type of strerror_r:
79*58b9f456SAndroid Build Coastguard Worker
80*58b9f456SAndroid Build Coastguard Worker // For the GNU variant, a char* return value:
81*58b9f456SAndroid Build Coastguard Worker __attribute__((unused)) const char *
handle_strerror_r_return(char * strerror_return,char * buffer)82*58b9f456SAndroid Build Coastguard Worker handle_strerror_r_return(char *strerror_return, char *buffer) {
83*58b9f456SAndroid Build Coastguard Worker // GNU always returns a string pointer in its return value. The
84*58b9f456SAndroid Build Coastguard Worker // string might point to either the input buffer, or a static
85*58b9f456SAndroid Build Coastguard Worker // buffer, but we don't care which.
86*58b9f456SAndroid Build Coastguard Worker return strerror_return;
87*58b9f456SAndroid Build Coastguard Worker }
88*58b9f456SAndroid Build Coastguard Worker
89*58b9f456SAndroid Build Coastguard Worker // For the POSIX variant: an int return value.
90*58b9f456SAndroid Build Coastguard Worker __attribute__((unused)) const char *
handle_strerror_r_return(int strerror_return,char * buffer)91*58b9f456SAndroid Build Coastguard Worker handle_strerror_r_return(int strerror_return, char *buffer) {
92*58b9f456SAndroid Build Coastguard Worker // The POSIX variant either:
93*58b9f456SAndroid Build Coastguard Worker // - fills in the provided buffer and returns 0
94*58b9f456SAndroid Build Coastguard Worker // - returns a positive error value, or
95*58b9f456SAndroid Build Coastguard Worker // - returns -1 and fills in errno with an error value.
96*58b9f456SAndroid Build Coastguard Worker if (strerror_return == 0)
97*58b9f456SAndroid Build Coastguard Worker return buffer;
98*58b9f456SAndroid Build Coastguard Worker
99*58b9f456SAndroid Build Coastguard Worker // Only handle EINVAL. Other errors abort.
100*58b9f456SAndroid Build Coastguard Worker int new_errno = strerror_return == -1 ? errno : strerror_return;
101*58b9f456SAndroid Build Coastguard Worker if (new_errno == EINVAL)
102*58b9f456SAndroid Build Coastguard Worker return "";
103*58b9f456SAndroid Build Coastguard Worker
104*58b9f456SAndroid Build Coastguard Worker _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
105*58b9f456SAndroid Build Coastguard Worker // FIXME maybe? 'strerror_buff_size' is likely to exceed the
106*58b9f456SAndroid Build Coastguard Worker // maximum error size so ERANGE shouldn't be returned.
107*58b9f456SAndroid Build Coastguard Worker std::abort();
108*58b9f456SAndroid Build Coastguard Worker }
109*58b9f456SAndroid Build Coastguard Worker
110*58b9f456SAndroid Build Coastguard Worker // This function handles both GNU and POSIX variants, dispatching to
111*58b9f456SAndroid Build Coastguard Worker // one of the two above functions.
do_strerror_r(int ev)112*58b9f456SAndroid Build Coastguard Worker string do_strerror_r(int ev) {
113*58b9f456SAndroid Build Coastguard Worker char buffer[strerror_buff_size];
114*58b9f456SAndroid Build Coastguard Worker // Preserve errno around the call. (The C++ standard requires that
115*58b9f456SAndroid Build Coastguard Worker // system_error functions not modify errno).
116*58b9f456SAndroid Build Coastguard Worker const int old_errno = errno;
117*58b9f456SAndroid Build Coastguard Worker const char *error_message = handle_strerror_r_return(
118*58b9f456SAndroid Build Coastguard Worker ::strerror_r(ev, buffer, strerror_buff_size), buffer);
119*58b9f456SAndroid Build Coastguard Worker // If we didn't get any message, print one now.
120*58b9f456SAndroid Build Coastguard Worker if (!error_message[0]) {
121*58b9f456SAndroid Build Coastguard Worker std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
122*58b9f456SAndroid Build Coastguard Worker error_message = buffer;
123*58b9f456SAndroid Build Coastguard Worker }
124*58b9f456SAndroid Build Coastguard Worker errno = old_errno;
125*58b9f456SAndroid Build Coastguard Worker return string(error_message);
126*58b9f456SAndroid Build Coastguard Worker }
127*58b9f456SAndroid Build Coastguard Worker #endif
128*58b9f456SAndroid Build Coastguard Worker } // end namespace
129*58b9f456SAndroid Build Coastguard Worker #endif
130*58b9f456SAndroid Build Coastguard Worker
131*58b9f456SAndroid Build Coastguard Worker string
message(int ev) const132*58b9f456SAndroid Build Coastguard Worker __do_message::message(int ev) const
133*58b9f456SAndroid Build Coastguard Worker {
134*58b9f456SAndroid Build Coastguard Worker #if defined(_LIBCPP_HAS_NO_THREADS)
135*58b9f456SAndroid Build Coastguard Worker return string(::strerror(ev));
136*58b9f456SAndroid Build Coastguard Worker #else
137*58b9f456SAndroid Build Coastguard Worker return do_strerror_r(ev);
138*58b9f456SAndroid Build Coastguard Worker #endif
139*58b9f456SAndroid Build Coastguard Worker }
140*58b9f456SAndroid Build Coastguard Worker
141*58b9f456SAndroid Build Coastguard Worker class _LIBCPP_HIDDEN __generic_error_category
142*58b9f456SAndroid Build Coastguard Worker : public __do_message
143*58b9f456SAndroid Build Coastguard Worker {
144*58b9f456SAndroid Build Coastguard Worker public:
145*58b9f456SAndroid Build Coastguard Worker virtual const char* name() const _NOEXCEPT;
146*58b9f456SAndroid Build Coastguard Worker virtual string message(int ev) const;
147*58b9f456SAndroid Build Coastguard Worker };
148*58b9f456SAndroid Build Coastguard Worker
149*58b9f456SAndroid Build Coastguard Worker const char*
name() const150*58b9f456SAndroid Build Coastguard Worker __generic_error_category::name() const _NOEXCEPT
151*58b9f456SAndroid Build Coastguard Worker {
152*58b9f456SAndroid Build Coastguard Worker return "generic";
153*58b9f456SAndroid Build Coastguard Worker }
154*58b9f456SAndroid Build Coastguard Worker
155*58b9f456SAndroid Build Coastguard Worker string
message(int ev) const156*58b9f456SAndroid Build Coastguard Worker __generic_error_category::message(int ev) const
157*58b9f456SAndroid Build Coastguard Worker {
158*58b9f456SAndroid Build Coastguard Worker #ifdef _LIBCPP_ELAST
159*58b9f456SAndroid Build Coastguard Worker if (ev > _LIBCPP_ELAST)
160*58b9f456SAndroid Build Coastguard Worker return string("unspecified generic_category error");
161*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_ELAST
162*58b9f456SAndroid Build Coastguard Worker return __do_message::message(ev);
163*58b9f456SAndroid Build Coastguard Worker }
164*58b9f456SAndroid Build Coastguard Worker
165*58b9f456SAndroid Build Coastguard Worker const error_category&
generic_category()166*58b9f456SAndroid Build Coastguard Worker generic_category() _NOEXCEPT
167*58b9f456SAndroid Build Coastguard Worker {
168*58b9f456SAndroid Build Coastguard Worker static __generic_error_category s;
169*58b9f456SAndroid Build Coastguard Worker return s;
170*58b9f456SAndroid Build Coastguard Worker }
171*58b9f456SAndroid Build Coastguard Worker
172*58b9f456SAndroid Build Coastguard Worker class _LIBCPP_HIDDEN __system_error_category
173*58b9f456SAndroid Build Coastguard Worker : public __do_message
174*58b9f456SAndroid Build Coastguard Worker {
175*58b9f456SAndroid Build Coastguard Worker public:
176*58b9f456SAndroid Build Coastguard Worker virtual const char* name() const _NOEXCEPT;
177*58b9f456SAndroid Build Coastguard Worker virtual string message(int ev) const;
178*58b9f456SAndroid Build Coastguard Worker virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
179*58b9f456SAndroid Build Coastguard Worker };
180*58b9f456SAndroid Build Coastguard Worker
181*58b9f456SAndroid Build Coastguard Worker const char*
name() const182*58b9f456SAndroid Build Coastguard Worker __system_error_category::name() const _NOEXCEPT
183*58b9f456SAndroid Build Coastguard Worker {
184*58b9f456SAndroid Build Coastguard Worker return "system";
185*58b9f456SAndroid Build Coastguard Worker }
186*58b9f456SAndroid Build Coastguard Worker
187*58b9f456SAndroid Build Coastguard Worker string
message(int ev) const188*58b9f456SAndroid Build Coastguard Worker __system_error_category::message(int ev) const
189*58b9f456SAndroid Build Coastguard Worker {
190*58b9f456SAndroid Build Coastguard Worker #ifdef _LIBCPP_ELAST
191*58b9f456SAndroid Build Coastguard Worker if (ev > _LIBCPP_ELAST)
192*58b9f456SAndroid Build Coastguard Worker return string("unspecified system_category error");
193*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_ELAST
194*58b9f456SAndroid Build Coastguard Worker return __do_message::message(ev);
195*58b9f456SAndroid Build Coastguard Worker }
196*58b9f456SAndroid Build Coastguard Worker
197*58b9f456SAndroid Build Coastguard Worker error_condition
default_error_condition(int ev) const198*58b9f456SAndroid Build Coastguard Worker __system_error_category::default_error_condition(int ev) const _NOEXCEPT
199*58b9f456SAndroid Build Coastguard Worker {
200*58b9f456SAndroid Build Coastguard Worker #ifdef _LIBCPP_ELAST
201*58b9f456SAndroid Build Coastguard Worker if (ev > _LIBCPP_ELAST)
202*58b9f456SAndroid Build Coastguard Worker return error_condition(ev, system_category());
203*58b9f456SAndroid Build Coastguard Worker #endif // _LIBCPP_ELAST
204*58b9f456SAndroid Build Coastguard Worker return error_condition(ev, generic_category());
205*58b9f456SAndroid Build Coastguard Worker }
206*58b9f456SAndroid Build Coastguard Worker
207*58b9f456SAndroid Build Coastguard Worker const error_category&
system_category()208*58b9f456SAndroid Build Coastguard Worker system_category() _NOEXCEPT
209*58b9f456SAndroid Build Coastguard Worker {
210*58b9f456SAndroid Build Coastguard Worker static __system_error_category s;
211*58b9f456SAndroid Build Coastguard Worker return s;
212*58b9f456SAndroid Build Coastguard Worker }
213*58b9f456SAndroid Build Coastguard Worker
214*58b9f456SAndroid Build Coastguard Worker // error_condition
215*58b9f456SAndroid Build Coastguard Worker
216*58b9f456SAndroid Build Coastguard Worker string
message() const217*58b9f456SAndroid Build Coastguard Worker error_condition::message() const
218*58b9f456SAndroid Build Coastguard Worker {
219*58b9f456SAndroid Build Coastguard Worker return __cat_->message(__val_);
220*58b9f456SAndroid Build Coastguard Worker }
221*58b9f456SAndroid Build Coastguard Worker
222*58b9f456SAndroid Build Coastguard Worker // error_code
223*58b9f456SAndroid Build Coastguard Worker
224*58b9f456SAndroid Build Coastguard Worker string
message() const225*58b9f456SAndroid Build Coastguard Worker error_code::message() const
226*58b9f456SAndroid Build Coastguard Worker {
227*58b9f456SAndroid Build Coastguard Worker return __cat_->message(__val_);
228*58b9f456SAndroid Build Coastguard Worker }
229*58b9f456SAndroid Build Coastguard Worker
230*58b9f456SAndroid Build Coastguard Worker // system_error
231*58b9f456SAndroid Build Coastguard Worker
232*58b9f456SAndroid Build Coastguard Worker string
__init(const error_code & ec,string what_arg)233*58b9f456SAndroid Build Coastguard Worker system_error::__init(const error_code& ec, string what_arg)
234*58b9f456SAndroid Build Coastguard Worker {
235*58b9f456SAndroid Build Coastguard Worker if (ec)
236*58b9f456SAndroid Build Coastguard Worker {
237*58b9f456SAndroid Build Coastguard Worker if (!what_arg.empty())
238*58b9f456SAndroid Build Coastguard Worker what_arg += ": ";
239*58b9f456SAndroid Build Coastguard Worker what_arg += ec.message();
240*58b9f456SAndroid Build Coastguard Worker }
241*58b9f456SAndroid Build Coastguard Worker return what_arg;
242*58b9f456SAndroid Build Coastguard Worker }
243*58b9f456SAndroid Build Coastguard Worker
system_error(error_code ec,const string & what_arg)244*58b9f456SAndroid Build Coastguard Worker system_error::system_error(error_code ec, const string& what_arg)
245*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(ec, what_arg)),
246*58b9f456SAndroid Build Coastguard Worker __ec_(ec)
247*58b9f456SAndroid Build Coastguard Worker {
248*58b9f456SAndroid Build Coastguard Worker }
249*58b9f456SAndroid Build Coastguard Worker
system_error(error_code ec,const char * what_arg)250*58b9f456SAndroid Build Coastguard Worker system_error::system_error(error_code ec, const char* what_arg)
251*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(ec, what_arg)),
252*58b9f456SAndroid Build Coastguard Worker __ec_(ec)
253*58b9f456SAndroid Build Coastguard Worker {
254*58b9f456SAndroid Build Coastguard Worker }
255*58b9f456SAndroid Build Coastguard Worker
system_error(error_code ec)256*58b9f456SAndroid Build Coastguard Worker system_error::system_error(error_code ec)
257*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(ec, "")),
258*58b9f456SAndroid Build Coastguard Worker __ec_(ec)
259*58b9f456SAndroid Build Coastguard Worker {
260*58b9f456SAndroid Build Coastguard Worker }
261*58b9f456SAndroid Build Coastguard Worker
system_error(int ev,const error_category & ecat,const string & what_arg)262*58b9f456SAndroid Build Coastguard Worker system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
263*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(error_code(ev, ecat), what_arg)),
264*58b9f456SAndroid Build Coastguard Worker __ec_(error_code(ev, ecat))
265*58b9f456SAndroid Build Coastguard Worker {
266*58b9f456SAndroid Build Coastguard Worker }
267*58b9f456SAndroid Build Coastguard Worker
system_error(int ev,const error_category & ecat,const char * what_arg)268*58b9f456SAndroid Build Coastguard Worker system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
269*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(error_code(ev, ecat), what_arg)),
270*58b9f456SAndroid Build Coastguard Worker __ec_(error_code(ev, ecat))
271*58b9f456SAndroid Build Coastguard Worker {
272*58b9f456SAndroid Build Coastguard Worker }
273*58b9f456SAndroid Build Coastguard Worker
system_error(int ev,const error_category & ecat)274*58b9f456SAndroid Build Coastguard Worker system_error::system_error(int ev, const error_category& ecat)
275*58b9f456SAndroid Build Coastguard Worker : runtime_error(__init(error_code(ev, ecat), "")),
276*58b9f456SAndroid Build Coastguard Worker __ec_(error_code(ev, ecat))
277*58b9f456SAndroid Build Coastguard Worker {
278*58b9f456SAndroid Build Coastguard Worker }
279*58b9f456SAndroid Build Coastguard Worker
~system_error()280*58b9f456SAndroid Build Coastguard Worker system_error::~system_error() _NOEXCEPT
281*58b9f456SAndroid Build Coastguard Worker {
282*58b9f456SAndroid Build Coastguard Worker }
283*58b9f456SAndroid Build Coastguard Worker
284*58b9f456SAndroid Build Coastguard Worker void
__throw_system_error(int ev,const char * what_arg)285*58b9f456SAndroid Build Coastguard Worker __throw_system_error(int ev, const char* what_arg)
286*58b9f456SAndroid Build Coastguard Worker {
287*58b9f456SAndroid Build Coastguard Worker #ifndef _LIBCPP_NO_EXCEPTIONS
288*58b9f456SAndroid Build Coastguard Worker throw system_error(error_code(ev, system_category()), what_arg);
289*58b9f456SAndroid Build Coastguard Worker #else
290*58b9f456SAndroid Build Coastguard Worker (void)ev;
291*58b9f456SAndroid Build Coastguard Worker (void)what_arg;
292*58b9f456SAndroid Build Coastguard Worker _VSTD::abort();
293*58b9f456SAndroid Build Coastguard Worker #endif
294*58b9f456SAndroid Build Coastguard Worker }
295*58b9f456SAndroid Build Coastguard Worker
296*58b9f456SAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD
297