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;
36    bool operator<(const error_category& rhs) const noexcept;
37};
38
39const error_category& generic_category() noexcept;
40const error_category& system_category() noexcept;
41
42template <class T> struct is_error_code_enum
43    : public false_type {};
44
45template <class T> struct is_error_condition_enum
46    : public false_type {};
47
48template <class _Tp>
49inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; // C++17
50
51template <class _Tp>
52inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value; // C++17
53
54class error_code
55{
56public:
57    // constructors:
58    error_code() noexcept;
59    error_code(int val, const error_category& cat) noexcept;
60    template <class ErrorCodeEnum>
61        error_code(ErrorCodeEnum e) noexcept;
62
63    // modifiers:
64    void assign(int val, const error_category& cat) noexcept;
65    template <class ErrorCodeEnum>
66        error_code& operator=(ErrorCodeEnum e) noexcept;
67    void clear() noexcept;
68
69    // observers:
70    int value() const noexcept;
71    const error_category& category() const noexcept;
72    error_condition default_error_condition() const noexcept;
73    string message() const;
74    explicit operator bool() const noexcept;
75};
76
77// non-member functions:
78bool operator<(const error_code& lhs, const error_code& rhs) noexcept;
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
105bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept;
106
107class system_error
108    : public runtime_error
109{
110public:
111    system_error(error_code ec, const string& what_arg);
112    system_error(error_code ec, const char* what_arg);
113    system_error(error_code ec);
114    system_error(int ev, const error_category& ecat, const string& what_arg);
115    system_error(int ev, const error_category& ecat, const char* what_arg);
116    system_error(int ev, const error_category& ecat);
117
118    const error_code& code() const noexcept;
119    const char* what() const noexcept;
120};
121
122template <> struct is_error_condition_enum<errc>
123    : true_type { }
124
125error_code make_error_code(errc e) noexcept;
126error_condition make_error_condition(errc e) noexcept;
127
128// Comparison operators:
129bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
130bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
131bool operator==(const error_condition& lhs, const error_code& rhs) noexcept;
132bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
133bool operator!=(const error_code& lhs, const error_code& rhs) noexcept;
134bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept;
135bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept;
136bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept;
137
138template <> struct hash<std::error_code>;
139template <> struct hash<std::error_condition>;
140
141}  // std
142
143*/
144
145#include <__assert> // all public C++ headers provide the assertion handler
146#include <__config>
147#include <__errc>
148#include <__functional/hash.h>
149#include <__functional/unary_function.h>
150#include <stdexcept>
151#include <string>
152#include <type_traits>
153#include <version>
154
155// standard-mandated includes
156#include <compare>
157
158#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
159#  pragma GCC system_header
160#endif
161
162_LIBCPP_BEGIN_NAMESPACE_STD
163
164// is_error_code_enum
165
166template <class _Tp>
167struct _LIBCPP_TEMPLATE_VIS is_error_code_enum
168    : public false_type {};
169
170#if _LIBCPP_STD_VER > 14
171template <class _Tp>
172inline constexpr bool is_error_code_enum_v = is_error_code_enum<_Tp>::value;
173#endif
174
175// is_error_condition_enum
176
177template <class _Tp>
178struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum
179    : public false_type {};
180
181#if _LIBCPP_STD_VER > 14
182template <class _Tp>
183inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<_Tp>::value;
184#endif
185
186template <>
187struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc>
188    : true_type { };
189
190#ifdef _LIBCPP_CXX03_LANG
191template <>
192struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc::__lx>
193    : true_type { };
194#endif
195
196class _LIBCPP_TYPE_VIS error_condition;
197class _LIBCPP_TYPE_VIS error_code;
198
199// class error_category
200
201class _LIBCPP_HIDDEN __do_message;
202
203class _LIBCPP_TYPE_VIS error_category
204{
205public:
206    virtual ~error_category() _NOEXCEPT;
207
208#if defined(_LIBCPP_ERROR_CATEGORY_DEFINE_LEGACY_INLINE_FUNCTIONS)
209    error_category() noexcept;
210#else
211    _LIBCPP_INLINE_VISIBILITY
212    _LIBCPP_CONSTEXPR_AFTER_CXX11 error_category() _NOEXCEPT = default;
213#endif
214    error_category(const error_category&) = delete;
215    error_category& operator=(const error_category&) = delete;
216
217    virtual const char* name() const _NOEXCEPT = 0;
218    virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
219    virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
220    virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
221    virtual string message(int __ev) const = 0;
222
223    _LIBCPP_INLINE_VISIBILITY
224    bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;}
225
226    _LIBCPP_INLINE_VISIBILITY
227    bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);}
228
229    _LIBCPP_INLINE_VISIBILITY
230    bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;}
231
232    friend class _LIBCPP_HIDDEN __do_message;
233};
234
235class _LIBCPP_HIDDEN __do_message
236    : public error_category
237{
238public:
239    virtual string message(int __ev) const;
240};
241
242_LIBCPP_FUNC_VIS const error_category& generic_category() _NOEXCEPT;
243_LIBCPP_FUNC_VIS const error_category& system_category() _NOEXCEPT;
244
245class _LIBCPP_TYPE_VIS error_condition
246{
247    int __val_;
248    const error_category* __cat_;
249public:
250    _LIBCPP_INLINE_VISIBILITY
251    error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {}
252
253    _LIBCPP_INLINE_VISIBILITY
254    error_condition(int __val, const error_category& __cat) _NOEXCEPT
255        : __val_(__val), __cat_(&__cat) {}
256
257    template <class _Ep>
258        _LIBCPP_INLINE_VISIBILITY
259        error_condition(_Ep __e,
260              typename enable_if<is_error_condition_enum<_Ep>::value>::type* = nullptr
261                                                                     ) _NOEXCEPT
262            {*this = make_error_condition(__e);}
263
264    _LIBCPP_INLINE_VISIBILITY
265    void assign(int __val, const error_category& __cat) _NOEXCEPT
266    {
267        __val_ = __val;
268        __cat_ = &__cat;
269    }
270
271    template <class _Ep>
272        _LIBCPP_INLINE_VISIBILITY
273        typename enable_if
274        <
275            is_error_condition_enum<_Ep>::value,
276            error_condition&
277        >::type
278        operator=(_Ep __e) _NOEXCEPT
279            {*this = make_error_condition(__e); return *this;}
280
281    _LIBCPP_INLINE_VISIBILITY
282    void clear() _NOEXCEPT
283    {
284        __val_ = 0;
285        __cat_ = &generic_category();
286    }
287
288    _LIBCPP_INLINE_VISIBILITY
289    int value() const _NOEXCEPT {return __val_;}
290
291    _LIBCPP_INLINE_VISIBILITY
292    const error_category& category() const _NOEXCEPT {return *__cat_;}
293    string message() const;
294
295    _LIBCPP_INLINE_VISIBILITY
296    explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
297};
298
299inline _LIBCPP_INLINE_VISIBILITY
300error_condition
301make_error_condition(errc __e) _NOEXCEPT
302{
303    return error_condition(static_cast<int>(__e), generic_category());
304}
305
306inline _LIBCPP_INLINE_VISIBILITY
307bool
308operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT
309{
310    return __x.category() < __y.category()
311        || (__x.category() == __y.category() && __x.value() < __y.value());
312}
313
314// error_code
315
316class _LIBCPP_TYPE_VIS error_code
317{
318    int __val_;
319    const error_category* __cat_;
320public:
321    _LIBCPP_INLINE_VISIBILITY
322    error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {}
323
324    _LIBCPP_INLINE_VISIBILITY
325    error_code(int __val, const error_category& __cat) _NOEXCEPT
326        : __val_(__val), __cat_(&__cat) {}
327
328    template <class _Ep>
329        _LIBCPP_INLINE_VISIBILITY
330        error_code(_Ep __e,
331                   typename enable_if<is_error_code_enum<_Ep>::value>::type* = nullptr
332                                                                     ) _NOEXCEPT
333            {*this = make_error_code(__e);}
334
335    _LIBCPP_INLINE_VISIBILITY
336    void assign(int __val, const error_category& __cat) _NOEXCEPT
337    {
338        __val_ = __val;
339        __cat_ = &__cat;
340    }
341
342    template <class _Ep>
343        _LIBCPP_INLINE_VISIBILITY
344        typename enable_if
345        <
346            is_error_code_enum<_Ep>::value,
347            error_code&
348        >::type
349        operator=(_Ep __e) _NOEXCEPT
350            {*this = make_error_code(__e); return *this;}
351
352    _LIBCPP_INLINE_VISIBILITY
353    void clear() _NOEXCEPT
354    {
355        __val_ = 0;
356        __cat_ = &system_category();
357    }
358
359    _LIBCPP_INLINE_VISIBILITY
360    int value() const _NOEXCEPT {return __val_;}
361
362    _LIBCPP_INLINE_VISIBILITY
363    const error_category& category() const _NOEXCEPT {return *__cat_;}
364
365    _LIBCPP_INLINE_VISIBILITY
366    error_condition default_error_condition() const _NOEXCEPT
367        {return __cat_->default_error_condition(__val_);}
368
369    string message() const;
370
371    _LIBCPP_INLINE_VISIBILITY
372    explicit operator bool() const _NOEXCEPT {return __val_ != 0;}
373};
374
375inline _LIBCPP_INLINE_VISIBILITY
376error_code
377make_error_code(errc __e) _NOEXCEPT
378{
379    return error_code(static_cast<int>(__e), generic_category());
380}
381
382inline _LIBCPP_INLINE_VISIBILITY
383bool
384operator<(const error_code& __x, const error_code& __y) _NOEXCEPT
385{
386    return __x.category() < __y.category()
387        || (__x.category() == __y.category() && __x.value() < __y.value());
388}
389
390inline _LIBCPP_INLINE_VISIBILITY
391bool
392operator==(const error_code& __x, const error_code& __y) _NOEXCEPT
393{
394    return __x.category() == __y.category() && __x.value() == __y.value();
395}
396
397inline _LIBCPP_INLINE_VISIBILITY
398bool
399operator==(const error_code& __x, const error_condition& __y) _NOEXCEPT
400{
401    return __x.category().equivalent(__x.value(), __y)
402        || __y.category().equivalent(__x, __y.value());
403}
404
405inline _LIBCPP_INLINE_VISIBILITY
406bool
407operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT
408{
409    return __y == __x;
410}
411
412inline _LIBCPP_INLINE_VISIBILITY
413bool
414operator==(const error_condition& __x, const error_condition& __y) _NOEXCEPT
415{
416    return __x.category() == __y.category() && __x.value() == __y.value();
417}
418
419inline _LIBCPP_INLINE_VISIBILITY
420bool
421operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT
422{return !(__x == __y);}
423
424inline _LIBCPP_INLINE_VISIBILITY
425bool
426operator!=(const error_code& __x, const error_condition& __y) _NOEXCEPT
427{return !(__x == __y);}
428
429inline _LIBCPP_INLINE_VISIBILITY
430bool
431operator!=(const error_condition& __x, const error_code& __y) _NOEXCEPT
432{return !(__x == __y);}
433
434inline _LIBCPP_INLINE_VISIBILITY
435bool
436operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT
437{return !(__x == __y);}
438
439template <>
440struct _LIBCPP_TEMPLATE_VIS hash<error_code>
441    : public __unary_function<error_code, size_t>
442{
443    _LIBCPP_INLINE_VISIBILITY
444    size_t operator()(const error_code& __ec) const _NOEXCEPT
445    {
446        return static_cast<size_t>(__ec.value());
447    }
448};
449
450template <>
451struct _LIBCPP_TEMPLATE_VIS hash<error_condition>
452    : public __unary_function<error_condition, size_t>
453{
454    _LIBCPP_INLINE_VISIBILITY
455    size_t operator()(const error_condition& __ec) const _NOEXCEPT
456    {
457        return static_cast<size_t>(__ec.value());
458    }
459};
460
461// system_error
462
463class _LIBCPP_TYPE_VIS system_error
464    : public runtime_error
465{
466    error_code __ec_;
467public:
468    system_error(error_code __ec, const string& __what_arg);
469    system_error(error_code __ec, const char* __what_arg);
470    system_error(error_code __ec);
471    system_error(int __ev, const error_category& __ecat, const string& __what_arg);
472    system_error(int __ev, const error_category& __ecat, const char* __what_arg);
473    system_error(int __ev, const error_category& __ecat);
474    system_error(const system_error&) _NOEXCEPT = default;
475    ~system_error() _NOEXCEPT;
476
477    _LIBCPP_INLINE_VISIBILITY
478    const error_code& code() const _NOEXCEPT {return __ec_;}
479
480private:
481    static string __init(const error_code&, string);
482};
483
484_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
485void __throw_system_error(int __ev, const char* __what_arg);
486
487_LIBCPP_END_NAMESPACE_STD
488
489#endif // _LIBCPP_SYSTEM_ERROR
490