https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66438
Bug ID: 66438
Summary: libstdc++ 5.1 broke binary compat with old code using
std::error_category
Product: gcc
Version: 5.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: libstdc++
Assignee: unassigned at gcc dot gnu.org
Reporter: foom at fuhm dot net
Target Milestone: ---
If you compile this program with GCC 4.9, but you have libstdc++ version 5.1
installed on your system. (E.g., this is the case for me because I'm using
Debian unstable).
#include <system_error>
int main() {
std::error_code x = make_error_code(std::errc::no_such_file_or_directory);
std::error_condition e = std::errc::no_such_file_or_directory;
return x == e;
}
Then running it will return 0 instead of 1, like it should, (and did, with
libstdc++ 4.9 installed).
So, the thing to note, is that both "x" and "e" here have a category() of
_ZSt16generic_categoryv() as their category instance -- NOT
_ZNSt3_V216generic_categoryEv(), because it was built against the old headers.
(This seems to be as intended.)
Going through the calls, first we have this from
libstdc++-v3/include/std/system_error:
inline bool
operator==(const error_code& __lhs, const error_condition& __rhs) noexcept
{
return (__lhs.category().equivalent(__lhs.value(), __rhs)
|| __rhs.category().equivalent(__lhs, __rhs.value()));
}
which calls, from libstdc++-v3/src/c++11/compatibility-c++0x.cc:
bool
error_category::equivalent(int __i,
const error_condition& __cond) const noexcept
{ return default_error_condition(__i) == __cond; }
which calls, from the same file:
error_condition
error_category::default_error_condition(int __i) const noexcept
{
if (*this == system_category())
return error_condition(__i, _V2::system_category());
return error_condition(__i, _V2::generic_category());
}
which returns a _V2::generic_category() object. Oops. Now we're in big trouble!
Then, back to error_category::equivalent, where it calls, from
libstdc++-v3/include/std/system_error:
inline bool
operator==(const error_condition& __lhs,
const error_condition& __rhs) noexcept
{
return (__lhs.category() == __rhs.category()
&& __lhs.value() == __rhs.value());
}
Which fails, because __lhs.category() is the V2 generic_category, and
__rhs.category() is the "V1" generic_category.