blob: 06caa6fecd9fec6b1da6fcdedf78910cd4ebbb42 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:16 +00001//===---------------------- system_error.cpp ------------------------------===//
2//
Howard Hinnant5b08a8a2010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnant3e519522010-05-11 19:42:16 +00004//
Howard Hinnant412dbeb2010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnant3e519522010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
Jonathan Roelofsa409d592014-09-02 20:34:23 +000010#include "__config"
Dan Alberta76dfbd2015-01-06 17:34:51 +000011
Howard Hinnant3e519522010-05-11 19:42:16 +000012#include "system_error"
Dan Alberta76dfbd2015-01-06 17:34:51 +000013
Eric Fiseliere8fd1642015-08-18 21:08:54 +000014#include "include/config_elast.h"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000015#include "cerrno"
Howard Hinnant3e519522010-05-11 19:42:16 +000016#include "cstring"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000017#include "cstdio"
18#include "cstdlib"
Dan Alberta76dfbd2015-01-06 17:34:51 +000019#include "string"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000020#include "string.h"
Eric Fiseliere49cdfb2017-02-04 23:22:28 +000021#include "__debug"
Howard Hinnant3e519522010-05-11 19:42:16 +000022
Dan Albert953d7d42016-06-15 20:20:32 +000023#if defined(__ANDROID__)
24#include <android/api-level.h>
25#endif
26
Howard Hinnant3e519522010-05-11 19:42:16 +000027_LIBCPP_BEGIN_NAMESPACE_STD
28
29// class error_category
30
Eric Fiselier11f60452017-01-17 03:16:26 +000031#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
Howard Hinnanta62f2892011-05-26 19:48:01 +000032error_category::error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000033{
34}
Eric Fiselier9aca97d2017-01-02 22:17:51 +000035#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000036
Howard Hinnanta62f2892011-05-26 19:48:01 +000037error_category::~error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000038{
39}
40
41error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +000042error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000043{
44 return error_condition(ev, *this);
45}
46
47bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000048error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000049{
50 return default_error_condition(code) == condition;
51}
52
53bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000054error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000055{
56 return *this == code.category() && code.value() == condition;
57}
58
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +000059#if !defined(_LIBCPP_HAS_NO_THREADS)
Eric Fiselier9778a6d2016-06-14 03:45:31 +000060namespace {
61
62// GLIBC also uses 1024 as the maximum buffer size internally.
63constexpr size_t strerror_buff_size = 1024;
64
65string do_strerror_r(int ev);
66
Eric Fiselier1ec02622017-05-31 22:14:05 +000067#if defined(_LIBCPP_MSVCRT_LIKE)
Saleem Abdulrasooledd09b32017-01-03 02:00:33 +000068string do_strerror_r(int ev) {
69 char buffer[strerror_buff_size];
70 if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
71 return string(buffer);
72 std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
73 return string(buffer);
74}
Eric Fiselier9778a6d2016-06-14 03:45:31 +000075#else
James Y Knight929f1592017-07-19 21:48:49 +000076
77// Only one of the two following functions will be used, depending on
78// the return type of strerror_r:
79
80// For the GNU variant, a char* return value:
81__attribute__((unused)) const char *
82handle_strerror_r_return(char *strerror_return, char *buffer) {
83 // GNU always returns a string pointer in its return value. The
84 // string might point to either the input buffer, or a static
85 // buffer, but we don't care which.
86 return strerror_return;
87}
88
89// For the POSIX variant: an int return value.
90__attribute__((unused)) const char *
91handle_strerror_r_return(int strerror_return, char *buffer) {
92 // The POSIX variant either:
93 // - fills in the provided buffer and returns 0
94 // - returns a positive error value, or
95 // - returns -1 and fills in errno with an error value.
96 if (strerror_return == 0)
97 return buffer;
98
99 // Only handle EINVAL. Other errors abort.
100 int new_errno = strerror_return == -1 ? errno : strerror_return;
101 if (new_errno == EINVAL)
102 return "";
103
104 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
105 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
106 // maximum error size so ERANGE shouldn't be returned.
107 std::abort();
108}
109
110// This function handles both GNU and POSIX variants, dispatching to
111// one of the two above functions.
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000112string do_strerror_r(int ev) {
113 char buffer[strerror_buff_size];
James Y Knight929f1592017-07-19 21:48:49 +0000114 // Preserve errno around the call. (The C++ standard requires that
115 // system_error functions not modify errno).
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000116 const int old_errno = errno;
James Y Knight929f1592017-07-19 21:48:49 +0000117 const char *error_message = handle_strerror_r_return(
118 ::strerror_r(ev, buffer, strerror_buff_size), buffer);
119 // If we didn't get any message, print one now.
120 if (!error_message[0]) {
121 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
122 error_message = buffer;
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000123 }
James Y Knight929f1592017-07-19 21:48:49 +0000124 errno = old_errno;
125 return string(error_message);
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000126}
127#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000128} // end namespace
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +0000129#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000130
Howard Hinnant3e519522010-05-11 19:42:16 +0000131string
132__do_message::message(int ev) const
133{
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000134#if defined(_LIBCPP_HAS_NO_THREADS)
135 return string(::strerror(ev));
136#else
137 return do_strerror_r(ev);
138#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000139}
140
141class _LIBCPP_HIDDEN __generic_error_category
142 : public __do_message
143{
144public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000145 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000146 virtual string message(int ev) const;
147};
148
149const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000150__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000151{
152 return "generic";
153}
154
155string
156__generic_error_category::message(int ev) const
157{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000158#ifdef _LIBCPP_ELAST
159 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000160 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000161#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000162 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000163}
164
165const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000166generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000167{
168 static __generic_error_category s;
169 return s;
170}
171
172class _LIBCPP_HIDDEN __system_error_category
173 : public __do_message
174{
175public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000176 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000177 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000178 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000179};
180
181const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000182__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000183{
184 return "system";
185}
186
187string
188__system_error_category::message(int ev) const
189{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000190#ifdef _LIBCPP_ELAST
191 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000192 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000193#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000194 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000195}
196
197error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000198__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000199{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000200#ifdef _LIBCPP_ELAST
201 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000202 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000203#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000204 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000205}
206
207const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000208system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000209{
210 static __system_error_category s;
211 return s;
212}
213
214// error_condition
215
216string
217error_condition::message() const
218{
219 return __cat_->message(__val_);
220}
221
222// error_code
223
224string
225error_code::message() const
226{
227 return __cat_->message(__val_);
228}
229
230// system_error
231
232string
233system_error::__init(const error_code& ec, string what_arg)
234{
235 if (ec)
236 {
237 if (!what_arg.empty())
238 what_arg += ": ";
239 what_arg += ec.message();
240 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000241 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000242}
243
244system_error::system_error(error_code ec, const string& what_arg)
245 : runtime_error(__init(ec, what_arg)),
246 __ec_(ec)
247{
248}
249
250system_error::system_error(error_code ec, const char* what_arg)
251 : runtime_error(__init(ec, what_arg)),
252 __ec_(ec)
253{
254}
255
256system_error::system_error(error_code ec)
257 : runtime_error(__init(ec, "")),
258 __ec_(ec)
259{
260}
261
262system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
263 : runtime_error(__init(error_code(ev, ecat), what_arg)),
264 __ec_(error_code(ev, ecat))
265{
266}
267
268system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
269 : runtime_error(__init(error_code(ev, ecat), what_arg)),
270 __ec_(error_code(ev, ecat))
271{
272}
273
274system_error::system_error(int ev, const error_category& ecat)
275 : runtime_error(__init(error_code(ev, ecat), "")),
276 __ec_(error_code(ev, ecat))
277{
278}
279
Howard Hinnanta62f2892011-05-26 19:48:01 +0000280system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000281{
282}
283
284void
285__throw_system_error(int ev, const char* what_arg)
286{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000287#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000288 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000289#else
290 (void)ev;
291 (void)what_arg;
Marshall Clowd437fa52016-08-25 15:09:01 +0000292 _VSTD::abort();
Howard Hinnant54b409f2010-08-11 17:04:31 +0000293#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000294}
295
296_LIBCPP_END_NAMESPACE_STD