• 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 #include "system_error"
13 
14 #include "include/config_elast.h"
15 #include "cerrno"
16 #include "cstring"
17 #include "cstdio"
18 #include "cstdlib"
19 #include "string"
20 #include "string.h"
21 #include "__debug"
22 
23 #if defined(__ANDROID__)
24 #include <android/api-level.h>
25 #endif
26 
27 _LIBCPP_BEGIN_NAMESPACE_STD
28 
29 // class error_category
30 
31 #if defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
error_category()32 error_category::error_category() _NOEXCEPT
33 {
34 }
35 #endif
36 
~error_category()37 error_category::~error_category() _NOEXCEPT
38 {
39 }
40 
41 error_condition
default_error_condition(int ev) const42 error_category::default_error_condition(int ev) const _NOEXCEPT
43 {
44     return error_condition(ev, *this);
45 }
46 
47 bool
equivalent(int code,const error_condition & condition) const48 error_category::equivalent(int code, const error_condition& condition) const _NOEXCEPT
49 {
50     return default_error_condition(code) == condition;
51 }
52 
53 bool
equivalent(const error_code & code,int condition) const54 error_category::equivalent(const error_code& code, int condition) const _NOEXCEPT
55 {
56     return *this == code.category() && code.value() == condition;
57 }
58 
59 #if !defined(_LIBCPP_HAS_NO_THREADS)
60 namespace {
61 
62 //  GLIBC also uses 1024 as the maximum buffer size internally.
63 constexpr size_t strerror_buff_size = 1024;
64 
65 string do_strerror_r(int ev);
66 
67 #if defined(_LIBCPP_MSVCRT_LIKE)
do_strerror_r(int ev)68 string do_strerror_r(int ev) {
69   char buffer[strerror_buff_size];
70   if (::strerror_s(buffer, strerror_buff_size, ev) == 0)
71     return string(buffer);
72   std::snprintf(buffer, strerror_buff_size, "unknown error %d", ev);
73   return string(buffer);
74 }
75 #else
76 
77 // Only one of the two following functions will be used, depending on
78 // the return type of strerror_r:
79 
80 // For the GNU variant, a char* return value:
81 __attribute__((unused)) const char *
handle_strerror_r_return(char * strerror_return,char * buffer)82 handle_strerror_r_return(char *strerror_return, char *buffer) {
83   // GNU always returns a string pointer in its return value. The
84   // string might point to either the input buffer, or a static
85   // buffer, but we don't care which.
86   return strerror_return;
87 }
88 
89 // For the POSIX variant: an int return value.
90 __attribute__((unused)) const char *
handle_strerror_r_return(int strerror_return,char * buffer)91 handle_strerror_r_return(int strerror_return, char *buffer) {
92   // The POSIX variant either:
93   // - fills in the provided buffer and returns 0
94   // - returns a positive error value, or
95   // - returns -1 and fills in errno with an error value.
96   if (strerror_return == 0)
97     return buffer;
98 
99   // Only handle EINVAL. Other errors abort.
100   int new_errno = strerror_return == -1 ? errno : strerror_return;
101   if (new_errno == EINVAL)
102     return "";
103 
104   _LIBCPP_ASSERT(new_errno == ERANGE, "unexpected error from ::strerror_r");
105   // FIXME maybe? 'strerror_buff_size' is likely to exceed the
106   // maximum error size so ERANGE shouldn't be returned.
107   std::abort();
108 }
109 
110 // This function handles both GNU and POSIX variants, dispatching to
111 // one of the two above functions.
do_strerror_r(int ev)112 string do_strerror_r(int ev) {
113     char buffer[strerror_buff_size];
114     // Preserve errno around the call. (The C++ standard requires that
115     // system_error functions not modify errno).
116     const int old_errno = errno;
117     const char *error_message = handle_strerror_r_return(
118         ::strerror_r(ev, buffer, strerror_buff_size), buffer);
119     // If we didn't get any message, print one now.
120     if (!error_message[0]) {
121       std::snprintf(buffer, strerror_buff_size, "Unknown error %d", ev);
122       error_message = buffer;
123     }
124     errno = old_errno;
125     return string(error_message);
126 }
127 #endif
128 } // end namespace
129 #endif
130 
131 string
message(int ev) const132 __do_message::message(int ev) const
133 {
134 #if defined(_LIBCPP_HAS_NO_THREADS)
135     return string(::strerror(ev));
136 #else
137     return do_strerror_r(ev);
138 #endif
139 }
140 
141 class _LIBCPP_HIDDEN __generic_error_category
142     : public __do_message
143 {
144 public:
145     virtual const char* name() const _NOEXCEPT;
146     virtual string message(int ev) const;
147 };
148 
149 const char*
name() const150 __generic_error_category::name() const _NOEXCEPT
151 {
152     return "generic";
153 }
154 
155 string
message(int ev) const156 __generic_error_category::message(int ev) const
157 {
158 #ifdef _LIBCPP_ELAST
159     if (ev > _LIBCPP_ELAST)
160       return string("unspecified generic_category error");
161 #endif  // _LIBCPP_ELAST
162     return __do_message::message(ev);
163 }
164 
165 const error_category&
generic_category()166 generic_category() _NOEXCEPT
167 {
168     static __generic_error_category s;
169     return s;
170 }
171 
172 class _LIBCPP_HIDDEN __system_error_category
173     : public __do_message
174 {
175 public:
176     virtual const char* name() const _NOEXCEPT;
177     virtual string message(int ev) const;
178     virtual error_condition default_error_condition(int ev) const _NOEXCEPT;
179 };
180 
181 const char*
name() const182 __system_error_category::name() const _NOEXCEPT
183 {
184     return "system";
185 }
186 
187 string
message(int ev) const188 __system_error_category::message(int ev) const
189 {
190 #ifdef _LIBCPP_ELAST
191     if (ev > _LIBCPP_ELAST)
192       return string("unspecified system_category error");
193 #endif  // _LIBCPP_ELAST
194     return __do_message::message(ev);
195 }
196 
197 error_condition
default_error_condition(int ev) const198 __system_error_category::default_error_condition(int ev) const _NOEXCEPT
199 {
200 #ifdef _LIBCPP_ELAST
201     if (ev > _LIBCPP_ELAST)
202       return error_condition(ev, system_category());
203 #endif  // _LIBCPP_ELAST
204     return error_condition(ev, generic_category());
205 }
206 
207 const error_category&
system_category()208 system_category() _NOEXCEPT
209 {
210     static __system_error_category s;
211     return s;
212 }
213 
214 // error_condition
215 
216 string
message() const217 error_condition::message() const
218 {
219     return __cat_->message(__val_);
220 }
221 
222 // error_code
223 
224 string
message() const225 error_code::message() const
226 {
227     return __cat_->message(__val_);
228 }
229 
230 // system_error
231 
232 string
__init(const error_code & ec,string what_arg)233 system_error::__init(const error_code& ec, string what_arg)
234 {
235     if (ec)
236     {
237         if (!what_arg.empty())
238             what_arg += ": ";
239         what_arg += ec.message();
240     }
241     return what_arg;
242 }
243 
system_error(error_code ec,const string & what_arg)244 system_error::system_error(error_code ec, const string& what_arg)
245     : runtime_error(__init(ec, what_arg)),
246       __ec_(ec)
247 {
248 }
249 
system_error(error_code ec,const char * what_arg)250 system_error::system_error(error_code ec, const char* what_arg)
251     : runtime_error(__init(ec, what_arg)),
252       __ec_(ec)
253 {
254 }
255 
system_error(error_code ec)256 system_error::system_error(error_code ec)
257     : runtime_error(__init(ec, "")),
258       __ec_(ec)
259 {
260 }
261 
system_error(int ev,const error_category & ecat,const string & what_arg)262 system_error::system_error(int ev, const error_category& ecat, const string& what_arg)
263     : runtime_error(__init(error_code(ev, ecat), what_arg)),
264       __ec_(error_code(ev, ecat))
265 {
266 }
267 
system_error(int ev,const error_category & ecat,const char * what_arg)268 system_error::system_error(int ev, const error_category& ecat, const char* what_arg)
269     : runtime_error(__init(error_code(ev, ecat), what_arg)),
270       __ec_(error_code(ev, ecat))
271 {
272 }
273 
system_error(int ev,const error_category & ecat)274 system_error::system_error(int ev, const error_category& ecat)
275     : runtime_error(__init(error_code(ev, ecat), "")),
276       __ec_(error_code(ev, ecat))
277 {
278 }
279 
~system_error()280 system_error::~system_error() _NOEXCEPT
281 {
282 }
283 
284 void
__throw_system_error(int ev,const char * what_arg)285 __throw_system_error(int ev, const char* what_arg)
286 {
287 #ifndef _LIBCPP_NO_EXCEPTIONS
288     throw system_error(error_code(ev, system_category()), what_arg);
289 #else
290     (void)ev;
291     (void)what_arg;
292     _VSTD::abort();
293 #endif
294 }
295 
296 _LIBCPP_END_NAMESPACE_STD
297