1eb8650a7SLouis Dionne //===----------------------------------------------------------------------===//
23e519524SHoward Hinnant //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63e519524SHoward Hinnant //
73e519524SHoward Hinnant //===----------------------------------------------------------------------===//
83e519524SHoward Hinnant 
9bbb0f2c7SArthur O'Dwyer #include <__config>
10*0cc34ca7SLouis Dionne #ifdef _LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS
11*0cc34ca7SLouis Dionne #   define _LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS
12*0cc34ca7SLouis Dionne #endif
13*0cc34ca7SLouis Dionne 
14*0cc34ca7SLouis Dionne #include <__assert>
15bbb0f2c7SArthur O'Dwyer #include <cerrno>
16bbb0f2c7SArthur O'Dwyer #include <cstdio>
17bbb0f2c7SArthur O'Dwyer #include <cstdlib>
18bbb0f2c7SArthur O'Dwyer #include <cstring>
19bbb0f2c7SArthur O'Dwyer #include <string>
20bbb0f2c7SArthur O'Dwyer #include <string.h>
21bbb0f2c7SArthur O'Dwyer #include <system_error>
22a76dfbd4SDan Albert 
23e8fd1645SEric Fiselier #include "include/config_elast.h"
243e519524SHoward Hinnant 
25953d7d44SDan Albert #if defined(__ANDROID__)
26953d7d44SDan Albert #include <android/api-level.h>
27953d7d44SDan Albert #endif
28953d7d44SDan Albert 
293e519524SHoward Hinnant _LIBCPP_BEGIN_NAMESPACE_STD
303e519524SHoward Hinnant 
313e519524SHoward Hinnant // class error_category
323e519524SHoward Hinnant 
33*0cc34ca7SLouis Dionne #if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
error_category()345601305fSLouis Dionne error_category::error_category() noexcept
353e519524SHoward Hinnant {
363e519524SHoward Hinnant }
379aca97d6SEric Fiselier #endif
383e519524SHoward Hinnant 
~error_category()395601305fSLouis Dionne error_category::~error_category() noexcept
403e519524SHoward Hinnant {
413e519524SHoward Hinnant }
423e519524SHoward Hinnant 
433e519524SHoward Hinnant error_condition
default_error_condition(int ev) const445601305fSLouis Dionne error_category::default_error_condition(int ev) const noexcept
453e519524SHoward Hinnant {
463e519524SHoward Hinnant     return error_condition(ev, *this);
473e519524SHoward Hinnant }
483e519524SHoward Hinnant 
493e519524SHoward Hinnant bool
equivalent(int code,const error_condition & condition) const505601305fSLouis Dionne error_category::equivalent(int code, const error_condition& condition) const noexcept
513e519524SHoward Hinnant {
523e519524SHoward Hinnant     return default_error_condition(code) == condition;
533e519524SHoward Hinnant }
543e519524SHoward Hinnant 
553e519524SHoward Hinnant bool
equivalent(const error_code & code,int condition) const565601305fSLouis Dionne error_category::equivalent(const error_code& code, int condition) const noexcept
573e519524SHoward Hinnant {
583e519524SHoward Hinnant     return *this == code.category() && code.value() == condition;
593e519524SHoward Hinnant }
603e519524SHoward Hinnant 
61c8bf9618SSaleem Abdulrasool #if !defined(_LIBCPP_HAS_NO_THREADS)
629778a6d8SEric Fiselier namespace {
639778a6d8SEric Fiselier 
649778a6d8SEric Fiselier //  GLIBC also uses 1024 as the maximum buffer size internally.
659778a6d8SEric Fiselier constexpr size_t strerror_buff_size = 1024;
669778a6d8SEric Fiselier 
679778a6d8SEric Fiselier string do_strerror_r(int ev);
689778a6d8SEric Fiselier 
691ec02625SEric Fiselier #if defined(_LIBCPP_MSVCRT_LIKE)
do_strerror_r(int ev)70edd09b3dSSaleem Abdulrasool string do_strerror_r(int ev) {
71edd09b3dSSaleem Abdulrasool   char buffer[strerror_buff_size];
72edd09b3dSSaleem Abdulrasool   if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
73edd09b3dSSaleem Abdulrasool     return string(buffer);
74edd09b3dSSaleem Abdulrasool   std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
75edd09b3dSSaleem Abdulrasool   return string(buffer);
76edd09b3dSSaleem Abdulrasool }
779778a6d8SEric Fiselier #else
78929f1597SJames Y Knight 
79929f1597SJames Y Knight // Only one of the two following functions will be used, depending on
80929f1597SJames Y Knight // the return type of strerror_r:
81929f1597SJames Y Knight 
82929f1597SJames Y Knight // For the GNU variant, a char* return value:
83929f1597SJames Y Knight __attribute__((unused)) const char *
handle_strerror_r_return(char * strerror_return,char * buffer)84929f1597SJames Y Knight handle_strerror_r_return(char *strerror_return, char *buffer) {
85929f1597SJames Y Knight   // GNU always returns a string pointer in its return value. The
86929f1597SJames Y Knight   // string might point to either the input buffer, or a static
87929f1597SJames Y Knight   // buffer, but we don't care which.
88929f1597SJames Y Knight   return strerror_return;
89929f1597SJames Y Knight }
90929f1597SJames Y Knight 
91929f1597SJames Y Knight // For the POSIX variant: an int return value.
92929f1597SJames Y Knight __attribute__((unused)) const char *
handle_strerror_r_return(int strerror_return,char * buffer)93929f1597SJames Y Knight handle_strerror_r_return(int strerror_return, char *buffer) {
94929f1597SJames Y Knight   // The POSIX variant either:
95929f1597SJames Y Knight   // - fills in the provided buffer and returns 0
96929f1597SJames Y Knight   // - returns a positive error value, or
97929f1597SJames Y Knight   // - returns -1 and fills in errno with an error value.
98929f1597SJames Y Knight   if (strerror_return == 0)
99929f1597SJames Y Knight     return buffer;
100929f1597SJames Y Knight 
101929f1597SJames Y Knight   // Only handle EINVAL. Other errors abort.
102929f1597SJames Y Knight   int new_errno = strerror_return == -1 ? errno : strerror_return;
103929f1597SJames Y Knight   if (new_errno == EINVAL)
104929f1597SJames Y Knight     return "";
105929f1597SJames Y Knight 
106929f1597SJames Y Knight   _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
1079778a6d8SEric Fiselier   // FIXME maybe? 'strerror_buff_size' is likely to exceed the
1089778a6d8SEric Fiselier   // maximum error size so ERANGE shouldn't be returned.
1099778a6d8SEric Fiselier   std::abort();
1109778a6d8SEric Fiselier }
111929f1597SJames Y Knight 
112929f1597SJames Y Knight // This function handles both GNU and POSIX variants, dispatching to
113929f1597SJames Y Knight // one of the two above functions.
do_strerror_r(int ev)114929f1597SJames Y Knight string do_strerror_r(int ev) {
115929f1597SJames Y Knight     char buffer[strerror_buff_size];
116929f1597SJames Y Knight     // Preserve errno around the call. (The C++ standard requires that
117929f1597SJames Y Knight     // system_error functions not modify errno).
118929f1597SJames Y Knight     const int old_errno = errno;
119929f1597SJames Y Knight     const char *error_message = handle_strerror_r_return(
120929f1597SJames Y Knight         ::strerror_r(ev, buffer, strerror_buff_size), buffer);
121929f1597SJames Y Knight     // If we didn't get any message, print one now.
122929f1597SJames Y Knight     if (!error_message[0]) {
123929f1597SJames Y Knight       std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
124929f1597SJames Y Knight       error_message = buffer;
1259778a6d8SEric Fiselier     }
126929f1597SJames Y Knight     errno = old_errno;
127929f1597SJames Y Knight     return string(error_message);
1289778a6d8SEric Fiselier }
1299778a6d8SEric Fiselier #endif
1309778a6d8SEric Fiselier } // end namespace
131c8bf9618SSaleem Abdulrasool #endif
1329778a6d8SEric Fiselier 
1333e519524SHoward Hinnant string
message(int ev) const1343e519524SHoward Hinnant __do_message::message(int ev) const
1353e519524SHoward Hinnant {
1369778a6d8SEric Fiselier #if defined(_LIBCPP_HAS_NO_THREADS)
1379778a6d8SEric Fiselier     return string(::strerror(ev));
1389778a6d8SEric Fiselier #else
1399778a6d8SEric Fiselier     return do_strerror_r(ev);
1409778a6d8SEric Fiselier #endif
1413e519524SHoward Hinnant }
1423e519524SHoward Hinnant 
1433e519524SHoward Hinnant class _LIBCPP_HIDDEN __generic_error_category
1443e519524SHoward Hinnant     : public __do_message
1453e519524SHoward Hinnant {
1463e519524SHoward Hinnant public:
1475601305fSLouis Dionne     virtual const char* name() const noexcept;
1483e519524SHoward Hinnant     virtual string message(int ev) const;
1493e519524SHoward Hinnant };
1503e519524SHoward Hinnant 
1513e519524SHoward Hinnant const char*
name() const1525601305fSLouis Dionne __generic_error_category::name() const noexcept
1533e519524SHoward Hinnant {
1543e519524SHoward Hinnant     return "generic";
1553e519524SHoward Hinnant }
1563e519524SHoward Hinnant 
1573e519524SHoward Hinnant string
message(int ev) const1583e519524SHoward Hinnant __generic_error_category::message(int ev) const
1593e519524SHoward Hinnant {
160a409d59cSJonathan Roelofs #ifdef _LIBCPP_ELAST
161a409d59cSJonathan Roelofs     if (ev > _LIBCPP_ELAST)
1623e519524SHoward Hinnant       return string("unspecified generic_category error");
163a409d59cSJonathan Roelofs #endif // _LIBCPP_ELAST
164128ba719SHoward Hinnant     return __do_message::message(ev);
1653e519524SHoward Hinnant }
1663e519524SHoward Hinnant 
1673e519524SHoward Hinnant const error_category&
generic_category()1685601305fSLouis Dionne generic_category() noexcept
1693e519524SHoward Hinnant {
1703e519524SHoward Hinnant     static __generic_error_category s;
1713e519524SHoward Hinnant     return s;
1723e519524SHoward Hinnant }
1733e519524SHoward Hinnant 
1743e519524SHoward Hinnant class _LIBCPP_HIDDEN __system_error_category
1753e519524SHoward Hinnant     : public __do_message
1763e519524SHoward Hinnant {
1773e519524SHoward Hinnant public:
1785601305fSLouis Dionne     virtual const char* name() const noexcept;
1793e519524SHoward Hinnant     virtual string message(int ev) const;
1805601305fSLouis Dionne     virtual error_condition default_error_condition(int ev) const noexcept;
1813e519524SHoward Hinnant };
1823e519524SHoward Hinnant 
1833e519524SHoward Hinnant const char*
name() const1845601305fSLouis Dionne __system_error_category::name() const noexcept
1853e519524SHoward Hinnant {
1863e519524SHoward Hinnant     return "system";
1873e519524SHoward Hinnant }
1883e519524SHoward Hinnant 
1893e519524SHoward Hinnant string
message(int ev) const1903e519524SHoward Hinnant __system_error_category::message(int ev) const
1913e519524SHoward Hinnant {
192a409d59cSJonathan Roelofs #ifdef _LIBCPP_ELAST
193a409d59cSJonathan Roelofs     if (ev > _LIBCPP_ELAST)
1943e519524SHoward Hinnant       return string("unspecified system_category error");
195a409d59cSJonathan Roelofs #endif // _LIBCPP_ELAST
196128ba719SHoward Hinnant     return __do_message::message(ev);
1973e519524SHoward Hinnant }
1983e519524SHoward Hinnant 
1993e519524SHoward Hinnant error_condition
default_error_condition(int ev) const2005601305fSLouis Dionne __system_error_category::default_error_condition(int ev) const noexcept
2013e519524SHoward Hinnant {
202a409d59cSJonathan Roelofs #ifdef _LIBCPP_ELAST
203a409d59cSJonathan Roelofs     if (ev > _LIBCPP_ELAST)
2043e519524SHoward Hinnant       return error_condition(ev, system_category());
205a409d59cSJonathan Roelofs #endif // _LIBCPP_ELAST
206128ba719SHoward Hinnant     return error_condition(ev, generic_category());
2073e519524SHoward Hinnant }
2083e519524SHoward Hinnant 
2093e519524SHoward Hinnant const error_category&
system_category()2105601305fSLouis Dionne system_category() noexcept
2113e519524SHoward Hinnant {
2123e519524SHoward Hinnant     static __system_error_category s;
2133e519524SHoward Hinnant     return s;
2143e519524SHoward Hinnant }
2153e519524SHoward Hinnant 
2163e519524SHoward Hinnant // error_condition
2173e519524SHoward Hinnant 
2183e519524SHoward Hinnant string
message() const2193e519524SHoward Hinnant error_condition::message() const
2203e519524SHoward Hinnant {
2213e519524SHoward Hinnant     return __cat_->message(__val_);
2223e519524SHoward Hinnant }
2233e519524SHoward Hinnant 
2243e519524SHoward Hinnant // error_code
2253e519524SHoward Hinnant 
2263e519524SHoward Hinnant string
message() const2273e519524SHoward Hinnant error_code::message() const
2283e519524SHoward Hinnant {
2293e519524SHoward Hinnant     return __cat_->message(__val_);
2303e519524SHoward Hinnant }
2313e519524SHoward Hinnant 
2323e519524SHoward Hinnant // system_error
2333e519524SHoward Hinnant 
2343e519524SHoward Hinnant string
__init(const error_code & ec,string what_arg)2353e519524SHoward Hinnant system_error::__init(const error_code& ec, string what_arg)
2363e519524SHoward Hinnant {
2373e519524SHoward Hinnant     if (ec)
2383e519524SHoward Hinnant     {
2393e519524SHoward Hinnant         if (!what_arg.empty())
2403e519524SHoward Hinnant             what_arg += ": ";
2413e519524SHoward Hinnant         what_arg += ec.message();
2423e519524SHoward Hinnant     }
2431c545bafSRichard Trieu     return what_arg;
2443e519524SHoward Hinnant }
2453e519524SHoward Hinnant 
system_error(error_code ec,const string & what_arg)2463e519524SHoward Hinnant system_error::system_error(error_code ec, const string& what_arg)
2473e519524SHoward Hinnant     : runtime_error(__init(ec, what_arg)),
2483e519524SHoward Hinnant       __ec_(ec)
2493e519524SHoward Hinnant {
2503e519524SHoward Hinnant }
2513e519524SHoward Hinnant 
system_error(error_code ec,const char * what_arg)2523e519524SHoward Hinnant system_error::system_error(error_code ec, const char* what_arg)
2533e519524SHoward Hinnant     : runtime_error(__init(ec, what_arg)),
2543e519524SHoward Hinnant       __ec_(ec)
2553e519524SHoward Hinnant {
2563e519524SHoward Hinnant }
2573e519524SHoward Hinnant 
system_error(error_code ec)2583e519524SHoward Hinnant system_error::system_error(error_code ec)
2593e519524SHoward Hinnant     : runtime_error(__init(ec, "")),
2603e519524SHoward Hinnant       __ec_(ec)
2613e519524SHoward Hinnant {
2623e519524SHoward Hinnant }
2633e519524SHoward Hinnant 
system_error(int ev,const error_category & ecat,const string & what_arg)2643e519524SHoward Hinnant system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
2653e519524SHoward Hinnant     : runtime_error(__init(error_code(ev, ecat), what_arg)),
2663e519524SHoward Hinnant       __ec_(error_code(ev, ecat))
2673e519524SHoward Hinnant {
2683e519524SHoward Hinnant }
2693e519524SHoward Hinnant 
system_error(int ev,const error_category & ecat,const char * what_arg)2703e519524SHoward Hinnant system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
2713e519524SHoward Hinnant     : runtime_error(__init(error_code(ev, ecat), what_arg)),
2723e519524SHoward Hinnant       __ec_(error_code(ev, ecat))
2733e519524SHoward Hinnant {
2743e519524SHoward Hinnant }
2753e519524SHoward Hinnant 
system_error(int ev,const error_category & ecat)2763e519524SHoward Hinnant system_error::system_error(int ev, const error_category& ecat)
2773e519524SHoward Hinnant     : runtime_error(__init(error_code(ev, ecat), "")),
2783e519524SHoward Hinnant       __ec_(error_code(ev, ecat))
2793e519524SHoward Hinnant {
2803e519524SHoward Hinnant }
2813e519524SHoward Hinnant 
~system_error()2825601305fSLouis Dionne system_error::~system_error() noexcept
2833e519524SHoward Hinnant {
2843e519524SHoward Hinnant }
2853e519524SHoward Hinnant 
2863e519524SHoward Hinnant void
__throw_system_error(int ev,const char * what_arg)2873e519524SHoward Hinnant __throw_system_error(int ev, const char* what_arg)
2883e519524SHoward Hinnant {
28954b409fdSHoward Hinnant #ifndef _LIBCPP_NO_EXCEPTIONS
2903e519524SHoward Hinnant     throw system_error(error_code(ev, system_category()), what_arg);
291e00e6f23SHoward Hinnant #else
292e00e6f23SHoward Hinnant     (void)ev;
293e00e6f23SHoward Hinnant     (void)what_arg;
294d437fa5cSMarshall Clow     _VSTD::abort();
29554b409fdSHoward Hinnant #endif
2963e519524SHoward Hinnant }
2973e519524SHoward Hinnant 
2983e519524SHoward Hinnant _LIBCPP_END_NAMESPACE_STD
299