Home | History | Annotate | Download | only in src
      1 //===---------------------- system_error.cpp ------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "__config"
     11 
     12 #define _LIBCPP_BUILDING_SYSTEM_ERROR
     13 #include "system_error"
     14 
     15 #include "include/config_elast.h"
     16 #include "cerrno"
     17 #include "cstring"
     18 #include "cstdio"
     19 #include "cstdlib"
     20 #include "string"
     21 #include "string.h"
     22 #include "__debug"
     23 
     24 #if defined(__ANDROID__)
     25 #include <android/api-level.h>
     26 #endif
     27 
     28 _LIBCPP_BEGIN_NAMESPACE_STD
     29 
     30 // class error_category
     31 
     32 #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
     33 error_category::error_category() _NOEXCEPT
     34 {
     35 }
     36 #endif
     37 
     38 error_category::~error_category() _NOEXCEPT
     39 {
     40 }
     41 
     42 error_condition
     43 error_category::default_error_condition(int ev) const _NOEXCEPT
     44 {
     45     return error_condition(ev, *this);
     46 }
     47 
     48 bool
     49 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
     50 {
     51     return default_error_condition(code) == condition;
     52 }
     53 
     54 bool
     55 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
     56 {
     57     return *this == code.category() && code.value() == condition;
     58 }
     59 
     60 #if !defined(_LIBCPP_HAS_NO_THREADS)
     61 namespace {
     62 
     63 //  GLIBC also uses 1024 as the maximum buffer size internally.
     64 constexpr size_t strerror_buff_size = 1024;
     65 
     66 string do_strerror_r(int ev);
     67 
     68 #if defined(_LIBCPP_MSVCRT)
     69 string 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)
     78 // GNU Extended version
     79 string 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
     86 string do_strerror_r(int ev) {
     87     char buffer[strerror_buff_size];
     88     const int old_errno = errno;
     89     int ret;
     90     if ((ret = ::strerror_r(ev, buffer, strerror_buff_size)) != 0) {
     91         // 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;
     94         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 {
     99             _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerr_r");
    100             // 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
    110 #endif
    111 
    112 string
    113 __do_message::message(int ev) const
    114 {
    115 #if defined(_LIBCPP_HAS_NO_THREADS)
    116     return string(::strerror(ev));
    117 #else
    118     return do_strerror_r(ev);
    119 #endif
    120 }
    121 
    122 class _LIBCPP_HIDDEN __generic_error_category
    123     : public __do_message
    124 {
    125 public:
    126     virtual const char* name() const _NOEXCEPT;
    127     virtual string message(int ev) const;
    128 };
    129 
    130 const char*
    131 __generic_error_category::name() const _NOEXCEPT
    132 {
    133     return "generic";
    134 }
    135 
    136 string
    137 __generic_error_category::message(int ev) const
    138 {
    139 #ifdef _LIBCPP_ELAST
    140     if (ev > _LIBCPP_ELAST)
    141       return string("unspecified generic_category error");
    142 #endif  // _LIBCPP_ELAST
    143     return __do_message::message(ev);
    144 }
    145 
    146 const error_category&
    147 generic_category() _NOEXCEPT
    148 {
    149     static __generic_error_category s;
    150     return s;
    151 }
    152 
    153 class _LIBCPP_HIDDEN __system_error_category
    154     : public __do_message
    155 {
    156 public:
    157     virtual const char* name() const _NOEXCEPT;
    158     virtual string message(int ev) const;
    159     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
    160 };
    161 
    162 const char*
    163 __system_error_category::name() const _NOEXCEPT
    164 {
    165     return "system";
    166 }
    167 
    168 string
    169 __system_error_category::message(int ev) const
    170 {
    171 #ifdef _LIBCPP_ELAST
    172     if (ev > _LIBCPP_ELAST)
    173       return string("unspecified system_category error");
    174 #endif  // _LIBCPP_ELAST
    175     return __do_message::message(ev);
    176 }
    177 
    178 error_condition
    179 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
    180 {
    181 #ifdef _LIBCPP_ELAST
    182     if (ev > _LIBCPP_ELAST)
    183       return error_condition(ev, system_category());
    184 #endif  // _LIBCPP_ELAST
    185     return error_condition(ev, generic_category());
    186 }
    187 
    188 const error_category&
    189 system_category() _NOEXCEPT
    190 {
    191     static __system_error_category s;
    192     return s;
    193 }
    194 
    195 // error_condition
    196 
    197 string
    198 error_condition::message() const
    199 {
    200     return __cat_->message(__val_);
    201 }
    202 
    203 // error_code
    204 
    205 string
    206 error_code::message() const
    207 {
    208     return __cat_->message(__val_);
    209 }
    210 
    211 // system_error
    212 
    213 string
    214 system_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     }
    222     return what_arg;
    223 }
    224 
    225 system_error::system_error(error_code ec, const string& what_arg)
    226     : runtime_error(__init(ec, what_arg)),
    227       __ec_(ec)
    228 {
    229 }
    230 
    231 system_error::system_error(error_code ec, const char* what_arg)
    232     : runtime_error(__init(ec, what_arg)),
    233       __ec_(ec)
    234 {
    235 }
    236 
    237 system_error::system_error(error_code ec)
    238     : runtime_error(__init(ec, "")),
    239       __ec_(ec)
    240 {
    241 }
    242 
    243 system_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 
    249 system_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 
    255 system_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 
    261 system_error::~system_error() _NOEXCEPT
    262 {
    263 }
    264 
    265 void
    266 __throw_system_error(int ev, const char* what_arg)
    267 {
    268 #ifndef _LIBCPP_NO_EXCEPTIONS
    269     throw system_error(error_code(ev, system_category()), what_arg);
    270 #else
    271     (void)ev;
    272     (void)what_arg;
    273     _VSTD::abort();
    274 #endif
    275 }
    276 
    277 _LIBCPP_END_NAMESPACE_STD
    278