blob: 72623ea6bc813f261268c409d1a5bf47fba1b96f [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
12#define _LIBCPP_BUILDING_SYSTEM_ERROR
Howard Hinnant3e519522010-05-11 19:42:16 +000013#include "system_error"
Dan Alberta76dfbd2015-01-06 17:34:51 +000014
Eric Fiseliere8fd1642015-08-18 21:08:54 +000015#include "include/config_elast.h"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000016#include "cerrno"
Howard Hinnant3e519522010-05-11 19:42:16 +000017#include "cstring"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000018#include "cstdio"
19#include "cstdlib"
Dan Alberta76dfbd2015-01-06 17:34:51 +000020#include "string"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000021#include "string.h"
Eric Fiseliere49cdfb2017-02-04 23:22:28 +000022#include "__debug"
Howard Hinnant3e519522010-05-11 19:42:16 +000023
Dan Albert953d7d42016-06-15 20:20:32 +000024#if defined(__ANDROID__)
25#include <android/api-level.h>
26#endif
27
Howard Hinnant3e519522010-05-11 19:42:16 +000028_LIBCPP_BEGIN_NAMESPACE_STD
29
30// class error_category
31
Eric Fiselier11f60452017-01-17 03:16:26 +000032#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
Howard Hinnanta62f2892011-05-26 19:48:01 +000033error_category::error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000034{
35}
Eric Fiselier9aca97d2017-01-02 22:17:51 +000036#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000037
Howard Hinnanta62f2892011-05-26 19:48:01 +000038error_category::~error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000039{
40}
41
42error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +000043error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000044{
45 return error_condition(ev, *this);
46}
47
48bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000049error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000050{
51 return default_error_condition(code) == condition;
52}
53
54bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000055error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000056{
57 return *this == code.category() && code.value() == condition;
58}
59
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +000060#if !defined(_LIBCPP_HAS_NO_THREADS)
Eric Fiselier9778a6d2016-06-14 03:45:31 +000061namespace {
62
63// GLIBC also uses 1024 as the maximum buffer size internally.
64constexpr size_t strerror_buff_size = 1024;
65
66string do_strerror_r(int ev);
67
Eric Fiselier1ec02622017-05-31 22:14:05 +000068#if defined(_LIBCPP_MSVCRT_LIKE)
Saleem Abdulrasooledd09b32017-01-03 02:00:33 +000069string do_strerror_r(int ev) {
70 char buffer[strerror_buff_size];
71 if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
72 return string(buffer);
73 std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
74 return string(buffer);
75}
Eric Fiselier9778a6d2016-06-14 03:45:31 +000076#else
James Y Knight929f1592017-07-19 21:48:49 +000077
78// Only one of the two following functions will be used, depending on
79// the return type of strerror_r:
80
81// For the GNU variant, a char* return value:
82__attribute__((unused)) const char *
83handle_strerror_r_return(char *strerror_return, char *buffer) {
84 // GNU always returns a string pointer in its return value. The
85 // string might point to either the input buffer, or a static
86 // buffer, but we don't care which.
87 return strerror_return;
88}
89
90// For the POSIX variant: an int return value.
91__attribute__((unused)) const char *
92handle_strerror_r_return(int strerror_return, char *buffer) {
93 // The POSIX variant either:
94 // - fills in the provided buffer and returns 0
95 // - returns a positive error value, or
96 // - returns -1 and fills in errno with an error value.
97 if (strerror_return == 0)
98 return buffer;
99
100 // Only handle EINVAL. Other errors abort.
101 int new_errno = strerror_return == -1 ? errno : strerror_return;
102 if (new_errno == EINVAL)
103 return "";
104
105 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
106 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
107 // maximum error size so ERANGE shouldn't be returned.
108 std::abort();
109}
110
111// This function handles both GNU and POSIX variants, dispatching to
112// one of the two above functions.
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000113string do_strerror_r(int ev) {
114 char buffer[strerror_buff_size];
James Y Knight929f1592017-07-19 21:48:49 +0000115 // Preserve errno around the call. (The C++ standard requires that
116 // system_error functions not modify errno).
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000117 const int old_errno = errno;
James Y Knight929f1592017-07-19 21:48:49 +0000118 const char *error_message = handle_strerror_r_return(
119 ::strerror_r(ev, buffer, strerror_buff_size), buffer);
120 // If we didn't get any message, print one now.
121 if (!error_message[0]) {
122 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
123 error_message = buffer;
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000124 }
James Y Knight929f1592017-07-19 21:48:49 +0000125 errno = old_errno;
126 return string(error_message);
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000127}
128#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000129} // end namespace
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +0000130#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000131
Howard Hinnant3e519522010-05-11 19:42:16 +0000132string
133__do_message::message(int ev) const
134{
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000135#if defined(_LIBCPP_HAS_NO_THREADS)
136 return string(::strerror(ev));
137#else
138 return do_strerror_r(ev);
139#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000140}
141
142class _LIBCPP_HIDDEN __generic_error_category
143 : public __do_message
144{
145public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000146 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000147 virtual string message(int ev) const;
148};
149
150const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000151__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000152{
153 return "generic";
154}
155
156string
157__generic_error_category::message(int ev) const
158{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000159#ifdef _LIBCPP_ELAST
160 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000161 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000162#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000163 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000164}
165
166const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000167generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000168{
169 static __generic_error_category s;
170 return s;
171}
172
173class _LIBCPP_HIDDEN __system_error_category
174 : public __do_message
175{
176public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000177 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000178 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000179 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000180};
181
182const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000183__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000184{
185 return "system";
186}
187
188string
189__system_error_category::message(int ev) const
190{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000191#ifdef _LIBCPP_ELAST
192 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000193 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000194#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000195 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000196}
197
198error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000199__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000200{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000201#ifdef _LIBCPP_ELAST
202 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000203 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000204#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000205 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000206}
207
208const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000209system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000210{
211 static __system_error_category s;
212 return s;
213}
214
215// error_condition
216
217string
218error_condition::message() const
219{
220 return __cat_->message(__val_);
221}
222
223// error_code
224
225string
226error_code::message() const
227{
228 return __cat_->message(__val_);
229}
230
231// system_error
232
233string
234system_error::__init(const error_code& ec, string what_arg)
235{
236 if (ec)
237 {
238 if (!what_arg.empty())
239 what_arg += ": ";
240 what_arg += ec.message();
241 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000242 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000243}
244
245system_error::system_error(error_code ec, const string& what_arg)
246 : runtime_error(__init(ec, what_arg)),
247 __ec_(ec)
248{
249}
250
251system_error::system_error(error_code ec, const char* what_arg)
252 : runtime_error(__init(ec, what_arg)),
253 __ec_(ec)
254{
255}
256
257system_error::system_error(error_code ec)
258 : runtime_error(__init(ec, "")),
259 __ec_(ec)
260{
261}
262
263system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
264 : runtime_error(__init(error_code(ev, ecat), what_arg)),
265 __ec_(error_code(ev, ecat))
266{
267}
268
269system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
270 : runtime_error(__init(error_code(ev, ecat), what_arg)),
271 __ec_(error_code(ev, ecat))
272{
273}
274
275system_error::system_error(int ev, const error_category& ecat)
276 : runtime_error(__init(error_code(ev, ecat), "")),
277 __ec_(error_code(ev, ecat))
278{
279}
280
Howard Hinnanta62f2892011-05-26 19:48:01 +0000281system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000282{
283}
284
285void
286__throw_system_error(int ev, const char* what_arg)
287{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000288#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000289 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000290#else
291 (void)ev;
292 (void)what_arg;
Marshall Clowd437fa52016-08-25 15:09:01 +0000293 _VSTD::abort();
Howard Hinnant54b409f2010-08-11 17:04:31 +0000294#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000295}
296
297_LIBCPP_END_NAMESPACE_STD