blob: 4ecafeaa3b87ee00729b6eeb9a4fe61dfdfe3bb0 [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"
20#include "cassert"
Dan Alberta76dfbd2015-01-06 17:34:51 +000021#include "string"
Eric Fiselier9778a6d2016-06-14 03:45:31 +000022#include "string.h"
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 Fiselier9aca97d2017-01-02 22:17:51 +000032#if defined(_LIBCPP_DEPRECATED_ABI_EXTERNAL_ERROR_CATEGORY_CONSTRUCTOR)
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
Dan Albert953d7d42016-06-15 20:20:32 +000068#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \
69 && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
Eric Fiselier9778a6d2016-06-14 03:45:31 +000070// GNU Extended version
71string do_strerror_r(int ev) {
72 char buffer[strerror_buff_size];
73 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
74 return string(ret);
75}
76#else
77// POSIX version
78string do_strerror_r(int ev) {
79 char buffer[strerror_buff_size];
80 const int old_errno = errno;
Eric Fiselier61df7902016-06-14 06:08:10 +000081 int ret;
82 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
Eric Fiselier79e05742016-06-14 06:03:20 +000083 // If `ret == -1` then the error is specified using `errno`, otherwise
84 // `ret` represents the error.
85 const int new_errno = ret == -1 ? errno : ret;
Eric Fiselier9778a6d2016-06-14 03:45:31 +000086 errno = old_errno;
87 if (new_errno == EINVAL) {
88 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
89 return string(buffer);
90 } else {
91 assert(new_errno == ERANGE);
92 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
93 // maximum error size so ERANGE shouldn't be returned.
94 std::abort();
95 }
96 }
97 return string(buffer);
98}
99#endif
100
101} // end namespace
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +0000102#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000103
Howard Hinnant3e519522010-05-11 19:42:16 +0000104string
105__do_message::message(int ev) const
106{
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000107#if defined(_LIBCPP_HAS_NO_THREADS)
108 return string(::strerror(ev));
109#else
110 return do_strerror_r(ev);
111#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000112}
113
114class _LIBCPP_HIDDEN __generic_error_category
115 : public __do_message
116{
117public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000118 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000119 virtual string message(int ev) const;
120};
121
122const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000123__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000124{
125 return "generic";
126}
127
128string
129__generic_error_category::message(int ev) const
130{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000131#ifdef _LIBCPP_ELAST
132 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000133 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000134#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000135 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000136}
137
138const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000139generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000140{
141 static __generic_error_category s;
142 return s;
143}
144
145class _LIBCPP_HIDDEN __system_error_category
146 : public __do_message
147{
148public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000149 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000150 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000151 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000152};
153
154const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000155__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000156{
157 return "system";
158}
159
160string
161__system_error_category::message(int ev) const
162{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000163#ifdef _LIBCPP_ELAST
164 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000165 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000166#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000167 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000168}
169
170error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000171__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000172{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000173#ifdef _LIBCPP_ELAST
174 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000175 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000176#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000177 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000178}
179
180const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000181system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000182{
183 static __system_error_category s;
184 return s;
185}
186
187// error_condition
188
189string
190error_condition::message() const
191{
192 return __cat_->message(__val_);
193}
194
195// error_code
196
197string
198error_code::message() const
199{
200 return __cat_->message(__val_);
201}
202
203// system_error
204
205string
206system_error::__init(const error_code& ec, string what_arg)
207{
208 if (ec)
209 {
210 if (!what_arg.empty())
211 what_arg += ": ";
212 what_arg += ec.message();
213 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000214 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000215}
216
217system_error::system_error(error_code ec, const string& what_arg)
218 : runtime_error(__init(ec, what_arg)),
219 __ec_(ec)
220{
221}
222
223system_error::system_error(error_code ec, const char* what_arg)
224 : runtime_error(__init(ec, what_arg)),
225 __ec_(ec)
226{
227}
228
229system_error::system_error(error_code ec)
230 : runtime_error(__init(ec, "")),
231 __ec_(ec)
232{
233}
234
235system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
236 : runtime_error(__init(error_code(ev, ecat), what_arg)),
237 __ec_(error_code(ev, ecat))
238{
239}
240
241system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
242 : runtime_error(__init(error_code(ev, ecat), what_arg)),
243 __ec_(error_code(ev, ecat))
244{
245}
246
247system_error::system_error(int ev, const error_category& ecat)
248 : runtime_error(__init(error_code(ev, ecat), "")),
249 __ec_(error_code(ev, ecat))
250{
251}
252
Howard Hinnanta62f2892011-05-26 19:48:01 +0000253system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000254{
255}
256
257void
258__throw_system_error(int ev, const char* what_arg)
259{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000260#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000261 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000262#else
263 (void)ev;
264 (void)what_arg;
Marshall Clowd437fa52016-08-25 15:09:01 +0000265 _VSTD::abort();
Howard Hinnant54b409f2010-08-11 17:04:31 +0000266#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000267}
268
269_LIBCPP_END_NAMESPACE_STD