blob: 3a2255425f092443c7f42ee49ba65d0788e42c19 [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
Howard Hinnanta62f2892011-05-26 19:48:01 +000032error_category::error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000033{
34}
35
Howard Hinnanta62f2892011-05-26 19:48:01 +000036error_category::~error_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000037{
38}
39
40error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +000041error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000042{
43 return error_condition(ev, *this);
44}
45
46bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000047error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000048{
49 return default_error_condition(code) == condition;
50}
51
52bool
Howard Hinnanta62f2892011-05-26 19:48:01 +000053error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +000054{
55 return *this == code.category() && code.value() == condition;
56}
57
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +000058#if !defined(_LIBCPP_HAS_NO_THREADS)
Eric Fiselier9778a6d2016-06-14 03:45:31 +000059namespace {
60
61// GLIBC also uses 1024 as the maximum buffer size internally.
62constexpr size_t strerror_buff_size = 1024;
63
64string do_strerror_r(int ev);
65
Dan Albert953d7d42016-06-15 20:20:32 +000066#if defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) \
67 && (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
Eric Fiselier9778a6d2016-06-14 03:45:31 +000068// GNU Extended version
69string do_strerror_r(int ev) {
70 char buffer[strerror_buff_size];
71 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
72 return string(ret);
73}
74#else
75// POSIX version
76string do_strerror_r(int ev) {
77 char buffer[strerror_buff_size];
78 const int old_errno = errno;
Eric Fiselier61df7902016-06-14 06:08:10 +000079 int ret;
80 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
Eric Fiselier79e05742016-06-14 06:03:20 +000081 // If `ret == -1` then the error is specified using `errno`, otherwise
82 // `ret` represents the error.
83 const int new_errno = ret == -1 ? errno : ret;
Eric Fiselier9778a6d2016-06-14 03:45:31 +000084 errno = old_errno;
85 if (new_errno == EINVAL) {
86 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
87 return string(buffer);
88 } else {
89 assert(new_errno == ERANGE);
90 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
91 // maximum error size so ERANGE shouldn't be returned.
92 std::abort();
93 }
94 }
95 return string(buffer);
96}
97#endif
98
99} // end namespace
Saleem Abdulrasoolc8bf9612016-12-31 21:24:04 +0000100#endif
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000101
Howard Hinnant3e519522010-05-11 19:42:16 +0000102string
103__do_message::message(int ev) const
104{
Eric Fiselier9778a6d2016-06-14 03:45:31 +0000105#if defined(_LIBCPP_HAS_NO_THREADS)
106 return string(::strerror(ev));
107#else
108 return do_strerror_r(ev);
109#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000110}
111
112class _LIBCPP_HIDDEN __generic_error_category
113 : public __do_message
114{
115public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000116 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000117 virtual string message(int ev) const;
118};
119
120const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000121__generic_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000122{
123 return "generic";
124}
125
126string
127__generic_error_category::message(int ev) const
128{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000129#ifdef _LIBCPP_ELAST
130 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000131 return string("unspecified generic_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000132#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000133 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000134}
135
136const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000137generic_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000138{
139 static __generic_error_category s;
140 return s;
141}
142
143class _LIBCPP_HIDDEN __system_error_category
144 : public __do_message
145{
146public:
Howard Hinnanta62f2892011-05-26 19:48:01 +0000147 virtual const char* name() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000148 virtual string message(int ev) const;
Howard Hinnanta62f2892011-05-26 19:48:01 +0000149 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +0000150};
151
152const char*
Howard Hinnanta62f2892011-05-26 19:48:01 +0000153__system_error_category::name() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000154{
155 return "system";
156}
157
158string
159__system_error_category::message(int ev) const
160{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000161#ifdef _LIBCPP_ELAST
162 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000163 return string("unspecified system_category error");
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000164#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000165 return __do_message::message(ev);
Howard Hinnant3e519522010-05-11 19:42:16 +0000166}
167
168error_condition
Howard Hinnanta62f2892011-05-26 19:48:01 +0000169__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000170{
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000171#ifdef _LIBCPP_ELAST
172 if (ev > _LIBCPP_ELAST)
Howard Hinnant128ba712010-05-24 17:49:41 +0000173 return error_condition(ev, system_category());
Jonathan Roelofsa409d592014-09-02 20:34:23 +0000174#endif // _LIBCPP_ELAST
Howard Hinnant128ba712010-05-24 17:49:41 +0000175 return error_condition(ev, generic_category());
Howard Hinnant3e519522010-05-11 19:42:16 +0000176}
177
178const error_category&
Howard Hinnanta62f2892011-05-26 19:48:01 +0000179system_category() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000180{
181 static __system_error_category s;
182 return s;
183}
184
185// error_condition
186
187string
188error_condition::message() const
189{
190 return __cat_->message(__val_);
191}
192
193// error_code
194
195string
196error_code::message() const
197{
198 return __cat_->message(__val_);
199}
200
201// system_error
202
203string
204system_error::__init(const error_code& ec, string what_arg)
205{
206 if (ec)
207 {
208 if (!what_arg.empty())
209 what_arg += ": ";
210 what_arg += ec.message();
211 }
Richard Trieu1c545ba2015-04-30 21:47:28 +0000212 return what_arg;
Howard Hinnant3e519522010-05-11 19:42:16 +0000213}
214
215system_error::system_error(error_code ec, const string& what_arg)
216 : runtime_error(__init(ec, what_arg)),
217 __ec_(ec)
218{
219}
220
221system_error::system_error(error_code ec, const char* what_arg)
222 : runtime_error(__init(ec, what_arg)),
223 __ec_(ec)
224{
225}
226
227system_error::system_error(error_code ec)
228 : runtime_error(__init(ec, "")),
229 __ec_(ec)
230{
231}
232
233system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
234 : runtime_error(__init(error_code(ev, ecat), what_arg)),
235 __ec_(error_code(ev, ecat))
236{
237}
238
239system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
240 : runtime_error(__init(error_code(ev, ecat), what_arg)),
241 __ec_(error_code(ev, ecat))
242{
243}
244
245system_error::system_error(int ev, const error_category& ecat)
246 : runtime_error(__init(error_code(ev, ecat), "")),
247 __ec_(error_code(ev, ecat))
248{
249}
250
Howard Hinnanta62f2892011-05-26 19:48:01 +0000251system_error::~system_error() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000252{
253}
254
255void
256__throw_system_error(int ev, const char* what_arg)
257{
Howard Hinnant54b409f2010-08-11 17:04:31 +0000258#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +0000259 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnante00e6f22013-03-28 18:56:26 +0000260#else
261 (void)ev;
262 (void)what_arg;
Marshall Clowd437fa52016-08-25 15:09:01 +0000263 _VSTD::abort();
Howard Hinnant54b409f2010-08-11 17:04:31 +0000264#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000265}
266
267_LIBCPP_END_NAMESPACE_STD