1// <system_error> -*- C++ -*- 2 3// Copyright (C) 2007-2020 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 inline namespace _V2 { 79 80 /** Abstract base class for types defining a category of error codes. 81 * 82 * An error category defines a context that give meaning to the integer 83 * stored in an `error_code` or `error_condition` object. For example, 84 * the standard `errno` constants such a `EINVAL` and `ENOMEM` are 85 * associated with the "generic" category and other OS-specific error 86 * numbers are associated with the "system" category, but a user-defined 87 * category might give different meanings to the same numerical values. 88 */ 89 class error_category 90 { 91 public: 92 constexpr error_category() noexcept = default; 93 94 virtual ~error_category(); 95 96 error_category(const error_category&) = delete; 97 error_category& operator=(const error_category&) = delete; 98 99 virtual const char* 100 name() const noexcept = 0; 101 102 // We need two different virtual functions here, one returning a 103 // COW string and one returning an SSO string. Their positions in the 104 // vtable must be consistent for dynamic dispatch to work, but which one 105 // the name "message()" finds depends on which ABI the caller is using. 106#if _GLIBCXX_USE_CXX11_ABI 107 private: 108 _GLIBCXX_DEFAULT_ABI_TAG 109 virtual __cow_string 110 _M_message(int) const; 111 112 public: 113 _GLIBCXX_DEFAULT_ABI_TAG 114 virtual string 115 message(int) const = 0; 116#else 117 virtual string 118 message(int) const = 0; 119 120 private: 121 virtual __sso_string 122 _M_message(int) const; 123#endif 124 125 public: 126 virtual error_condition 127 default_error_condition(int __i) const noexcept; 128 129 virtual bool 130 equivalent(int __i, const error_condition& __cond) const noexcept; 131 132 virtual bool 133 equivalent(const error_code& __code, int __i) const noexcept; 134 135 bool 136 operator==(const error_category& __other) const noexcept 137 { return this == &__other; } 138 139#if __cpp_lib_three_way_comparison 140 strong_ordering 141 operator<=>(const error_category& __rhs) const noexcept 142 { return std::compare_three_way()(this, &__rhs); } 143#else 144 bool 145 operator!=(const error_category& __other) const noexcept 146 { return this != &__other; } 147 148 bool 149 operator<(const error_category& __other) const noexcept 150 { return less<const error_category*>()(this, &__other); } 151#endif 152 }; 153 154 // DR 890. 155 156 /// Error category for `errno` error codes. 157 _GLIBCXX_CONST const error_category& generic_category() noexcept; 158 159 /// Error category for other error codes defined by the OS. 160 _GLIBCXX_CONST const error_category& system_category() noexcept; 161 162 } // end inline namespace 163 164 error_code make_error_code(errc) noexcept; 165 166 /** Class error_code 167 * 168 * This class is a value type storing an integer error number and a 169 * category that gives meaning to the error number. Typically this is done 170 * close the the point where the error happens, to capture the original 171 * error value. 172 * 173 * An `error_code` object can be used to store the original error value 174 * emitted by some subsystem, with a category relevant to the subsystem. 175 * For example, errors from POSIX library functions can be represented by 176 * an `errno` value and the "generic" category, but errors from an HTTP 177 * library might be represented by an HTTP response status code (e.g. 404) 178 * and a custom category defined by the library. 179 */ 180 struct error_code 181 { 182 error_code() noexcept 183 : _M_value(0), _M_cat(&system_category()) { } 184 185 error_code(int __v, const error_category& __cat) noexcept 186 : _M_value(__v), _M_cat(&__cat) { } 187 188 template<typename _ErrorCodeEnum, typename = typename 189 enable_if<is_error_code_enum<_ErrorCodeEnum>::value>::type> 190 error_code(_ErrorCodeEnum __e) noexcept 191 { *this = make_error_code(__e); } 192 193 void 194 assign(int __v, const error_category& __cat) noexcept 195 { 196 _M_value = __v; 197 _M_cat = &__cat; 198 } 199 200 void 201 clear() noexcept 202 { assign(0, system_category()); } 203 204 // DR 804. 205 template<typename _ErrorCodeEnum> 206 typename enable_if<is_error_code_enum<_ErrorCodeEnum>::value, 207 error_code&>::type 208 operator=(_ErrorCodeEnum __e) noexcept 209 { return *this = make_error_code(__e); } 210 211 int 212 value() const noexcept { return _M_value; } 213 214 const error_category& 215 category() const noexcept { return *_M_cat; } 216 217 error_condition 218 default_error_condition() const noexcept; 219 220 _GLIBCXX_DEFAULT_ABI_TAG 221 string 222 message() const 223 { return category().message(value()); } 224 225 explicit operator bool() const noexcept 226 { return _M_value != 0; } 227 228 // DR 804. 229 private: 230 int _M_value; 231 const error_category* _M_cat; 232 }; 233 234 // 19.4.2.6 non-member functions 235 236 /// @relates error_code @{ 237 238 inline error_code 239 make_error_code(errc __e) noexcept 240 { return error_code(static_cast<int>(__e), generic_category()); } 241 242#if __cpp_lib_three_way_comparison 243 inline strong_ordering 244 operator<=>(const error_code& __lhs, const error_code& __rhs) noexcept 245 { 246 if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) 247 return __c; 248 return __lhs.value() <=> __rhs.value(); 249 } 250#else 251 inline bool 252 operator<(const error_code& __lhs, const error_code& __rhs) noexcept 253 { 254 return (__lhs.category() < __rhs.category() 255 || (__lhs.category() == __rhs.category() 256 && __lhs.value() < __rhs.value())); 257 } 258#endif 259 260 template<typename _CharT, typename _Traits> 261 basic_ostream<_CharT, _Traits>& 262 operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e) 263 { return (__os << __e.category().name() << ':' << __e.value()); } 264 265 /// @} 266 267 error_condition make_error_condition(errc) noexcept; 268 269 /** Class error_condition 270 * 271 * This class represents error conditions that may be visible at an API 272 * boundary. Different `error_code` values that can occur within a library 273 * or module might map to the same `error_condition`. 274 * 275 * An `error_condition` represents something that the program can test for, 276 * and subsequently take appropriate action. 277 */ 278 struct error_condition 279 { 280 error_condition() noexcept 281 : _M_value(0), _M_cat(&generic_category()) { } 282 283 error_condition(int __v, const error_category& __cat) noexcept 284 : _M_value(__v), _M_cat(&__cat) { } 285 286 template<typename _ErrorConditionEnum, typename = typename 287 enable_if<is_error_condition_enum<_ErrorConditionEnum>::value>::type> 288 error_condition(_ErrorConditionEnum __e) noexcept 289 { *this = make_error_condition(__e); } 290 291 void 292 assign(int __v, const error_category& __cat) noexcept 293 { 294 _M_value = __v; 295 _M_cat = &__cat; 296 } 297 298 // DR 804. 299 template<typename _ErrorConditionEnum> 300 typename enable_if<is_error_condition_enum 301 <_ErrorConditionEnum>::value, error_condition&>::type 302 operator=(_ErrorConditionEnum __e) noexcept 303 { return *this = make_error_condition(__e); } 304 305 void 306 clear() noexcept 307 { assign(0, generic_category()); } 308 309 // 19.4.3.4 observers 310 int 311 value() const noexcept { return _M_value; } 312 313 const error_category& 314 category() const noexcept { return *_M_cat; } 315 316 _GLIBCXX_DEFAULT_ABI_TAG 317 string 318 message() const 319 { return category().message(value()); } 320 321 explicit operator bool() const noexcept 322 { return _M_value != 0; } 323 324 // DR 804. 325 private: 326 int _M_value; 327 const error_category* _M_cat; 328 }; 329 330 // 19.4.3.6 non-member functions 331 332 /// Create an `error_condition` representing a standard `errc` condition. 333 /// @relates error_condition 334 inline error_condition 335 make_error_condition(errc __e) noexcept 336 { return error_condition(static_cast<int>(__e), generic_category()); } 337 338 // 19.4.4 Comparison operators 339 340 /// @relates error_code 341 inline bool 342 operator==(const error_code& __lhs, const error_code& __rhs) noexcept 343 { return (__lhs.category() == __rhs.category() 344 && __lhs.value() == __rhs.value()); } 345 346 /// @relates error_code 347 /// @relates error_condition 348 inline bool 349 operator==(const error_code& __lhs, const error_condition& __rhs) noexcept 350 { 351 return (__lhs.category().equivalent(__lhs.value(), __rhs) 352 || __rhs.category().equivalent(__lhs, __rhs.value())); 353 } 354 355 /// @relates error_condition 356 inline bool 357 operator==(const error_condition& __lhs, 358 const error_condition& __rhs) noexcept 359 { 360 return (__lhs.category() == __rhs.category() 361 && __lhs.value() == __rhs.value()); 362 } 363 364#if __cpp_lib_three_way_comparison 365 /// Define an ordering for error_condition objects. 366 /// @relates error_condition 367 inline strong_ordering 368 operator<=>(const error_condition& __lhs, 369 const error_condition& __rhs) noexcept 370 { 371 if (auto __c = __lhs.category() <=> __rhs.category(); __c != 0) 372 return __c; 373 return __lhs.value() <=> __rhs.value(); 374 } 375#else 376 /// Define an ordering for error_condition objects. 377 /// @relates error_condition 378 inline bool 379 operator<(const error_condition& __lhs, 380 const error_condition& __rhs) noexcept 381 { 382 return (__lhs.category() < __rhs.category() 383 || (__lhs.category() == __rhs.category() 384 && __lhs.value() < __rhs.value())); 385 } 386 387 /// @relates error_code 388 /// @relates error_condition 389 inline bool 390 operator==(const error_condition& __lhs, const error_code& __rhs) noexcept 391 { 392 return (__rhs.category().equivalent(__rhs.value(), __lhs) 393 || __lhs.category().equivalent(__rhs, __lhs.value())); 394 } 395 396 /// @relates error_code 397 inline bool 398 operator!=(const error_code& __lhs, const error_code& __rhs) noexcept 399 { return !(__lhs == __rhs); } 400 401 /// @relates error_code 402 /// @relates error_condition 403 inline bool 404 operator!=(const error_code& __lhs, const error_condition& __rhs) noexcept 405 { return !(__lhs == __rhs); } 406 407 /// @relates error_code 408 /// @relates error_condition 409 inline bool 410 operator!=(const error_condition& __lhs, const error_code& __rhs) noexcept 411 { return !(__lhs == __rhs); } 412 413 /// @relates error_condition 414 inline bool 415 operator!=(const error_condition& __lhs, 416 const error_condition& __rhs) noexcept 417 { return !(__lhs == __rhs); } 418#endif // three_way_comparison 419 420 /** 421 * @brief An exception type that includes an `error_code` value. 422 * 423 * Typically used to report errors from the operating system and other 424 * low-level APIs. 425 * 426 * @ingroup exceptions 427 */ 428 class system_error : public std::runtime_error 429 { 430 private: 431 error_code _M_code; 432 433 public: 434 system_error(error_code __ec = error_code()) 435 : runtime_error(__ec.message()), _M_code(__ec) { } 436 437 system_error(error_code __ec, const string& __what) 438 : runtime_error(__what + ": " + __ec.message()), _M_code(__ec) { } 439 440 system_error(error_code __ec, const char* __what) 441 : runtime_error(__what + (": " + __ec.message())), _M_code(__ec) { } 442 443 system_error(int __v, const error_category& __ecat, const char* __what) 444 : system_error(error_code(__v, __ecat), __what) { } 445 446 system_error(int __v, const error_category& __ecat) 447 : runtime_error(error_code(__v, __ecat).message()), 448 _M_code(__v, __ecat) { } 449 450 system_error(int __v, const error_category& __ecat, const string& __what) 451 : runtime_error(__what + ": " + error_code(__v, __ecat).message()), 452 _M_code(__v, __ecat) { } 453 454#if __cplusplus >= 201103L 455 system_error (const system_error &) = default; 456 system_error &operator= (const system_error &) = default; 457#endif 458 459 virtual ~system_error() noexcept; 460 461 const error_code& 462 code() const noexcept { return _M_code; } 463 }; 464 465_GLIBCXX_END_NAMESPACE_VERSION 466} // namespace 467 468#include <bits/functional_hash.h> 469 470namespace std _GLIBCXX_VISIBILITY(default) 471{ 472_GLIBCXX_BEGIN_NAMESPACE_VERSION 473 474#ifndef _GLIBCXX_COMPATIBILITY_CXX0X 475 // DR 1182. 476 /// std::hash specialization for error_code. 477 /// @relates error_code 478 template<> 479 struct hash<error_code> 480 : public __hash_base<size_t, error_code> 481 { 482 size_t 483 operator()(const error_code& __e) const noexcept 484 { 485 const size_t __tmp = std::_Hash_impl::hash(__e.value()); 486 return std::_Hash_impl::__hash_combine(&__e.category(), __tmp); 487 } 488 }; 489#endif // _GLIBCXX_COMPATIBILITY_CXX0X 490 491#if __cplusplus >= 201703L 492 // DR 2686. 493 /// std::hash specialization for error_condition. 494 /// @relates error_condition 495 template<> 496 struct hash<error_condition> 497 : public __hash_base<size_t, error_condition> 498 { 499 size_t 500 operator()(const error_condition& __e) const noexcept 501 { 502 const size_t __tmp = std::_Hash_impl::hash(__e.value()); 503 return std::_Hash_impl::__hash_combine(&__e.category(), __tmp); 504 } 505 }; 506#endif 507 508_GLIBCXX_END_NAMESPACE_VERSION 509} // namespace 510 511#endif // C++11 512 513#endif // _GLIBCXX_SYSTEM_ERROR 514