Default comparison operator gives wrong result when constexpr

Viewed 108

I was testing the new feature of C++20 to automatically generate comparison operators and I found a weird case when the default operator appears to give a wrong result.

It happens only with gcc and only if the operator is declared as constexpr.

The following code:

#include <iostream>

struct Foo
{
    int foo;
    constexpr bool operator==(const Foo&) const = default;
};

struct Bar : public Foo
{
    constexpr bool operator==(const Bar&) const = default;
};

int main()
{
    const Foo foo0{5};
    const Foo foo1{0};
    std::cout << "Foo: {" << foo0.foo << "} == {" << foo1.foo << "} => " << ((foo0 == foo1) ? "true" : "false") << std::endl;

    const Bar bar0{5};
    const Bar bar1{0};
    std::cout << "Bar: {" << bar0.foo << "} == {" << bar1.foo << "} => " << ((bar0 == bar1) ? "true" : "false") << std::endl;

    return 0;
}

when compiled with gcc gives:

Foo: {5} == {0} => false
Bar: {5} == {0} => true

but when compiled with clang gives:

Foo: {5} == {0} => false
Bar: {5} == {0} => false

Compiler Explorer link: https://godbolt.org/z/vbzo35an5

I'm assuming it's a bug in gcc but I don't know all the quirks of the language so I've decided to ask here before reporting it.

1 Answers

Yes, the code as written ought to work, so this is a GCC bug. The default operator== is expected to do an equality comparison of all the subobjects, not just the member subobjects.

You can see from the assembly output that GCC 11.1 produces the same comparison operator code for Bar as it would for a struct with no subobjects.

Related