1 //===---------------------- system_error.cpp ------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
11 #include "system_error"
13 #include "include/config_elast.h"
22 #if defined(__ANDROID__)
23 #include <android/api-level.h>
26 _LIBCPP_BEGIN_NAMESPACE_STD
28 // class error_category
30 #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
31 error_category::error_category() _NOEXCEPT
36 error_category::~error_category() _NOEXCEPT
41 error_category::default_error_condition(int ev) const _NOEXCEPT
43 return error_condition(ev, *this);
47 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
49 return default_error_condition(code) == condition;
53 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
55 return *this == code.category() && code.value() == condition;
58 #if !defined(_LIBCPP_HAS_NO_THREADS)
61 // GLIBC also uses 1024 as the maximum buffer size internally.
62 constexpr size_t strerror_buff_size = 1024;
64 string do_strerror_r(int ev);
66 #if defined(_LIBCPP_MSVCRT_LIKE)
67 string do_strerror_r(int ev) {
68 char buffer[strerror_buff_size];
69 if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
70 return string(buffer);
71 std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
72 return string(buffer);
76 // Only one of the two following functions will be used, depending on
77 // the return type of strerror_r:
79 // For the GNU variant, a char* return value:
80 __attribute__((unused)) const char *
81 handle_strerror_r_return(char *strerror_return, char *buffer) {
82 // GNU always returns a string pointer in its return value. The
83 // string might point to either the input buffer, or a static
84 // buffer, but we don't care which.
85 return strerror_return;
88 // For the POSIX variant: an int return value.
89 __attribute__((unused)) const char *
90 handle_strerror_r_return(int strerror_return, char *buffer) {
91 // The POSIX variant either:
92 // - fills in the provided buffer and returns 0
93 // - returns a positive error value, or
94 // - returns -1 and fills in errno with an error value.
95 if (strerror_return == 0)
98 // Only handle EINVAL. Other errors abort.
99 int new_errno = strerror_return == -1 ? errno : strerror_return;
100 if (new_errno == EINVAL)
103 _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
104 // FIXME maybe? 'strerror_buff_size' is likely to exceed the
105 // maximum error size so ERANGE shouldn't be returned.
109 // This function handles both GNU and POSIX variants, dispatching to
110 // one of the two above functions.
111 string do_strerror_r(int ev) {
112 char buffer[strerror_buff_size];
113 // Preserve errno around the call. (The C++ standard requires that
114 // system_error functions not modify errno).
115 const int old_errno = errno;
116 const char *error_message = handle_strerror_r_return(
117 ::strerror_r(ev, buffer, strerror_buff_size), buffer);
118 // If we didn't get any message, print one now.
119 if (!error_message[0]) {
120 std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
121 error_message = buffer;
124 return string(error_message);
131 __do_message::message(int ev) const
133 #if defined(_LIBCPP_HAS_NO_THREADS)
134 return string(::strerror(ev));
136 return do_strerror_r(ev);
140 class _LIBCPP_HIDDEN __generic_error_category
141 : public __do_message
144 virtual const char* name() const _NOEXCEPT;
145 virtual string message(int ev) const;
149 __generic_error_category::name() const _NOEXCEPT
155 __generic_error_category::message(int ev) const
158 if (ev > _LIBCPP_ELAST)
159 return string("unspecified generic_category error");
160 #endif // _LIBCPP_ELAST
161 return __do_message::message(ev);
164 const error_category&
165 generic_category() _NOEXCEPT
167 static __generic_error_category s;
171 class _LIBCPP_HIDDEN __system_error_category
172 : public __do_message
175 virtual const char* name() const _NOEXCEPT;
176 virtual string message(int ev) const;
177 virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
181 __system_error_category::name() const _NOEXCEPT
187 __system_error_category::message(int ev) const
190 if (ev > _LIBCPP_ELAST)
191 return string("unspecified system_category error");
192 #endif // _LIBCPP_ELAST
193 return __do_message::message(ev);
197 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
200 if (ev > _LIBCPP_ELAST)
201 return error_condition(ev, system_category());
202 #endif // _LIBCPP_ELAST
203 return error_condition(ev, generic_category());
206 const error_category&
207 system_category() _NOEXCEPT
209 static __system_error_category s;
216 error_condition::message() const
218 return __cat_->message(__val_);
224 error_code::message() const
226 return __cat_->message(__val_);
232 system_error::__init(const error_code& ec, string what_arg)
236 if (!what_arg.empty())
238 what_arg += ec.message();
243 system_error::system_error(error_code ec, const string& what_arg)
244 : runtime_error(__init(ec, what_arg)),
249 system_error::system_error(error_code ec, const char* what_arg)
250 : runtime_error(__init(ec, what_arg)),
255 system_error::system_error(error_code ec)
256 : runtime_error(__init(ec, "")),
261 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
262 : runtime_error(__init(error_code(ev, ecat), what_arg)),
263 __ec_(error_code(ev, ecat))
267 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
268 : runtime_error(__init(error_code(ev, ecat), what_arg)),
269 __ec_(error_code(ev, ecat))
273 system_error::system_error(int ev, const error_category& ecat)
274 : runtime_error(__init(error_code(ev, ecat), "")),
275 __ec_(error_code(ev, ecat))
279 system_error::~system_error() _NOEXCEPT
284 __throw_system_error(int ev, const char* what_arg)
286 #ifndef _LIBCPP_NO_EXCEPTIONS
287 throw system_error(error_code(ev, system_category()), what_arg);
295 _LIBCPP_END_NAMESPACE_STD