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_GLIBCXX_BEGIN_INLINE_ABI_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 192_GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) 193 194 /** @addtogroup diagnostics 195 * @{ 196 */ 197 198namespace __adl_only 199{ 200 void make_error_code() = delete; 201 void make_error_condition() = delete; 202} 203 204 /** Class error_code 205 * 206 * This class is a value type storing an integer error number and a 207 * category that gives meaning to the error number. Typically this is done 208 * close the the point where the error happens, to capture the original 209 * error value. 210 * 211 * An `error_code` object can be used to store the original error value 212 * emitted by some subsystem, with a category relevant to the subsystem. 213 * For example, errors from POSIX library functions can be represented by 214 * an `errno` value and the "generic" category, but errors from an HTTP 215 * library might be represented by an HTTP response status code (e.g. 404) 216 * and a custom category defined by the library. 217 * 218 * @headerfile system_error 219 * @since C++11 220 */ 221 class error_code 222 { 223 public: 224 error_code() noexcept 225 : _M_value(0), _M_cat(&system_category()) { } 226 227 error_code(int __v, const error_category& __cat) noexcept 228 : _M_value(__v), _M_cat(&__cat) { } 229 230 template<typename _ErrorCodeEnum, typename = typename 231 enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type> 232 error_code(_ErrorCodeEnum __e) noexcept 233 { 234 using __adl_only::make_error_code; 235 *this = make_error_code(__e); 236 } 237 238 void 239 assign(int __v, const error_category& __cat) noexcept 240 { 241 _M_value = __v; 242 _M_cat = &__cat; 243 } 244 245 void 246 clear() noexcept 247 { assign(0, system_category()); } 248 249 // DR 804. 250 template<typename _ErrorCodeEnum> 251 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value, 252 error_code&>::type 253 operator=(_ErrorCodeEnum __e) noexcept 254 { return *this = make_error_code(__e); } 255 256 /// The error value. 257 [[__nodiscard__]] 258 int 259 value() const noexcept { return _M_value; } 260 261 /// The error category that this error belongs to. 262 [[__nodiscard__]] 263 const error_category& 264 category() const noexcept { return *_M_cat; } 265 266 /// An `error_condition` for this error's category and value. 267 error_condition 268 default_error_condition() const noexcept; 269 270 /// The category's description of the value. 271 _GLIBCXX_DEFAULT_ABI_TAG 272 string 273 message() const 274 { return category().message(value()); } 275 276 /// Test whether `value()` is non-zero. 277 [[__nodiscard__]] 278 explicit operator bool() const noexcept 279 { return _M_value != 0; } 280 281 // DR 804. 282 private: 283 int _M_value; 284 const error_category* _M_cat; 285 }; 286 287 // C++11 19.5.2.5 non-member functions 288 289 /** Create an `error_code` representing a standard `errc` condition. 290 * 291 * The `std::errc` constants correspond to `errno` macros and so use the 292 * generic category. 293 * 294 * @relates error_code 295 * @since C++11 296 */ 297 [[__nodiscard__]] 298 inline error_code 299 make_error_code(errc __e) noexcept 300 { return error_code(static_cast<int>(__e), generic_category()); } 301 302 /** Ordered comparison for std::error_code. 303 * 304 * This defines a total order by comparing the categories, and then 305 * if they are equal comparing the values. 306 * 307 * @relates error_code 308 * @since C++11 309 */ 310#if __cpp_lib_three_way_comparison 311 [[nodiscard]] 312 inline strong_ordering 313 operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept 314 { 315 if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) 316 return __c; 317 return __lhs.value() <=> __rhs.value(); 318 } 319#else 320 inline bool 321 operator<(const error_code& __lhs, const error_code& __rhs) noexcept 322 { 323 return (__lhs.category() < __rhs.category() 324 || (__lhs.category() == __rhs.category() 325 && __lhs.value() < __rhs.value())); 326 } 327#endif 328 329 /** Write a std::error_code to an ostream. 330 * 331 * @relates error_code 332 * @since C++11 333 */ 334 template<typename _CharT, typename _Traits> 335 basic_ostream<_CharT, _Traits>& 336 operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e) 337 { return (__os << __e.category().name() << ':' << __e.value()); } 338 339 /** Class error_condition 340 * 341 * This class represents error conditions that may be visible at an API 342 * boundary. Different `error_code` values that can occur within a library 343 * or module might map to the same `error_condition`. 344 * 345 * An `error_condition` represents something that the program can test for, 346 * and subsequently take appropriate action. 347 * 348 * @headerfile system_error 349 * @since C++11 350 */ 351 class error_condition 352 { 353 public: 354 /// Initialize with a zero (no error) value and the generic category. 355 error_condition() noexcept 356 : _M_value(0), _M_cat(&generic_category()) { } 357 358 /// Initialize with the specified value and category. 359 error_condition(int __v, const error_category& __cat) noexcept 360 : _M_value(__v), _M_cat(&__cat) { } 361 362 template<typename _ErrorConditionEnum, typename = typename 363 enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type> 364 error_condition(_ErrorConditionEnum __e) noexcept 365 { 366 using __adl_only::make_error_condition; 367 *this = make_error_condition(__e); 368 } 369 370 /// Set the value and category. 371 void 372 assign(int __v, const error_category& __cat) noexcept 373 { 374 _M_value = __v; 375 _M_cat = &__cat; 376 } 377 378 // DR 804. 379 template<typename _ErrorConditionEnum> 380 typename enable_if<is_error_condition_enum 381 <_ErrorConditionEnum>::value, error_condition&>::type 382 operator=(_ErrorConditionEnum __e) noexcept 383 { return *this = make_error_condition(__e); } 384 385 /// Reset the value and category to the default-constructed state. 386 void 387 clear() noexcept 388 { assign(0, generic_category()); } 389 390 // C++11 19.5.3.4 observers 391 392 /// The error value. 393 [[__nodiscard__]] 394 int 395 value() const noexcept { return _M_value; } 396 397 /// The error category that this error belongs to. 398 [[__nodiscard__]] 399 const error_category& 400 category() const noexcept { return *_M_cat; } 401 402 /// The category's description of the value. 403 _GLIBCXX_DEFAULT_ABI_TAG 404 string 405 message() const 406 { return category().message(value()); } 407 408 /// Test whether `value()` is non-zero. 409 [[__nodiscard__]] 410 explicit operator bool() const noexcept 411 { return _M_value != 0; } 412 413 // DR 804. 414 private: 415 int _M_value; 416 const error_category* _M_cat; 417 }; 418 419 // C++11 19.5.3.5 non-member functions 420 421 /** Create an `error_condition` representing a standard `errc` condition. 422 * 423 * The `std::errc` constants correspond to `errno` macros and so use the 424 * generic category. 425 * 426 * @relates error_condition 427 * @since C++11 428 */ 429 [[__nodiscard__]] 430 inline error_condition 431 make_error_condition(errc __e) noexcept 432 { return error_condition(static_cast<int>(__e), generic_category()); } 433 434 // C++11 19.5.4 Comparison operators 435 436 /** Equality comparison for std::error_code. 437 * 438 * Returns true only if they have the same category and the same value. 439 * 440 * @relates error_condition 441 * @since C++11 442 */ 443 [[__nodiscard__]] 444 inline bool 445 operator==(const error_code& __lhs, const error_code& __rhs) noexcept 446 { 447 return __lhs.category() == __rhs.category() 448 && __lhs.value() == __rhs.value(); 449 } 450 451 /** Equality comparison for std::error_code and std::error_condition. 452 * 453 * Uses each category's `equivalent` member function to check whether 454 * the values correspond to an equivalent error in that category. 455 * 456 * @relates error_condition 457 * @since C++11 458 */ 459 [[__nodiscard__]] 460 inline bool 461 operator==(const error_code& __lhs, const error_condition& __rhs) noexcept 462 { 463 return __lhs.category().equivalent(__lhs.value(), __rhs) 464 || __rhs.category().equivalent(__lhs, __rhs.value()); 465 } 466 467 /** Equality comparison for std::error_condition. 468 * 469 * Returns true only if they have the same category and the same value. 470 * 471 * @relates error_condition 472 * @since C++11 473 */ 474 [[__nodiscard__]] 475 inline bool 476 operator==(const error_condition& __lhs, 477 const error_condition& __rhs) noexcept 478 { 479 return __lhs.category() == __rhs.category() 480 && __lhs.value() == __rhs.value(); 481 } 482 483 /** Ordered comparison for std::error_condition. 484 * 485 * This defines a total order by comparing the categories, and then 486 * if they are equal comparing the values. 487 * 488 * @relates error_condition 489 * @since C++11 490 */ 491#if __cpp_lib_three_way_comparison 492 [[nodiscard]] 493 inline strong_ordering 494 operator<=>(const error_condition& __lhs, 495 const error_condition& __rhs) noexcept 496 { 497 if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) 498 return __c; 499 return __lhs.value() <=> __rhs.value(); 500 } 501#else 502 inline bool 503 operator<(const error_condition& __lhs, 504 const error_condition& __rhs) noexcept 505 { 506 return (__lhs.category() < __rhs.category() 507 || (__lhs.category() == __rhs.category() 508 && __lhs.value() < __rhs.value())); 509 } 510 511 /// @relates error_condition 512 inline bool 513 operator==(const error_condition& __lhs, const error_code& __rhs) noexcept 514 { 515 return (__rhs.category().equivalent(__rhs.value(), __lhs) 516 || __lhs.category().equivalent(__rhs, __lhs.value())); 517 } 518 519 /// @relates error_code 520 inline bool 521 operator!=(const error_code& __lhs, const error_code& __rhs) noexcept 522 { return !(__lhs == __rhs); } 523 524 /// @relates error_code 525 inline bool 526 operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept 527 { return !(__lhs == __rhs); } 528 529 /// @relates error_condition 530 inline bool 531 operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept 532 { return !(__lhs == __rhs); } 533 534 /// @relates error_condition 535 inline bool 536 operator!=(const error_condition& __lhs, 537 const error_condition& __rhs) noexcept 538 { return !(__lhs == __rhs); } 539#endif // three_way_comparison 540 /// @} 541 542 /** 543 * @brief An exception type that includes an `error_code` value. 544 * 545 * Typically used to report errors from the operating system and other 546 * low-level APIs. 547 * 548 * @headerfile system_error 549 * @since C++11 550 * @ingroup exceptions 551 */ 552 class system_error : public std::runtime_error 553 { 554 private: 555 error_code _M_code; 556 557 public: 558 system_error(error_code __ec = error_code()) 559 : runtime_error(__ec.message()), _M_code(__ec) { } 560 561 system_error(error_code __ec, const string& __what) 562 : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { } 563 564 system_error(error_code __ec, const char* __what) 565 : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { } 566 567 system_error(int __v, const error_category& __ecat, const char* __what) 568 : system_error(error_code(__v, __ecat), __what) { } 569 570 system_error(int __v, const error_category& __ecat) 571 : runtime_error(error_code(__v, __ecat).message()), 572 _M_code(__v, __ecat) { } 573 574 system_error(int __v, const error_category& __ecat, const string& __what) 575 : runtime_error(__what + ": " + error_code(__v, __ecat).message()), 576 _M_code(__v, __ecat) { } 577 578#if __cplusplus >= 201103L 579 system_error (const system_error &) = default; 580 system_error &operator= (const system_error &) = default; 581#endif 582 583 virtual ~system_error() noexcept; 584 585 const error_code& 586 code() const noexcept { return _M_code; } 587 }; 588 589_GLIBCXX_END_NAMESPACE_VERSION 590} // namespace 591 592#include <bits/functional_hash.h> 593 594namespace std _GLIBCXX_VISIBILITY(default) 595{ 596_GLIBCXX_BEGIN_NAMESPACE_VERSION 597 598#ifndef _GLIBCXX_COMPATIBILITY_CXX0X 599 // DR 1182. 600 /// std::hash specialization for error_code. 601 /// @relates error_code 602 template<> 603 struct hash<error_code> 604 : public __hash_base<size_t, error_code> 605 { 606 size_t 607 operator()(const error_code& __e) const noexcept 608 { 609 const size_t __tmp = std::_Hash_impl::hash(__e.value()); 610 return std::_Hash_impl::__hash_combine(&__e.category(), __tmp); 611 } 612 }; 613#endif // _GLIBCXX_COMPATIBILITY_CXX0X 614 615#if __cplusplus >= 201703L 616 // DR 2686. 617 /// std::hash specialization for error_condition. 618 /// @relates error_condition 619 template<> 620 struct hash<error_condition> 621 : public __hash_base<size_t, error_condition> 622 { 623 size_t 624 operator()(const error_condition& __e) const noexcept 625 { 626 const size_t __tmp = std::_Hash_impl::hash(__e.value()); 627 return std::_Hash_impl::__hash_combine(&__e.category(), __tmp); 628 } 629 }; 630#endif 631 632_GLIBCXX_END_NAMESPACE_VERSION 633} // namespace 634 635#endif // C++11 636 637#endif // _GLIBCXX_SYSTEM_ERROR 638