This is an archive of the discontinued LLVM Phabricator instance.

[clang] Add `clang::equality_operator_compares_members_lexicographically`
AbandonedPublic

Authored by philnik on May 27 2023, 9:05 PM.

Details

Reviewers
aaron.ballman
erichkeane
Group Reviewers
Restricted Project
Summary

This attribute is equivalent to a defaulted member equality comparison for the purposes of __is_trivially_equality_comparable. The difference is that it doesn't try to do ADL calls when instantiating a class template. We encountered this problem while trying to make classes in libc++ trivially equality comparable. It can be used to guarantee that enums are trivially equality comparable (which is more of a bonus than a good reason to add this attribute).

Diff Detail

Event Timeline

philnik created this revision.May 27 2023, 9:05 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 27 2023, 9:05 PM
Herald added a subscriber: dschuff. · View Herald Transcript
philnik requested review of this revision.May 27 2023, 9:05 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 27 2023, 9:05 PM

If anybody has a better name for this I'm all ears.

erichkeane added a reviewer: Restricted Project.May 30 2023, 7:05 AM

I'm a little dense today perhaps, but I don't get the use case for this? Can you ELI-EWG? Is this an attribute we expect our users to use? The name is horrifyingly long for users to use, but perhaps that is a good thing.

clang/include/clang/Basic/AttrDocs.td
541–542

Unrelated changes. I realize your editor probably does this, please don't have it do it on this file.

3531

I'm a little dense today perhaps, but I don't get the use case for this? Can you ELI-EWG? Is this an attribute we expect our users to use? The name is horrifyingly long for users to use, but perhaps that is a good thing.

This is useful for libraries which have ADL requirements. Something like

template <class T>
struct Holder {
  T v;
};

struct Incomplete;

template <class T>
class TupleImpl {
  T v;

  bool operator==(const TupleImpl&) const = default;
};

template <class T>
class Tuple : public TupleImpl<T> {
  bool operator==(const Tuple&) const = default; // ADL call here
};

void func() {
  Tuple<Holder<Incomplete>*> f; // Instantiation fails because Incomplete isn't defined
}

has to work for std::tuple etc. to make them __is_trivially_equality_comparable, but the defaulted operator== will always try ADL (at least that's my understanding). To not make ADL calls, this attribute can be used instead, which basically say "trust me, my operator== does what the defaulted one would do".

Not sure what you mean by "Can you ELI-EWG?".
I agree that the name isn't great, but I couldn't come up with anything better that is still descriptive, and this attribute will probably only be used by very few libraries anyways (maybe just libc++, since this is pure QoI). As I said in the attribute description, the defaulted operator should be used if possible (which is probably the case in 99.9% of use cases).

(Note to self: maybe add the example as a test)

I'm a little dense today perhaps, but I don't get the use case for this? Can you ELI-EWG? Is this an attribute we expect our users to use? The name is horrifyingly long for users to use, but perhaps that is a good thing.

This is useful for libraries which have ADL requirements. Something like

template <class T>
struct Holder {
  T v;
};

struct Incomplete;

template <class T>
class TupleImpl {
  T v;

  bool operator==(const TupleImpl&) const = default;
};

template <class T>
class Tuple : public TupleImpl<T> {
  bool operator==(const Tuple&) const = default; // ADL call here
};

void func() {
  Tuple<Holder<Incomplete>*> f; // Instantiation fails because Incomplete isn't defined
}

has to work for std::tuple etc. to make them __is_trivially_equality_comparable, but the defaulted operator== will always try ADL (at least that's my understanding). To not make ADL calls, this attribute can be used instead, which basically say "trust me, my operator== does what the defaulted one would do".

Not sure what you mean by "Can you ELI-EWG?".
I agree that the name isn't great, but I couldn't come up with anything better that is still descriptive, and this attribute will probably only be used by very few libraries anyways (maybe just libc++, since this is pure QoI). As I said in the attribute description, the defaulted operator should be used if possible (which is probably the case in 99.9% of use cases).

(Note to self: maybe add the example as a test)

ELI-EWG: "Explain-like-I'm Evolution Working Group" :) Its a touch of a joke, there is a common reddit 'ELI5' (Explain like I'm 5), so I'm equating the C++ EWG to needing 5-year-old-esque explanations.

I can see the value to that I guess? I don't have a good idea on the name, but perhaps folks from @clang-language-wg might have an idea? Either way, I want to give it a little time for folks to comment.

That said, it DOES seem that the pre-commit-CI failures are related, so those need fixing as well.

philnik updated this revision to Diff 527704.Jun 1 2023, 7:18 PM
philnik marked 2 inline comments as done.
  • Address comments
  • Try to fix CI

1- This needs a release note.
2- I want others to comment on the name. I like its verbosity in that it'll discourage people from using it without knowing what it means, but I want to hear Aaron/others' opinion as well.
3- Trailing WS thing, I see you did a cleanup patch, so just make sure this gets commited after that.

clang/include/clang/Basic/AttrDocs.td
541

Trailing WS change, please don't do in this commit.

@aaron.ballman Do you have any opinion here?

aaron.ballman added inline comments.Jul 24 2023, 8:29 AM
clang/include/clang/Basic/AttrDocs.td
3525

The docs don't make it clear what the ramifications are of using the attribute. Do you get better codegen? Different diagnostics? That sort of thing.

It'd probably help for the docs to have a short code example showing what the difference the attribute makes.

Also, should we explicitly define it as UB if the user applies the attribute to something and the equivalence requirements aren't met?

If the attribute is written on a structure that's used as a base class, does the derived class automatically "inherit" the behavior as well? Or do derived classes have to be redeclared with the attribute? Is it reasonable for a base class which does not have the attribute to be inherited by a derived class which adds the attribute?

(I'm kind of wondering whether there are situations in which we want to diagnose use of the attribute to help programmers avoid mistakes.)

3531–3533
clang/test/SemaCXX/attr-equality-operator-compares-members-lexicographically.cpp
1

Is the triple necessary?

72

FIXME?

AMP999 added a subscriber: AMP999.Jul 24 2023, 9:58 AM

This attribute is trying to work around an issue with operator== instantiation, but according to https://cpplang.slack.com/archives/C6K47F8TT/p1689107603335019?thread_ts=1689107603.335019&cid=C6K47F8TT the problem is actually a bug in Clang. Shouldn't the Clang bug be fixed instead, so that this attribute won't be needed?

This attribute is trying to work around an issue with operator== instantiation, but according to https://cpplang.slack.com/archives/C6K47F8TT/p1689107603335019?thread_ts=1689107603.335019&cid=C6K47F8TT the problem is actually a bug in Clang. Shouldn't the Clang bug be fixed instead, so that this attribute won't be needed?

Any chance you can provide some more details about why the problem is a bug in Clang (Slack seems to require signing up in order to see what's behind the link)?

AMP999 added a comment.EditedJul 26 2023, 4:31 AM

Any chance you can provide some more details about why the problem is a bug in Clang (Slack seems to require signing up in order to see what's behind the link)?

Sure, I just filed this as a GitHub issue in the following link: https://github.com/llvm/llvm-project/issues/64124

Any chance you can provide some more details about why the problem is a bug in Clang (Slack seems to require signing up in order to see what's behind the link)?

Sure, I just filed this as a GitHub issue in the following link: https://github.com/llvm/llvm-project/issues/64124

Thank you for filing it as an issue, that's helpful!

philnik abandoned this revision.Sep 23 2023, 1:06 AM