diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b8532c280db02..283babfe25c07 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,13 @@ +2018-08-01 Jonathan Wakely + + PR libstdc++/60555 + * src/c++11/system_error.cc + (system_error_category::default_error_condition): New override to + check for POSIX errno values. + * testsuite/19_diagnostics/error_category/generic_category.cc: New + * testsuite/19_diagnostics/error_category/system_category.cc: New + test. + 2018-07-31 Jonathan Wakely PR libstdc++/86751 diff --git a/libstdc++-v3/src/c++11/system_error.cc b/libstdc++-v3/src/c++11/system_error.cc index c6549fcb4e08e..82b4cb5f98c6d 100644 --- a/libstdc++-v3/src/c++11/system_error.cc +++ b/libstdc++-v3/src/c++11/system_error.cc @@ -29,6 +29,7 @@ #include #include #include +#include #undef __sso_string namespace @@ -65,6 +66,260 @@ namespace // _GLIBCXX_HAVE_STRERROR_L, strerror_l(i, cloc) return string(strerror(i)); } + + virtual std::error_condition + default_error_condition(int ev) const noexcept + { + switch (ev) + { + // List of errno macros from [cerrno.syn]. + // C11 only defines EDOM, EILSEQ and ERANGE, the rest are from POSIX. + // They expand to integer constant expressions with type int, + // and distinct positive values, suitable for use in #if directives. + // POSIX adds more macros (but they're not defined on all targets, + // see config/os/*/error_constants.h), and POSIX allows + // EAGAIN == EWOULDBLOCK and ENOTSUP == EOPNOTSUPP. + +#ifdef E2BIG + case E2BIG: +#endif +#ifdef EACCES + case EACCES: +#endif +#ifdef EADDRINUSE + case EADDRINUSE: +#endif +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: +#endif +#ifdef EAFNOSUPPORT + case EAFNOSUPPORT: +#endif +#ifdef EAGAIN + case EAGAIN: +#endif +#ifdef EALREADY + case EALREADY: +#endif +#ifdef EBADF + case EBADF: +#endif +#ifdef EBADMSG + case EBADMSG: +#endif +#ifdef EBUSY + case EBUSY: +#endif +#ifdef ECANCELED + case ECANCELED: +#endif +#ifdef ECHILD + case ECHILD: +#endif +#ifdef ECONNABORTED + case ECONNABORTED: +#endif +#ifdef ECONNREFUSED + case ECONNREFUSED: +#endif +#ifdef ECONNRESET + case ECONNRESET: +#endif +#ifdef EDEADLK + case EDEADLK: +#endif +#ifdef EDESTADDRREQ + case EDESTADDRREQ: +#endif + case EDOM: +#ifdef EEXIST + case EEXIST: +#endif +#ifdef EFAULT + case EFAULT: +#endif +#ifdef EFBIG + case EFBIG: +#endif +#ifdef EHOSTUNREACH + case EHOSTUNREACH: +#endif +#ifdef EIDRM + case EIDRM: +#endif + case EILSEQ: +#ifdef EINPROGRESS + case EINPROGRESS: +#endif +#ifdef EINTR + case EINTR: +#endif +#ifdef EINVAL + case EINVAL: +#endif +#ifdef EIO + case EIO: +#endif +#ifdef EISCONN + case EISCONN: +#endif +#ifdef EISDIR + case EISDIR: +#endif +#ifdef ELOOP + case ELOOP: +#endif +#ifdef EMFILE + case EMFILE: +#endif +#ifdef EMLINK + case EMLINK: +#endif +#ifdef EMSGSIZE + case EMSGSIZE: +#endif +#ifdef ENAMETOOLONG + case ENAMETOOLONG: +#endif +#ifdef ENETDOWN + case ENETDOWN: +#endif +#ifdef ENETRESET + case ENETRESET: +#endif +#ifdef ENETUNREACH + case ENETUNREACH: +#endif +#ifdef ENFILE + case ENFILE: +#endif +#ifdef ENOBUFS + case ENOBUFS: +#endif +#ifdef ENODATA + case ENODATA: +#endif +#ifdef ENODEV + case ENODEV: +#endif +#ifdef ENOENT + case ENOENT: +#endif +#ifdef ENOEXEC + case ENOEXEC: +#endif +#ifdef ENOLCK + case ENOLCK: +#endif +#ifdef ENOLINK + case ENOLINK: +#endif +#ifdef ENOMEM + case ENOMEM: +#endif +#ifdef ENOMSG + case ENOMSG: +#endif +#ifdef ENOPROTOOPT + case ENOPROTOOPT: +#endif +#ifdef ENOSPC + case ENOSPC: +#endif +#ifdef ENOSR + case ENOSR: +#endif +#ifdef ENOSTR + case ENOSTR: +#endif +#ifdef ENOSYS + case ENOSYS: +#endif +#ifdef ENOTCONN + case ENOTCONN: +#endif +#ifdef ENOTDIR + case ENOTDIR: +#endif +#ifdef ENOTEMPTY + case ENOTEMPTY: +#endif +#ifdef ENOTRECOVERABLE + case ENOTRECOVERABLE: +#endif +#ifdef ENOTSOCK + case ENOTSOCK: +#endif +#ifdef ENOTSUP + case ENOTSUP: +#endif +#ifdef ENOTTY + case ENOTTY: +#endif +#ifdef ENXIO + case ENXIO: +#endif +#if defined EOPNOTSUPP && (!defined ENOTSUP || EOPNOTSUPP != ENOTSUP) + case EOPNOTSUPP: +#endif +#ifdef EOVERFLOW + case EOVERFLOW: +#endif +#ifdef EOWNERDEAD + case EOWNERDEAD: +#endif +#ifdef EPERM + case EPERM: +#endif +#ifdef EPIPE + case EPIPE: +#endif +#ifdef EPROTO + case EPROTO: +#endif +#ifdef EPROTONOSUPPORT + case EPROTONOSUPPORT: +#endif +#ifdef EPROTOTYPE + case EPROTOTYPE: +#endif + case ERANGE: +#ifdef EROFS + case EROFS: +#endif +#ifdef ESPIPE + case ESPIPE: +#endif +#ifdef ESRCH + case ESRCH: +#endif +#ifdef ETIME + case ETIME: +#endif +#ifdef ETIMEDOUT + case ETIMEDOUT: +#endif +#ifdef ETXTBSY + case ETXTBSY: +#endif +#if defined EWOULDBLOCK && (!defined EAGAIN || EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif +#ifdef EXDEV + case EXDEV: +#endif + return std::error_condition(ev, std::generic_category()); + + /* Additional system-dependent mappings from non-standard error codes + * to one of the POSIX values above would go here, e.g. + case EBLAH: + return std::error_condition(EINVAL, std::generic_category()); + */ + + default: + return std::error_condition(ev, std::system_category()); + } + } }; const generic_error_category generic_category_instance{}; diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/generic_category.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/generic_category.cc new file mode 100644 index 0000000000000..64881f44ca039 --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/generic_category.cc @@ -0,0 +1,69 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } + +#include +#include +#include + +void +test01() +{ + const char* name = std::generic_category().name(); + VERIFY( name == std::string("generic") ); +} + +void +test02() +{ + const std::error_category& cat = std::generic_category(); + std::error_condition cond; + + cond = cat.default_error_condition(EBADF); + VERIFY( cond.value() == EBADF ); + VERIFY( cond == std::errc::bad_file_descriptor ); + VERIFY( cond.category() == std::generic_category() ); + cond = cat.default_error_condition(EACCES); + VERIFY( cond.value() == EACCES ); + VERIFY( cond == std::errc::permission_denied ); + VERIFY( cond.category() == std::generic_category() ); + + // PR libstdc++/60555 + VERIFY( std::error_code(EBADF, cat) == std::errc::bad_file_descriptor ); + VERIFY( std::error_code(EACCES, cat) == std::errc::permission_denied ); +} + +void +test03() +{ + // set "C" locale to get expected message + auto loc = std::locale::global(std::locale::classic()); + + std::string msg = std::generic_category().message(EBADF); + VERIFY( msg.find("file") != std::string::npos ); + + std::locale::global(loc); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc new file mode 100644 index 0000000000000..6076d73551304 --- /dev/null +++ b/libstdc++-v3/testsuite/19_diagnostics/error_category/system_category.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-do run { target c++11 } } + +#include +#include +#include + +void +test01() +{ + const char* name = std::system_category().name(); + VERIFY( name == std::string("system") ); +} + +void +test02() +{ + const std::error_category& cat = std::system_category(); + std::error_condition cond; + + cond = cat.default_error_condition(EBADF); + VERIFY( cond.value() == EBADF ); + VERIFY( cond == std::errc::bad_file_descriptor ); + VERIFY( cond.category() == std::generic_category() ); + cond = cat.default_error_condition(EACCES); + VERIFY( cond.value() == EACCES ); + VERIFY( cond == std::errc::permission_denied ); + VERIFY( cond.category() == std::generic_category() ); + + // All POSIX errno values are positive: + cond = cat.default_error_condition(-1); + VERIFY( cond.value() == -1 ); + VERIFY( cond.category() == cat ); + cond = cat.default_error_condition(-99); + VERIFY( cond.value() == -99 ); + VERIFY( cond.category() == cat ); + + // PR libstdc++/60555 + VERIFY( std::error_code(EBADF, cat) == std::errc::bad_file_descriptor ); + VERIFY( std::error_code(EACCES, cat) == std::errc::permission_denied ); +} + +void +test03() +{ + // set "C" locale to get expected message + auto loc = std::locale::global(std::locale::classic()); + + std::string msg = std::system_category().message(EBADF); + VERIFY( msg.find("file") != std::string::npos ); + + std::locale::global(loc); +} + +int +main() +{ + test01(); + test02(); + test03(); +}