1// -*- C++ -*-
2//===---------------------------- system_error ----------------------------===//
3//
4//                     The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP_SYSTEM_ERROR
12#define _LIBCPP_SYSTEM_ERROR
13
14/*
15    system_error synopsis
16
17namespace std
18{
19
20class error_category
21{
22public:
23    virtual ~error_category() noexcept;
24
25    constexpr error_category();
26    error_category(const error_category&) = delete;
27    error_category& operator=(const error_category&) = delete;
28
29    virtual const char* name() const noexcept = 0;
30    virtual error_condition default_error_condition(int ev) const noexcept;
31    virtual bool equivalent(int code, const error_condition& condition) const noexcept;
32    virtual bool equivalent(const error_code& code, int condition) const noexcept;
33    virtual string message(int ev) const = 0;
34
35    bool operator==(const error_category& rhs) const noexcept;
36    bool operator!=(const error_category& rhs) const noexcept;
37    bool operator<(const error_category& rhs) const noexcept;
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 size_t is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; // C++17
51
52template <class _Tp>
53inline constexpr size_t 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:
79bool operator<(const error_code& lhs, const error_code& rhs) noexcept;
80template <class charT, class traits>
81    basic_ostream<charT,traits>&
82    operator<<(basic_ostream<charT,traits>& os, const error_code& ec);
83
84class error_condition
85{
86public:
87    // constructors:
88    error_condition() noexcept;
89    error_condition(int val, const error_category& cat) noexcept;
90    template <class ErrorConditionEnum>
91        error_condition(ErrorConditionEnum e) noexcept;
92
93    // modifiers:
94    void assign(int val, const error_category& cat) noexcept;
95    template <class ErrorConditionEnum>
96        error_condition& operator=(ErrorConditionEnum e) noexcept;
97    void clear() noexcept;
98
99    // observers:
100    int value() const noexcept;
101    const error_category& category() const noexcept;
102    string message() const noexcept;
103    explicit operator bool() const noexcept;
104};
105
106bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept;
107
108class system_error
109    : public runtime_error
110{
111public:
112    system_error(error_code ec, const string& what_arg);
113    system_error(error_code ec, const char* what_arg);
114    system_error(error_code ec);
115    system_error(int ev, const error_category& ecat, const string& what_arg);
116    system_error(int ev, const error_category& ecat, const char* what_arg);
117    system_error(int ev, const error_category& ecat);
118
119    const error_code& code() const noexcept;
120    const char* what() const noexcept;
121};
122
123template <> struct is_error_condition_enum<errc>
124    : true_type { }
125
126error_code make_error_code(errc e) noexcept;
127error_condition make_error_condition(errc e) noexcept;
128
129// Comparison operators:
130bool operator==(const error_code& lhs, const error_code& rhs) noexcept;
131bool operator==(const error_code& lhs, const error_condition& rhs) noexcept;
132bool operator==(const error_condition& lhs, const error_code& rhs) noexcept;
133bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept;
134bool operator!=(const error_code& lhs, const error_code& rhs) noexcept;
135bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept;
136bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept;
137bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept;
138
139template <> struct hash<std::error_code>;
140template <> struct hash<std::error_condition>;
141
142}  // std
143
144*/
145
146#include <__errc>
147#include <type_traits>
148#include <stdexcept>
149#include <__functional_base>
150#include <string>
151
152#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
153#pragma GCC system_header
154#endif
155
156_LIBCPP_BEGIN_NAMESPACE_STD
157
158// is_error_code_enum
159
160template <class _Tp>
161struct _LIBCPP_TEMPLATE_VIS is_error_code_enum
162    : public false_type {};
163
164#if _LIBCPP_STD_VER > 14
165template <class _Tp>
166_LIBCPP_INLINE_VAR constexpr size_t is_error_code_enum_v = is_error_code_enum<_Tp>::value;
167#endif
168
169// is_error_condition_enum
170
171template <class _Tp>
172struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum
173    : public false_type {};
174
175#if _LIBCPP_STD_VER > 14
176template <class _Tp>
177_LIBCPP_INLINE_VAR constexpr size_t is_error_condition_enum_v = is_error_condition_enum<_Tp>::value;
178#endif
179
180template <>
181struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc>
182    : true_type { };
183
184#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
185template <>
186struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum<errc::__lx>
187    : true_type { };
188#endif
189
190class _LIBCPP_TYPE_VIS error_condition;
191class _LIBCPP_TYPE_VIS error_code;
192
193// class error_category
194
195class _LIBCPP_HIDDEN __do_message;
196
197class _LIBCPP_TYPE_VIS error_category
198{
199public:
200    virtual ~error_category() _NOEXCEPT;
201
202#if defined(_LIBCPP_BUILDING_LIBRARY) && \
203    defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS)
204    error_category() _NOEXCEPT;
205#else
206    _LIBCPP_INLINE_VISIBILITY
207    _LIBCPP_CONSTEXPR_AFTER_CXX11 error_category() _NOEXCEPT _LIBCPP_DEFAULT
208#endif
209private:
210    error_category(const error_category&);// = delete;
211    error_category& operator=(const error_category&);// = delete;
212
213public:
214    virtual const char* name() const _NOEXCEPT = 0;
215    virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
216    virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
217    virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
218    virtual string message(int __ev) const = 0;
219
220    _LIBCPP_INLINE_VISIBILITY
221    bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;}
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    friend class _LIBCPP_HIDDEN __do_message;
230};
231
232class _LIBCPP_HIDDEN __do_message
233    : public error_category
234{
235public:
236    virtual string message(int ev) const;
237};
238
239_LIBCPP_FUNC_VIS const error_category& generic_category() _NOEXCEPT;
240_LIBCPP_FUNC_VIS const error_category& system_category() _NOEXCEPT;
241
242class _LIBCPP_TYPE_VIS error_condition
243{
244    int __val_;
245    const error_category* __cat_;
246public:
247    _LIBCPP_INLINE_VISIBILITY
248    error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {}
249
250    _LIBCPP_INLINE_VISIBILITY
251    error_condition(int __val, const error_category& __cat) _NOEXCEPT
252        : __val_(__val), __cat_(&__cat) {}
253
254    template <class _Ep>
255        _LIBCPP_INLINE_VISIBILITY
256        error_condition(_Ep __e,
257              typename enable_if<is_error_condition_enum<_Ep>::value>::type* = 0
258                                                                     ) _NOEXCEPT
259            {*this = make_error_condition(__e);}
260
261    _LIBCPP_INLINE_VISIBILITY
262    void assign(int __val, const error_category& __cat) _NOEXCEPT
263    {
264        __val_ = __val;
265        __cat_ = &__cat;
266    }
267
268    template <class _Ep>
269        _LIBCPP_INLINE_VISIBILITY
270        typename enable_if
271        <
272            is_error_condition_enum<_Ep>::value,
273            error_condition&
274        >::type
275        operator=(_Ep __e) _NOEXCEPT
276            {*this = make_error_condition(__e); return *this;}
277
278    _LIBCPP_INLINE_VISIBILITY
279    void clear() _NOEXCEPT
280    {
281        __val_ = 0;
282        __cat_ = &generic_category();
283    }
284
285    _LIBCPP_INLINE_VISIBILITY
286    int value() const _NOEXCEPT {return __val_;}
287
288    _LIBCPP_INLINE_VISIBILITY
289    const error_category& category() const _NOEXCEPT {return *__cat_;}
290    string message() const;
291
292    _LIBCPP_INLINE_VISIBILITY
293        _LIBCPP_EXPLICIT
294        operator bool() const _NOEXCEPT {return __val_ != 0;}
295};
296
297inline _LIBCPP_INLINE_VISIBILITY
298error_condition
299make_error_condition(errc __e) _NOEXCEPT
300{
301    return error_condition(static_cast<int>(__e), generic_category());
302}
303
304inline _LIBCPP_INLINE_VISIBILITY
305bool
306operator<(const error_condition& __x, const error_condition& __y) _NOEXCEPT
307{
308    return __x.category() < __y.category()
309        || (__x.category() == __y.category() && __x.value() < __y.value());
310}
311
312// error_code
313
314class _LIBCPP_TYPE_VIS error_code
315{
316    int __val_;
317    const error_category* __cat_;
318public:
319    _LIBCPP_INLINE_VISIBILITY
320    error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {}
321
322    _LIBCPP_INLINE_VISIBILITY
323    error_code(int __val, const error_category& __cat) _NOEXCEPT
324        : __val_(__val), __cat_(&__cat) {}
325
326    template <class _Ep>
327        _LIBCPP_INLINE_VISIBILITY
328        error_code(_Ep __e,
329                   typename enable_if<is_error_code_enum<_Ep>::value>::type* = 0
330                                                                     ) _NOEXCEPT
331            {*this = make_error_code(__e);}
332
333    _LIBCPP_INLINE_VISIBILITY
334    void assign(int __val, const error_category& __cat) _NOEXCEPT
335    {
336        __val_ = __val;
337        __cat_ = &__cat;
338    }
339
340    template <class _Ep>
341        _LIBCPP_INLINE_VISIBILITY
342        typename enable_if
343        <
344            is_error_code_enum<_Ep>::value,
345            error_code&
346        >::type
347        operator=(_Ep __e) _NOEXCEPT
348            {*this = make_error_code(__e); return *this;}
349
350    _LIBCPP_INLINE_VISIBILITY
351    void clear() _NOEXCEPT
352    {
353        __val_ = 0;
354        __cat_ = &system_category();
355    }
356
357    _LIBCPP_INLINE_VISIBILITY
358    int value() const _NOEXCEPT {return __val_;}
359
360    _LIBCPP_INLINE_VISIBILITY
361    const error_category& category() const _NOEXCEPT {return *__cat_;}
362
363    _LIBCPP_INLINE_VISIBILITY
364    error_condition default_error_condition() const _NOEXCEPT
365        {return __cat_->default_error_condition(__val_);}
366
367    string message() const;
368
369    _LIBCPP_INLINE_VISIBILITY
370        _LIBCPP_EXPLICIT
371        operator bool() const _NOEXCEPT {return __val_ != 0;}
372};
373
374inline _LIBCPP_INLINE_VISIBILITY
375error_code
376make_error_code(errc __e) _NOEXCEPT
377{
378    return error_code(static_cast<int>(__e), generic_category());
379}
380
381inline _LIBCPP_INLINE_VISIBILITY
382bool
383operator<(const error_code& __x, const error_code& __y) _NOEXCEPT
384{
385    return __x.category() < __y.category()
386        || (__x.category() == __y.category() && __x.value() < __y.value());
387}
388
389inline _LIBCPP_INLINE_VISIBILITY
390bool
391operator==(const error_code& __x, const error_code& __y) _NOEXCEPT
392{
393    return __x.category() == __y.category() && __x.value() == __y.value();
394}
395
396inline _LIBCPP_INLINE_VISIBILITY
397bool
398operator==(const error_code& __x, const error_condition& __y) _NOEXCEPT
399{
400    return __x.category().equivalent(__x.value(), __y)
401        || __y.category().equivalent(__x, __y.value());
402}
403
404inline _LIBCPP_INLINE_VISIBILITY
405bool
406operator==(const error_condition& __x, const error_code& __y) _NOEXCEPT
407{
408    return __y == __x;
409}
410
411inline _LIBCPP_INLINE_VISIBILITY
412bool
413operator==(const error_condition& __x, const error_condition& __y) _NOEXCEPT
414{
415    return __x.category() == __y.category() && __x.value() == __y.value();
416}
417
418inline _LIBCPP_INLINE_VISIBILITY
419bool
420operator!=(const error_code& __x, const error_code& __y) _NOEXCEPT
421{return !(__x == __y);}
422
423inline _LIBCPP_INLINE_VISIBILITY
424bool
425operator!=(const error_code& __x, const error_condition& __y) _NOEXCEPT
426{return !(__x == __y);}
427
428inline _LIBCPP_INLINE_VISIBILITY
429bool
430operator!=(const error_condition& __x, const error_code& __y) _NOEXCEPT
431{return !(__x == __y);}
432
433inline _LIBCPP_INLINE_VISIBILITY
434bool
435operator!=(const error_condition& __x, const error_condition& __y) _NOEXCEPT
436{return !(__x == __y);}
437
438template <>
439struct _LIBCPP_TEMPLATE_VIS hash<error_code>
440    : public unary_function<error_code, size_t>
441{
442    _LIBCPP_INLINE_VISIBILITY
443    size_t operator()(const error_code& __ec) const _NOEXCEPT
444    {
445        return static_cast<size_t>(__ec.value());
446    }
447};
448
449template <>
450struct _LIBCPP_TEMPLATE_VIS hash<error_condition>
451    : public unary_function<error_condition, size_t>
452{
453    _LIBCPP_INLINE_VISIBILITY
454    size_t operator()(const error_condition& __ec) const _NOEXCEPT
455    {
456        return static_cast<size_t>(__ec.value());
457    }
458};
459
460// system_error
461
462class _LIBCPP_TYPE_VIS system_error
463    : public runtime_error
464{
465    error_code __ec_;
466public:
467    system_error(error_code __ec, const string& __what_arg);
468    system_error(error_code __ec, const char* __what_arg);
469    system_error(error_code __ec);
470    system_error(int __ev, const error_category& __ecat, const string& __what_arg);
471    system_error(int __ev, const error_category& __ecat, const char* __what_arg);
472    system_error(int __ev, const error_category& __ecat);
473    ~system_error() _NOEXCEPT;
474
475    _LIBCPP_INLINE_VISIBILITY
476    const error_code& code() const _NOEXCEPT {return __ec_;}
477
478private:
479    static string __init(const error_code&, string);
480};
481
482_LIBCPP_NORETURN _LIBCPP_FUNC_VIS
483void __throw_system_error(int ev, const char* what_arg);
484
485_LIBCPP_END_NAMESPACE_STD
486
487#endif  // _LIBCPP_SYSTEM_ERROR
488