https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86750

            Bug ID: 86750
           Summary: libstdc++ std::system_category() does not map onto
                    std::generic_category()
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: s_gccbugzilla at nedprod dot com
  Target Milestone: ---

Got bitten by this yet again today in Boost.Outcome and the P1031 LLFIO
reference implementation, so despite it being already reported at #60555, I'd
like to get this fixed already. It's been four years of writing libstdc++
specific workarounds, no fix on the horizon :(

This should not fail. It does on libstdc++ 9.0 trunk:

```
#include <cassert>
#include <iostream>
#include <system_error>

bool test()
{
    return std::error_code(EEXIST, std::system_category()) ==
std::errc::file_exists;
}

int main()
{
    std::cout << test() << std::endl;
    assert(test() == true);
    return 0;
}
```

https://wandbox.org/permlink/jYpIIMlXKJ4zX3ud


Jonathan says in #60555 'The standard also says "What constitutes
correspondence for any given operating system is unspecified."' for mapping
POSIX error codes onto generic codes. However the full text for
system_category() is actually:

```
If the argument ev corresponds to a POSIX errno value posv, the function shall
return error_condition(posv, generic_category()). Otherwise, the function shall
return error_condition(ev, system_category()). What constitutes correspondence
for any given operating system is unspecified.

[ Note: The number of potential system error codes is large and unbounded, and
some may not correspond to any POSIX errno value. Thus implementations are
given latitude in determining correspondence. — end note ]
```

So what the standard means here is that on POSIX systems, system_category is by
definition a superset of generic_category. All generic_category codes are
guaranteed to map onto system_category if the system is POSIX compliant. The
reverse is not the case, because the POSIX implementation may have proprietary
error codes which have no valid mapping in generic_category.

My test program above compares a system category error code of EEXIST - which
is a POSIX error code - to the generic code errc::file_exists. This is supposed
to return true. See the equivalent Boost.System based test example
https://wandbox.org/permlink/FQ9u6DtTkw2Uno1A and it indeed works correctly.

Windows, despite not being POSIX, also gets this right:

```
#include <cassert>
#include <iostream>
#include <system_error>

#include <windows.h>

bool test()
{
    return std::error_code(ERROR_FILE_EXISTS, std::system_category()) ==
std::errc::file_exists;
}

int main()
{
    std::cout << test() << std::endl;
    assert(test() == true);
    return 0;
}
```

Please fix libstdc++.

Reply via email to