Skip to content

__is_trivially_equality_comparable(T) false positive when the defaulted operator is ineligible #89293

@AMP999

Description

@AMP999

Clang's __is_trivially_equality_comparable(T) builtin assumes that if a type has any defaulted trivial comparison operator, then all its comparison operators will be tantamount-to-trivial. That's a sane assumption... but only if the defaulted operator is actually eligible for the given T! If the defaulted operator is requires-clause'd away, then we shouldn't consider it relevant to the question of triviality at all.
https://godbolt.org/z/3hs4EKPKT

template<bool B>
struct S {
    int i;
    bool operator==(const S&) const requires B = default;
    bool operator==(const S& rhs) const { return (i % 3) == (rhs.i % 3); }
};
static_assert(__is_trivially_equality_comparable(S<true>)); // OK
static_assert(not __is_trivially_equality_comparable(S<false>)); // Oops, this line assert-fails

This compiler misbehavior causes libc++ to miscompile std::equal:
https://godbolt.org/z/YPfEG6cv9

    S<false> a[] = {1,2,3};
    S<false> b[] = {4,5,6};
    return std::equal(a, a+3, b, b+3);
      // should be true, not false

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions