xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/system_error (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
1// <system_error> -*- C++ -*-
2
3// Copyright (C) 2007-2022 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file include/system_error
26 *  This is a Standard C++ Library header.
27 */
28
29#ifndef _GLIBCXX_SYSTEM_ERROR
30#define _GLIBCXX_SYSTEM_ERROR 1
31
32#pragma GCC system_header
33
34#if __cplusplus < 201103L
35# include <bits/c++0x_warning.h>
36#else
37
38#include <bits/c++config.h>
39#include <bits/error_constants.h>
40#include <iosfwd>
41#include <stdexcept>
42#if __cplusplus > 201703L
43# include <compare>
44#endif
45
46namespace std _GLIBCXX_VISIBILITY(default)
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50  /** @addtogroup diagnostics
51   * @{
52   */
53
54  class error_code;
55  class error_condition;
56  class system_error;
57
58  /// is_error_code_enum
59  template<typename _Tp>
60    struct is_error_code_enum : public false_type { };
61
62  /// is_error_condition_enum
63  template<typename _Tp>
64    struct is_error_condition_enum : public false_type { };
65
66  template<>
67    struct is_error_condition_enum<errc>
68    : public true_type { };
69
70#if __cplusplus > 201402L
71  template <typename _Tp>
72    inline constexpr bool is_error_code_enum_v =
73      is_error_code_enum<_Tp>::value;
74  template <typename _Tp>
75    inline constexpr bool is_error_condition_enum_v =
76      is_error_condition_enum<_Tp>::value;
77#endif // C++17
78  /// @}
79
80  inline namespace _V2 {
81
82  /** @addtogroup diagnostics
83   * @{
84   */
85
86  /** Abstract base class for types defining a category of error codes.
87   *
88   * An error category defines a context that gives meaning to the integer
89   * stored in an `error_code` or `error_condition` object. For example,
90   * the standard `errno` constants such a `EINVAL` and `ENOMEM` are
91   * associated with the "generic" category and other OS-specific error
92   * numbers are associated with the "system" category, but a user-defined
93   * category might give different meanings to the same numerical values.
94   *
95   * A user-defined category can override the `equivalent` member functions
96   * to define correspondence between errors in different categories.
97   * For example, a category for errors from disk I/O could consider some
98   * of its error numbers equivalent to ENOSPC and ENOENT in the generic
99   * category.
100   *
101   * @headerfile system_error
102   * @since C++11
103   */
104  class error_category
105  {
106  public:
107    constexpr error_category() noexcept = default;
108
109    virtual ~error_category();
110
111    error_category(const error_category&) = delete;
112    error_category& operator=(const error_category&) = delete;
113
114    /// A string that identifies the error category.
115    virtual const char*
116    name() const noexcept = 0;
117
118    // We need two different virtual functions here, one returning a
119    // COW string and one returning an SSO string. Their positions in the
120    // vtable must be consistent for dynamic dispatch to work, but which one
121    // the name "message()" finds depends on which ABI the caller is using.
122#if _GLIBCXX_USE_CXX11_ABI
123  private:
124    _GLIBCXX_DEFAULT_ABI_TAG
125    virtual __cow_string
126    _M_message(int) const;
127
128  public:
129    /// A description of the error condition corresponding to the number.
130    _GLIBCXX_DEFAULT_ABI_TAG
131    virtual string
132    message(int) const = 0;
133#else
134    virtual string
135    message(int) const = 0;
136
137  private:
138    virtual __sso_string
139    _M_message(int) const;
140#endif
141
142  public:
143    /// Return an error_condition corresponding to `i` in this category.
144    virtual error_condition
145    default_error_condition(int __i) const noexcept;
146
147    /// Test whether `cond` corresponds to `i` for this category.
148    virtual bool
149    equivalent(int __i, const error_condition& __cond) const noexcept;
150
151    /// Test whether `code` corresponds to `i` for this category.
152    virtual bool
153    equivalent(const error_code& __code, int __i) const noexcept;
154
155    /// An error_category only compares equal to itself.
156    [[__nodiscard__]]
157    bool
158    operator==(const error_category& __other) const noexcept
159    { return this == &__other; }
160
161    /// Ordered comparison that defines a total order for error categories.
162#if __cpp_lib_three_way_comparison
163    [[nodiscard]]
164    strong_ordering
165    operator<=>(const error_category& __rhs) const noexcept
166    { return std::compare_three_way()(this, &__rhs); }
167#else
168    bool
169    operator<(const error_category& __other) const noexcept
170    { return less<const error_category*>()(this, &__other); }
171
172    bool
173    operator!=(const error_category& __other) const noexcept
174    { return this != &__other; }
175#endif
176  };
177
178  // DR 890.
179
180  /// Error category for `errno` error codes.
181  [[__nodiscard__, __gnu__::__const__]]
182  const error_category&
183  generic_category() noexcept;
184
185  /// Error category for other error codes defined by the OS.
186  [[__nodiscard__, __gnu__::__const__]]
187  const error_category&
188  system_category() noexcept;
189
190  /// @}
191  } // end inline namespace
192
193  /** @addtogroup diagnostics
194   * @{
195   */
196
197namespace __adl_only
198{
199  void make_error_code() = delete;
200  void make_error_condition() = delete;
201}
202
203  /** Class error_code
204   *
205   * This class is a value type storing an integer error number and a
206   * category that gives meaning to the error number. Typically this is done
207   * close the the point where the error happens, to capture the original
208   * error value.
209   *
210   * An `error_code` object can be used to store the original error value
211   * emitted by some subsystem, with a category relevant to the subsystem.
212   * For example, errors from POSIX library functions can be represented by
213   * an `errno` value and the "generic" category, but errors from an HTTP
214   * library might be represented by an HTTP response status code (e.g. 404)
215   * and a custom category defined by the library.
216   *
217   * @headerfile system_error
218   * @since C++11
219   */
220  class error_code
221  {
222  public:
223    error_code() noexcept
224    : _M_value(0), _M_cat(&system_category()) { }
225
226    error_code(int __v, const error_category& __cat) noexcept
227    : _M_value(__v), _M_cat(&__cat) { }
228
229    template<typename _ErrorCodeEnum, typename = typename
230	     enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type>
231      error_code(_ErrorCodeEnum __e) noexcept
232      {
233	using __adl_only::make_error_code;
234	*this = make_error_code(__e);
235      }
236
237    void
238    assign(int __v, const error_category& __cat) noexcept
239    {
240      _M_value = __v;
241      _M_cat = &__cat;
242    }
243
244    void
245    clear() noexcept
246    { assign(0, system_category()); }
247
248    // DR 804.
249    template<typename _ErrorCodeEnum>
250      typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value,
251			 error_code&>::type
252      operator=(_ErrorCodeEnum __e) noexcept
253      { return *this = make_error_code(__e); }
254
255    /// The error value.
256    [[__nodiscard__]]
257    int
258    value() const noexcept { return _M_value; }
259
260    /// The error category that this error belongs to.
261    [[__nodiscard__]]
262    const error_category&
263    category() const noexcept { return *_M_cat; }
264
265    /// An `error_condition` for this error's category and value.
266    error_condition
267    default_error_condition() const noexcept;
268
269    /// The category's description of the value.
270    _GLIBCXX_DEFAULT_ABI_TAG
271    string
272    message() const
273    { return category().message(value()); }
274
275    /// Test whether `value()` is non-zero.
276    [[__nodiscard__]]
277    explicit operator bool() const noexcept
278    { return _M_value != 0; }
279
280    // DR 804.
281  private:
282    int            		_M_value;
283    const error_category* 	_M_cat;
284  };
285
286  // C++11 19.5.2.5 non-member functions
287
288  /** Create an `error_code` representing a standard `errc` condition.
289   *
290   * The `std::errc` constants correspond to `errno` macros and so use the
291   * generic category.
292   *
293   * @relates error_code
294   * @since C++11
295   */
296  [[__nodiscard__]]
297  inline error_code
298  make_error_code(errc __e) noexcept
299  { return error_code(static_cast<int>(__e), generic_category()); }
300
301  /** Ordered comparison for std::error_code.
302   *
303   * This defines a total order by comparing the categories, and then
304   * if they are equal comparing the values.
305   *
306   * @relates error_code
307   * @since C++11
308   */
309#if __cpp_lib_three_way_comparison
310  [[nodiscard]]
311  inline strong_ordering
312  operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept
313  {
314    if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
315      return __c;
316    return __lhs.value() <=> __rhs.value();
317  }
318#else
319  inline bool
320  operator<(const error_code& __lhs, const error_code& __rhs) noexcept
321  {
322    return (__lhs.category() < __rhs.category()
323	    || (__lhs.category() == __rhs.category()
324		&& __lhs.value() < __rhs.value()));
325  }
326#endif
327
328  /** Write a std::error_code to an ostream.
329   *
330   * @relates error_code
331   * @since C++11
332   */
333  template<typename _CharT, typename _Traits>
334    basic_ostream<_CharT, _Traits>&
335    operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
336    { return (__os << __e.category().name() << ':' << __e.value()); }
337
338  /** Class error_condition
339   *
340   * This class represents error conditions that may be visible at an API
341   * boundary. Different `error_code` values that can occur within a library
342   * or module might map to the same `error_condition`.
343   *
344   * An `error_condition` represents something that the program can test for,
345   * and subsequently take appropriate action.
346   *
347   * @headerfile system_error
348   * @since C++11
349   */
350  class error_condition
351  {
352  public:
353    /// Initialize with a zero (no error) value and the generic category.
354    error_condition() noexcept
355    : _M_value(0), _M_cat(&generic_category()) { }
356
357    /// Initialize with the specified value and category.
358    error_condition(int __v, const error_category& __cat) noexcept
359    : _M_value(__v), _M_cat(&__cat) { }
360
361    template<typename _ErrorConditionEnum, typename = typename
362	 enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type>
363      error_condition(_ErrorConditionEnum __e) noexcept
364      {
365	using __adl_only::make_error_condition;
366	*this = make_error_condition(__e);
367      }
368
369    /// Set the value and category.
370    void
371    assign(int __v, const error_category& __cat) noexcept
372    {
373      _M_value = __v;
374      _M_cat = &__cat;
375    }
376
377    // DR 804.
378    template<typename _ErrorConditionEnum>
379      typename enable_if<is_error_condition_enum
380			 <_ErrorConditionEnum>::value, error_condition&>::type
381      operator=(_ErrorConditionEnum __e) noexcept
382      { return *this = make_error_condition(__e); }
383
384    /// Reset the value and category to the default-constructed state.
385    void
386    clear() noexcept
387    { assign(0, generic_category()); }
388
389    // C++11 19.5.3.4 observers
390
391    /// The error value.
392    [[__nodiscard__]]
393    int
394    value() const noexcept { return _M_value; }
395
396    /// The error category that this error belongs to.
397    [[__nodiscard__]]
398    const error_category&
399    category() const noexcept { return *_M_cat; }
400
401    /// The category's description of the value.
402    _GLIBCXX_DEFAULT_ABI_TAG
403    string
404    message() const
405    { return category().message(value()); }
406
407    /// Test whether `value()` is non-zero.
408    [[__nodiscard__]]
409    explicit operator bool() const noexcept
410    { return _M_value != 0; }
411
412    // DR 804.
413  private:
414    int 			_M_value;
415    const error_category* 	_M_cat;
416  };
417
418  // C++11 19.5.3.5 non-member functions
419
420  /** Create an `error_condition` representing a standard `errc` condition.
421   *
422   * The `std::errc` constants correspond to `errno` macros and so use the
423   * generic category.
424   *
425   * @relates error_condition
426   * @since C++11
427   */
428  [[__nodiscard__]]
429  inline error_condition
430  make_error_condition(errc __e) noexcept
431  { return error_condition(static_cast<int>(__e), generic_category()); }
432
433  // C++11 19.5.4 Comparison operators
434
435  /** Equality comparison for std::error_code.
436   *
437   * Returns true only if they have the same category and the same value.
438   *
439   * @relates error_condition
440   * @since C++11
441   */
442  [[__nodiscard__]]
443  inline bool
444  operator==(const error_code& __lhs, const error_code& __rhs) noexcept
445  {
446    return __lhs.category() == __rhs.category()
447	     && __lhs.value() == __rhs.value();
448  }
449
450  /** Equality comparison for std::error_code and std::error_condition.
451   *
452   * Uses each category's `equivalent` member function to check whether
453   * the values correspond to an equivalent error in that category.
454   *
455   * @relates error_condition
456   * @since C++11
457   */
458  [[__nodiscard__]]
459  inline bool
460  operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
461  {
462    return __lhs.category().equivalent(__lhs.value(), __rhs)
463	     || __rhs.category().equivalent(__lhs, __rhs.value());
464  }
465
466  /** Equality comparison for std::error_condition.
467   *
468   * Returns true only if they have the same category and the same value.
469   *
470   * @relates error_condition
471   * @since C++11
472   */
473  [[__nodiscard__]]
474  inline bool
475  operator==(const error_condition& __lhs,
476	     const error_condition& __rhs) noexcept
477  {
478    return __lhs.category() == __rhs.category()
479	     && __lhs.value() == __rhs.value();
480  }
481
482  /** Ordered comparison for std::error_condition.
483   *
484   * This defines a total order by comparing the categories, and then
485   * if they are equal comparing the values.
486   *
487   * @relates error_condition
488   * @since C++11
489   */
490#if __cpp_lib_three_way_comparison
491  [[nodiscard]]
492  inline strong_ordering
493  operator<=>(const error_condition& __lhs,
494	      const error_condition& __rhs) noexcept
495  {
496    if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0)
497      return __c;
498    return __lhs.value() <=> __rhs.value();
499  }
500#else
501  inline bool
502  operator<(const error_condition& __lhs,
503	    const error_condition& __rhs) noexcept
504  {
505    return (__lhs.category() < __rhs.category()
506	    || (__lhs.category() == __rhs.category()
507		&& __lhs.value() < __rhs.value()));
508  }
509
510  /// @relates error_condition
511  inline bool
512  operator==(const error_condition& __lhs, const error_code& __rhs) noexcept
513  {
514    return (__rhs.category().equivalent(__rhs.value(), __lhs)
515	    || __lhs.category().equivalent(__rhs, __lhs.value()));
516  }
517
518  /// @relates error_code
519  inline bool
520  operator!=(const error_code& __lhs, const error_code& __rhs) noexcept
521  { return !(__lhs == __rhs); }
522
523  /// @relates error_code
524  inline bool
525  operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept
526  { return !(__lhs == __rhs); }
527
528  /// @relates error_condition
529  inline bool
530  operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept
531  { return !(__lhs == __rhs); }
532
533  /// @relates error_condition
534  inline bool
535  operator!=(const error_condition& __lhs,
536	     const error_condition& __rhs) noexcept
537  { return !(__lhs == __rhs); }
538#endif // three_way_comparison
539  /// @}
540
541  /**
542   * @brief An exception type that includes an `error_code` value.
543   *
544   * Typically used to report errors from the operating system and other
545   * low-level APIs.
546   *
547   * @headerfile system_error
548   * @since C++11
549   * @ingroup exceptions
550   */
551  class system_error : public std::runtime_error
552  {
553  private:
554    error_code 	_M_code;
555
556  public:
557    system_error(error_code __ec = error_code())
558    : runtime_error(__ec.message()), _M_code(__ec) { }
559
560    system_error(error_code __ec, const string& __what)
561    : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { }
562
563    system_error(error_code __ec, const char* __what)
564    : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { }
565
566    system_error(int __v, const error_category& __ecat, const char* __what)
567    : system_error(error_code(__v, __ecat), __what) { }
568
569    system_error(int __v, const error_category& __ecat)
570    : runtime_error(error_code(__v, __ecat).message()),
571      _M_code(__v, __ecat) { }
572
573    system_error(int __v, const error_category& __ecat, const string& __what)
574    : runtime_error(__what + ": " + error_code(__v, __ecat).message()),
575      _M_code(__v, __ecat) { }
576
577#if __cplusplus >= 201103L
578    system_error (const system_error &) = default;
579    system_error &operator= (const system_error &) = default;
580#endif
581
582    virtual ~system_error() noexcept;
583
584    const error_code&
585    code() const noexcept { return _M_code; }
586  };
587
588_GLIBCXX_END_NAMESPACE_VERSION
589} // namespace
590
591#include <bits/functional_hash.h>
592
593namespace std _GLIBCXX_VISIBILITY(default)
594{
595_GLIBCXX_BEGIN_NAMESPACE_VERSION
596
597#ifndef _GLIBCXX_COMPATIBILITY_CXX0X
598  // DR 1182.
599  /// std::hash specialization for error_code.
600  /// @relates error_code
601  template<>
602    struct hash<error_code>
603    : public __hash_base<size_t, error_code>
604    {
605      size_t
606      operator()(const error_code& __e) const noexcept
607      {
608	const size_t __tmp = std::_Hash_impl::hash(__e.value());
609	return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
610      }
611    };
612#endif // _GLIBCXX_COMPATIBILITY_CXX0X
613
614#if __cplusplus >= 201703L
615  // DR 2686.
616  /// std::hash specialization for error_condition.
617  /// @relates error_condition
618  template<>
619    struct hash<error_condition>
620    : public __hash_base<size_t, error_condition>
621    {
622      size_t
623      operator()(const error_condition& __e) const noexcept
624      {
625	const size_t __tmp = std::_Hash_impl::hash(__e.value());
626	return std::_Hash_impl::__hash_combine(&__e.category(), __tmp);
627      }
628    };
629#endif
630
631_GLIBCXX_END_NAMESPACE_VERSION
632} // namespace
633
634#endif // C++11
635
636#endif // _GLIBCXX_SYSTEM_ERROR
637