blob: cbbbb5dcd15c4c1e9fac30a7197588a3d7ebba3c [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===---------------------- system_error.cpp ------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-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 Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
Jonathan Roelofsb9420932014-09-02 20:34:23 +000010#include "__config"
Dan Albert656850f2015-01-06 17:34:51 +000011
12#define _LIBCPP_BUILDING_SYSTEM_ERROR
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000013#include "system_error"
Dan Albert656850f2015-01-06 17:34:51 +000014
Eric Fiselier3b1fb532015-08-18 21:08:54 +000015#include "include/config_elast.h"
Eric Fiseliera30cee22016-06-14 03:45:31 +000016#include "cerrno"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000017#include "cstring"
Eric Fiseliera30cee22016-06-14 03:45:31 +000018#include "cstdio"
19#include "cstdlib"
Dan Albert656850f2015-01-06 17:34:51 +000020#include "string"
Eric Fiseliera30cee22016-06-14 03:45:31 +000021#include "string.h"
Eric Fiselier2c90d1f2017-01-24 04:57:33 +000022#include "__debug"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023
Dan Albertb2ce77f2016-06-15 20:20:32 +000024#if defined(__ANDROID__)
25#include <android/api-level.h>
26#endif
27
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000028_LIBCPP_BEGIN_NAMESPACE_STD
29
30// class error_category
31
Eric Fiseliera7ae3032017-01-17 03:16:26 +000032#if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
Howard Hinnant1e15fd12011-05-26 19:48:01 +000033error_category::error_category() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000034{
35}
Eric Fiselier4b07f982017-01-02 22:17:51 +000036#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000037
Howard Hinnant1e15fd12011-05-26 19:48:01 +000038error_category::~error_category() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039{
40}
41
42error_condition
Howard Hinnant1e15fd12011-05-26 19:48:01 +000043error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000044{
45 return error_condition(ev, *this);
46}
47
48bool
Howard Hinnant1e15fd12011-05-26 19:48:01 +000049error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000050{
51 return default_error_condition(code) == condition;
52}
53
54bool
Howard Hinnant1e15fd12011-05-26 19:48:01 +000055error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000056{
57 return *this == code.category() && code.value() == condition;
58}
59
Saleem Abdulrasoolf7e84952016-12-31 21:24:04 +000060#if !defined(_LIBCPP_HAS_NO_THREADS)
Eric Fiseliera30cee22016-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
Saleem Abdulrasoole34f9d52017-01-03 21:53:51 +000068#if defined(_LIBCPP_MSVCRT)
Saleem Abdulrasoolba161f42017-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}
76#elif defined(__linux__) && !defined(_LIBCPP_HAS_MUSL_LIBC) && \
77 (!defined(__ANDROID__) || __ANDROID_API__ >= 23)
Eric Fiseliera30cee22016-06-14 03:45:31 +000078// GNU Extended version
79string do_strerror_r(int ev) {
80 char buffer[strerror_buff_size];
81 char* ret = ::strerror_r(ev, buffer, strerror_buff_size);
82 return string(ret);
83}
84#else
85// POSIX version
86string do_strerror_r(int ev) {
87 char buffer[strerror_buff_size];
88 const int old_errno = errno;
Eric Fiselierd3f11342016-06-14 06:08:10 +000089 int ret;
90 if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
Eric Fiselier17402e32016-06-14 06:03:20 +000091 // If `ret == -1` then the error is specified using `errno`, otherwise
92 // `ret` represents the error.
93 const int new_errno = ret == -1 ? errno : ret;
Eric Fiseliera30cee22016-06-14 03:45:31 +000094 errno = old_errno;
95 if (new_errno == EINVAL) {
96 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
97 return string(buffer);
98 } else {
Eric Fiselier2c90d1f2017-01-24 04:57:33 +000099 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerr_r");
Eric Fiseliera30cee22016-06-14 03:45:31 +0000100 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
101 // maximum error size so ERANGE shouldn't be returned.
102 std::abort();
103 }
104 }
105 return string(buffer);
106}
107#endif
108
109} // end namespace
Saleem Abdulrasoolf7e84952016-12-31 21:24:04 +0000110#endif
Eric Fiseliera30cee22016-06-14 03:45:31 +0000111
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000112string
113__do_message::message(int ev) const
114{
Eric Fiseliera30cee22016-06-14 03:45:31 +0000115#if defined(_LIBCPP_HAS_NO_THREADS)
116 return string(::strerror(ev));
117#else
118 return do_strerror_r(ev);
119#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120}
121
122class _LIBCPP_HIDDEN __generic_error_category
123 : public __do_message
124{
125public:
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000126 virtual const char* name() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000127 virtual string message(int ev) const;
128};
129
130const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000131__generic_error_category::name() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000132{
133 return "generic";
134}
135
136string
137__generic_error_category::message(int ev) const
138{
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000139#ifdef _LIBCPP_ELAST
140 if (ev > _LIBCPP_ELAST)
Howard Hinnantadff4892010-05-24 17:49:41 +0000141 return string("unspecified generic_category error");
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000142#endif // _LIBCPP_ELAST
Howard Hinnantadff4892010-05-24 17:49:41 +0000143 return __do_message::message(ev);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000144}
145
146const error_category&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000147generic_category() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000148{
149 static __generic_error_category s;
150 return s;
151}
152
153class _LIBCPP_HIDDEN __system_error_category
154 : public __do_message
155{
156public:
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000157 virtual const char* name() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000158 virtual string message(int ev) const;
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000159 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000160};
161
162const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000163__system_error_category::name() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000164{
165 return "system";
166}
167
168string
169__system_error_category::message(int ev) const
170{
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000171#ifdef _LIBCPP_ELAST
172 if (ev > _LIBCPP_ELAST)
Howard Hinnantadff4892010-05-24 17:49:41 +0000173 return string("unspecified system_category error");
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000174#endif // _LIBCPP_ELAST
Howard Hinnantadff4892010-05-24 17:49:41 +0000175 return __do_message::message(ev);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000176}
177
178error_condition
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000179__system_error_category::default_error_condition(int ev) const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000180{
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000181#ifdef _LIBCPP_ELAST
182 if (ev > _LIBCPP_ELAST)
Howard Hinnantadff4892010-05-24 17:49:41 +0000183 return error_condition(ev, system_category());
Jonathan Roelofsb9420932014-09-02 20:34:23 +0000184#endif // _LIBCPP_ELAST
Howard Hinnantadff4892010-05-24 17:49:41 +0000185 return error_condition(ev, generic_category());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186}
187
188const error_category&
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000189system_category() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190{
191 static __system_error_category s;
192 return s;
193}
194
195// error_condition
196
197string
198error_condition::message() const
199{
200 return __cat_->message(__val_);
201}
202
203// error_code
204
205string
206error_code::message() const
207{
208 return __cat_->message(__val_);
209}
210
211// system_error
212
213string
214system_error::__init(const error_code& ec, string what_arg)
215{
216 if (ec)
217 {
218 if (!what_arg.empty())
219 what_arg += ": ";
220 what_arg += ec.message();
221 }
Richard Trieu14dbb252015-04-30 21:47:28 +0000222 return what_arg;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000223}
224
225system_error::system_error(error_code ec, const string& what_arg)
226 : runtime_error(__init(ec, what_arg)),
227 __ec_(ec)
228{
229}
230
231system_error::system_error(error_code ec, const char* what_arg)
232 : runtime_error(__init(ec, what_arg)),
233 __ec_(ec)
234{
235}
236
237system_error::system_error(error_code ec)
238 : runtime_error(__init(ec, "")),
239 __ec_(ec)
240{
241}
242
243system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
244 : runtime_error(__init(error_code(ev, ecat), what_arg)),
245 __ec_(error_code(ev, ecat))
246{
247}
248
249system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
250 : runtime_error(__init(error_code(ev, ecat), what_arg)),
251 __ec_(error_code(ev, ecat))
252{
253}
254
255system_error::system_error(int ev, const error_category& ecat)
256 : runtime_error(__init(error_code(ev, ecat), "")),
257 __ec_(error_code(ev, ecat))
258{
259}
260
Howard Hinnant1e15fd12011-05-26 19:48:01 +0000261system_error::~system_error() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000262{
263}
264
265void
266__throw_system_error(int ev, const char* what_arg)
267{
Howard Hinnantd4444702010-08-11 17:04:31 +0000268#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000269 throw system_error(error_code(ev, system_category()), what_arg);
Howard Hinnantdb4d4782013-03-28 18:56:26 +0000270#else
271 (void)ev;
272 (void)what_arg;
Marshall Clow14c09a22016-08-25 15:09:01 +0000273 _VSTD::abort();
Howard Hinnantd4444702010-08-11 17:04:31 +0000274#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000275}
276
277_LIBCPP_END_NAMESPACE_STD