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