xref: /freebsd/contrib/llvm-project/libcxx/include/system_error (revision ba3c1f5972d7b90feb6e6da47905ff2757e0fe57)
1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_SYSTEM_ERROR
11#define _LIBCPP_SYSTEM_ERROR
12
13/*
14    system_error synopsis
15
16namespace std
17{
18
19class error_category
20{
21public:
22    virtual ~error_category() noexcept;
23
24    constexpr error_category();
25    error_category(const error_category&) = delete;
26    error_category& operator=(const error_category&) = delete;
27
28    virtual const char* name() const noexcept = 0;
29    virtual error_condition default_error_condition(int ev) const noexcept;
30    virtual bool equivalent(int code, const error_condition& condition) const noexcept;
31    virtual bool equivalent(const error_code& code, int condition) const noexcept;
32    virtual string message(int ev) const = 0;
33
34    bool operator==(const error_category& rhs) const noexcept;
35    bool operator!=(const error_category& rhs) const noexcept;              // removed in C++20
36    bool operator<(const error_category& rhs) const noexcept;               // removed in C++20
37    strong_ordering operator<=>(const error_category& rhs) const noexcept;  // C++20
38};
39
40const error_category& generic_category() noexcept;
41const error_category& system_category() noexcept;
42
43template <class T> struct is_error_code_enum
44    : public false_type {};
45
46template <class T> struct is_error_condition_enum
47    : public false_type {};
48
49template <class _Tp>
50inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; // C++17
51
52template <class _Tp>
53inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value; // C++17
54
55class error_code
56{
57public:
58    // constructors:
59    error_code() noexcept;
60    error_code(int val, const error_category& cat) noexcept;
61    template <class ErrorCodeEnum>
62        error_code(ErrorCodeEnum e) noexcept;
63
64    // modifiers:
65    void assign(int val, const error_category& cat) noexcept;
66    template <class ErrorCodeEnum>
67        error_code& operator=(ErrorCodeEnum e) noexcept;
68    void clear() noexcept;
69
70    // observers:
71    int value() const noexcept;
72    const error_category& category() const noexcept;
73    error_condition default_error_condition() const noexcept;
74    string message() const;
75    explicit operator bool() const noexcept;
76};
77
78// non-member functions:
79template <class charT, class traits>
80    basic_ostream<charT,traits>&
81    operator<<(basic_ostream<charT,traits>& os, const error_code& ec);
82
83class error_condition
84{
85public:
86    // constructors:
87    error_condition() noexcept;
88    error_condition(int val, const error_category& cat) noexcept;
89    template <class ErrorConditionEnum>
90        error_condition(ErrorConditionEnum e) noexcept;
91
92    // modifiers:
93    void assign(int val, const error_category& cat) noexcept;
94    template <class ErrorConditionEnum>
95        error_condition& operator=(ErrorConditionEnum e) noexcept;
96    void clear() noexcept;
97
98    // observers:
99    int value() const noexcept;
100    const error_category& category() const noexcept;
101    string message() const noexcept;
102    explicit operator bool() const noexcept;
103};
104
105class system_error
106    : public runtime_error
107{
108public:
109    system_error(error_code ec, const string& what_arg);
110    system_error(error_code ec, const char* what_arg);
111    system_error(error_code ec);
112    system_error(int ev, const error_category& ecat, const string& what_arg);
113    system_error(int ev, const error_category& ecat, const char* what_arg);
114    system_error(int ev, const error_category& ecat);
115
116    const error_code& code() const noexcept;
117    const char* what() const noexcept;
118};
119
120template <> struct is_error_condition_enum<errc>
121    : true_type { }
122
123error_code make_error_code(errc e) noexcept;
124error_condition make_error_condition(errc e) noexcept;
125
126// Comparison operators:
127bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
128bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
129bool operator==(const error_condition& lhs, const error_code& rhs) noexcept;                  // removed in C++20
130bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
131bool operator!=(const error_code& lhs, const error_code& rhs) noexcept;                       // removed in C++20
132bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept;                  // removed in C++20
133bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept;                  // removed in C++20
134bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept;             // removed in C++20
135bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept;              // removed in C++20
136bool operator<(const error_code& lhs, const error_code& rhs) noexcept;                        // removed in C++20
137strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept;           // C++20
138strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept; // C++20
139
140template <> struct hash<std::error_code>;
141template <> struct hash<std::error_condition>;
142
143}  // std
144
145*/
146
147#include <__assert> // all public C++ headers provide the assertion handler
148#include <__config>
149#include <__errc>
150#include <__functional/hash.h>
151#include <__functional/unary_function.h>
152#include <__memory/addressof.h>
153#include <stdexcept>
154#include <string>
155#include <type_traits>
156#include <version>
157
158// standard-mandated includes
159
160// [system.error.syn]
161#include <compare>
162
163#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
164#  pragma GCC system_header
165#endif
166
167_LIBCPP_BEGIN_NAMESPACE_STD
168
169// is_error_code_enum
170
171template <class _Tp>
172struct _LIBCPP_TEMPLATE_VIS is_error_code_enum
173    : public false_type {};
174
175#if _LIBCPP_STD_VER > 14
176template <class _Tp>
177inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value;
178#endif
179
180// is_error_condition_enum
181
182template <class _Tp>
183struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum
184    : public false_type {};
185
186#if _LIBCPP_STD_VER > 14
187template <class _Tp>
188inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value;
189#endif
190
191template <>
192struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc>
193    : true_type { };
194
195#ifdef _LIBCPP_CXX03_LANG
196template <>
197struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc::__lx>
198    : true_type { };
199#endif
200
201class _LIBCPP_TYPE_VIS error_condition;
202class _LIBCPP_TYPE_VIS error_code;
203
204// class error_category
205
206class _LIBCPP_HIDDEN __do_message;
207
208class _LIBCPP_TYPE_VIS error_category
209{
210public:
211    virtual ~error_category() _NOEXCEPT;
212
213#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
214    error_category() noexcept;
215#else
216    _LIBCPP_INLINE_VISIBILITY
217    _LIBCPP_CONSTEXPR_SINCE_CXX14 error_category() _NOEXCEPT = default;
218#endif
219    error_category(const error_category&) = delete;
220    error_category& operator=(const error_category&) = delete;
221
222    virtual const char* name() const _NOEXCEPT = 0;
223    virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
224    virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
225    virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
226    virtual string message(int __ev) const = 0;
227
228    _LIBCPP_INLINE_VISIBILITY
229    bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;}
230
231#if _LIBCPP_STD_VER > 17
232
233    _LIBCPP_HIDE_FROM_ABI
234    strong_ordering operator<=>(const error_category& __rhs) const noexcept {return compare_three_way()(this, std::addressof(__rhs));}
235
236#else // _LIBCPP_STD_VER > 17
237
238    _LIBCPP_INLINE_VISIBILITY
239    bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);}
240
241    _LIBCPP_INLINE_VISIBILITY
242    bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;}
243
244#endif // _LIBCPP_STD_VER > 17
245
246    friend class _LIBCPP_HIDDEN __do_message;
247};
248
249class _LIBCPP_HIDDEN __do_message
250    : public error_category
251{
252public:
253    string message(int __ev) const override;
254};
255
256_LIBCPP_FUNC_VIS const error_category& generic_category() _NOEXCEPT;
257_LIBCPP_FUNC_VIS const error_category& system_category() _NOEXCEPT;
258
259namespace __adl_only {
260    // Those cause ADL to trigger but they are not viable candidates,
261    // so they are never actually selected.
262    void make_error_condition() = delete;
263    void make_error_code() = delete;
264} // namespace __adl_only
265
266class _LIBCPP_TYPE_VIS error_condition
267{
268    int __val_;
269    const error_category* __cat_;
270public:
271    _LIBCPP_INLINE_VISIBILITY
272    error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {}
273
274    _LIBCPP_INLINE_VISIBILITY
275    error_condition(int __val, const error_category& __cat) _NOEXCEPT
276        : __val_(__val), __cat_(&__cat) {}
277
278    template <class _Ep>
279        _LIBCPP_INLINE_VISIBILITY
280        error_condition(_Ep __e,
281              typename enable_if<is_error_condition_enum<_Ep>::value>::type* = nullptr
282                                                                     ) _NOEXCEPT
283            {
284                using __adl_only::make_error_condition;
285                *this = make_error_condition(__e);
286            }
287
288    _LIBCPP_INLINE_VISIBILITY
289    void assign(int __val, const error_category& __cat) _NOEXCEPT
290    {
291        __val_ = __val;
292        __cat_ = &__cat;
293    }
294
295    template <class _Ep>
296        _LIBCPP_INLINE_VISIBILITY
297        typename enable_if
298        <
299            is_error_condition_enum<_Ep>::value,
300            error_condition&
301        >::type
302        operator=(_Ep __e) _NOEXCEPT
303            {
304                using __adl_only::make_error_condition;
305                *this = make_error_condition(__e);
306                return *this;
307            }
308
309    _LIBCPP_INLINE_VISIBILITY
310    void clear() _NOEXCEPT
311    {
312        __val_ = 0;
313        __cat_ = &generic_category();
314    }
315
316    _LIBCPP_INLINE_VISIBILITY
317    int value() const _NOEXCEPT {return __val_;}
318
319    _LIBCPP_INLINE_VISIBILITY
320    const error_category& category() const _NOEXCEPT {return *__cat_;}
321    string message() const;
322
323    _LIBCPP_INLINE_VISIBILITY
324    explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
325};
326
327inline _LIBCPP_INLINE_VISIBILITY
328error_condition
329make_error_condition(errc __e) _NOEXCEPT
330{
331    return error_condition(static_cast<int>(__e), generic_category());
332}
333
334// error_code
335
336class _LIBCPP_TYPE_VIS error_code
337{
338    int __val_;
339    const error_category* __cat_;
340public:
341    _LIBCPP_INLINE_VISIBILITY
342    error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {}
343
344    _LIBCPP_INLINE_VISIBILITY
345    error_code(int __val, const error_category& __cat) _NOEXCEPT
346        : __val_(__val), __cat_(&__cat) {}
347
348    template <class _Ep>
349        _LIBCPP_INLINE_VISIBILITY
350        error_code(_Ep __e,
351                   typename enable_if<is_error_code_enum<_Ep>::value>::type* = nullptr
352                                                                     ) _NOEXCEPT
353            {
354                using __adl_only::make_error_code;
355                *this = make_error_code(__e);
356            }
357
358    _LIBCPP_INLINE_VISIBILITY
359    void assign(int __val, const error_category& __cat) _NOEXCEPT
360    {
361        __val_ = __val;
362        __cat_ = &__cat;
363    }
364
365    template <class _Ep>
366        _LIBCPP_INLINE_VISIBILITY
367        typename enable_if
368        <
369            is_error_code_enum<_Ep>::value,
370            error_code&
371        >::type
372        operator=(_Ep __e) _NOEXCEPT
373            {
374                using __adl_only::make_error_code;
375                *this = make_error_code(__e);
376                return *this;
377            }
378
379    _LIBCPP_INLINE_VISIBILITY
380    void clear() _NOEXCEPT
381    {
382        __val_ = 0;
383        __cat_ = &system_category();
384    }
385
386    _LIBCPP_INLINE_VISIBILITY
387    int value() const _NOEXCEPT {return __val_;}
388
389    _LIBCPP_INLINE_VISIBILITY
390    const error_category& category() const _NOEXCEPT {return *__cat_;}
391
392    _LIBCPP_INLINE_VISIBILITY
393    error_condition default_error_condition() const _NOEXCEPT
394        {return __cat_->default_error_condition(__val_);}
395
396    string message() const;
397
398    _LIBCPP_INLINE_VISIBILITY
399    explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
400};
401
402inline _LIBCPP_INLINE_VISIBILITY
403error_code
404make_error_code(errc __e) _NOEXCEPT
405{
406    return error_code(static_cast<int>(__e), generic_category());
407}
408
409inline _LIBCPP_INLINE_VISIBILITY
410bool
411operator==(const error_code& __x, const error_code& __y) _NOEXCEPT
412{
413    return __x.category() == __y.category() && __x.value() == __y.value();
414}
415
416inline _LIBCPP_INLINE_VISIBILITY
417bool
418operator==(const error_code& __x, const error_condition& __y) _NOEXCEPT
419{
420    return __x.category().equivalent(__x.value(), __y)
421        || __y.category().equivalent(__x, __y.value());
422}
423
424#if _LIBCPP_STD_VER <= 17
425inline _LIBCPP_INLINE_VISIBILITY
426bool
427operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT
428{
429    return __y == __x;
430}
431#endif
432
433inline _LIBCPP_INLINE_VISIBILITY
434bool
435operator==(const error_condition& __x, const error_condition& __y) _NOEXCEPT
436{
437    return __x.category() == __y.category() && __x.value() == __y.value();
438}
439
440#if _LIBCPP_STD_VER <= 17
441
442inline _LIBCPP_INLINE_VISIBILITY
443bool
444operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT
445{return !(__x == __y);}
446
447inline _LIBCPP_INLINE_VISIBILITY
448bool
449operator!=(const error_code& __x, const error_condition& __y) _NOEXCEPT
450{return !(__x == __y);}
451
452inline _LIBCPP_INLINE_VISIBILITY
453bool
454operator!=(const error_condition& __x, const error_code& __y) _NOEXCEPT
455{return !(__x == __y);}
456
457inline _LIBCPP_INLINE_VISIBILITY
458bool
459operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT
460{return !(__x == __y);}
461
462inline _LIBCPP_INLINE_VISIBILITY
463bool
464operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT
465{
466    return __x.category() < __y.category()
467        || (__x.category() == __y.category() && __x.value() < __y.value());
468}
469
470inline _LIBCPP_INLINE_VISIBILITY
471bool
472operator<(const error_code& __x, const error_code& __y) _NOEXCEPT
473{
474    return __x.category() < __y.category()
475        || (__x.category() == __y.category() && __x.value() < __y.value());
476}
477
478#else // _LIBCPP_STD_VER <= 17
479
480inline _LIBCPP_HIDE_FROM_ABI strong_ordering
481operator<=>(const error_code& __x, const error_code& __y) noexcept
482{
483    if (auto __c = __x.category() <=> __y.category(); __c != 0)
484        return __c;
485    return __x.value() <=> __y.value();
486}
487
488inline _LIBCPP_HIDE_FROM_ABI strong_ordering
489operator<=>(const error_condition& __x, const error_condition& __y) noexcept
490{
491    if (auto __c = __x.category() <=> __y.category(); __c != 0)
492       return __c;
493    return __x.value() <=> __y.value();
494}
495
496#endif // _LIBCPP_STD_VER <= 17
497
498template <>
499struct _LIBCPP_TEMPLATE_VIS hash<error_code>
500    : public __unary_function<error_code, size_t>
501{
502    _LIBCPP_INLINE_VISIBILITY
503    size_t operator()(const error_code& __ec) const _NOEXCEPT
504    {
505        return static_cast<size_t>(__ec.value());
506    }
507};
508
509template <>
510struct _LIBCPP_TEMPLATE_VIS hash<error_condition>
511    : public __unary_function<error_condition, size_t>
512{
513    _LIBCPP_INLINE_VISIBILITY
514    size_t operator()(const error_condition& __ec) const _NOEXCEPT
515    {
516        return static_cast<size_t>(__ec.value());
517    }
518};
519
520// system_error
521
522class _LIBCPP_TYPE_VIS system_error
523    : public runtime_error
524{
525    error_code __ec_;
526public:
527    system_error(error_code __ec, const string& __what_arg);
528    system_error(error_code __ec, const char* __what_arg);
529    system_error(error_code __ec);
530    system_error(int __ev, const error_category& __ecat, const string& __what_arg);
531    system_error(int __ev, const error_category& __ecat, const char* __what_arg);
532    system_error(int __ev, const error_category& __ecat);
533    system_error(const system_error&) _NOEXCEPT = default;
534    ~system_error() _NOEXCEPT override;
535
536    _LIBCPP_INLINE_VISIBILITY
537    const error_code& code() const _NOEXCEPT {return __ec_;}
538
539private:
540    static string __init(const error_code&, string);
541};
542
543_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
544void __throw_system_error(int __ev, const char* __what_arg);
545
546_LIBCPP_END_NAMESPACE_STD
547
548#endif // _LIBCPP_SYSTEM_ERROR
549