+2018-08-01 Jonathan Wakely <jwakely@redhat.com>
+
+ 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 <jwakely@redhat.com>
PR libstdc++/86751
#include <system_error>
#include <bits/functexcept.h>
#include <limits>
+#include <errno.h>
#undef __sso_string
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{};
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <system_error>
+#include <locale>
+#include <testsuite_hooks.h>
+
+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();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+
+#include <system_error>
+#include <locale>
+#include <testsuite_hooks.h>
+
+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();
+}