• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
error_category()33 error_category::error_category() _NOEXCEPT
34 {
35 }
36 #endif
37 
~error_category()38 error_category::~error_category() _NOEXCEPT
39 {
40 }
41 
42 error_condition
default_error_condition(int ev) const43 error_category::default_error_condition(int ev) const _NOEXCEPT
44 {
45     return error_condition(ev, *this);
46 }
47 
48 bool
equivalent(int code,const error_condition & condition) const49 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
50 {
51     return default_error_condition(code) == condition;
52 }
53 
54 bool
equivalent(const error_code & code,int condition) const55 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)
do_strerror_r(int ev)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
do_strerror_r(int ev)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
do_strerror_r(int ev)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
message(int ev) const113 __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*
name() const131 __generic_error_category::name() const _NOEXCEPT
132 {
133     return "generic";
134 }
135 
136 string
message(int ev) const137 __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&
generic_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*
name() const163 __system_error_category::name() const _NOEXCEPT
164 {
165     return "system";
166 }
167 
168 string
message(int ev) const169 __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
default_error_condition(int ev) const179 __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&
system_category()189 system_category() _NOEXCEPT
190 {
191     static __system_error_category s;
192     return s;
193 }
194 
195 // error_condition
196 
197 string
message() const198 error_condition::message() const
199 {
200     return __cat_->message(__val_);
201 }
202 
203 // error_code
204 
205 string
message() const206 error_code::message() const
207 {
208     return __cat_->message(__val_);
209 }
210 
211 // system_error
212 
213 string
__init(const error_code & ec,string what_arg)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 
system_error(error_code ec,const string & what_arg)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 
system_error(error_code ec,const char * what_arg)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 
system_error(error_code ec)237 system_error::system_error(error_code ec)
238     : runtime_error(__init(ec, "")),
239       __ec_(ec)
240 {
241 }
242 
system_error(int ev,const error_category & ecat,const string & what_arg)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 
system_error(int ev,const error_category & ecat,const char * what_arg)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 
system_error(int ev,const error_category & ecat)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 
~system_error()261 system_error::~system_error() _NOEXCEPT
262 {
263 }
264 
265 void
__throw_system_error(int ev,const char * what_arg)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