This is an archive of the discontinued LLVM Phabricator instance.

[Concepts] Fix overload resolution bug with constrained candidates
ClosedPublic

Authored by royjacobson on Apr 5 2022, 10:13 PM.

Details

Summary

When doing overload resolution, we have to check that candidates' parameter types are equal before trying to find a better candidate through checking which candidate is more constrained.
This revision adds this missing check and makes us diagnose those cases as ambiguous calls when the types are not equal.

Fixes GitHub issue https://github.com/llvm/llvm-project/issues/53640

Diff Detail

Event Timeline

royjacobson created this revision.Apr 5 2022, 10:13 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 5 2022, 10:13 PM
royjacobson requested review of this revision.Apr 5 2022, 10:13 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 5 2022, 10:13 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Fixed missing doc for new argument

Can you improve the commit-message? Title in particular, but more details would be greatly appreciated.

clang/lib/Sema/SemaOverload.cpp
2947–2948
2951

I don't really get what you mean for 'Reversed', can you better clarify? Both in comments, and here?

2964

Now I REALLY don't get it :)

9848

Since the point of this is to just calculate the CanCompareConstraints, I think it should be a separate function called below where it is used.

Formatting + clarify docs a bit

royjacobson marked an inline comment as done.Apr 11 2022, 1:51 PM
royjacobson retitled this revision from [Concepts] Fix issue #53640 to [Concepts] Fix overload resolution bug with constrained candidates.
royjacobson edited the summary of this revision. (Show Details)Apr 11 2022, 1:56 PM
royjacobson added inline comments.Apr 11 2022, 2:02 PM
clang/lib/Sema/SemaOverload.cpp
2951

I tried to modify the documentation a bit, I hope it's more understandable :)

C++20 added 'synthesized reverse operator overloads'. We support them in the overload resolution code by just remembering if we use a candidate with reverse order.

I need this here so the example in p6 with operator== works. It's a pretty annoying and weird corner case, but if it's explicitly in one of the standard's examples I might as well support it...

(BTW, GCC just don't implement this: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105174)

9848

Do you mean as in a separate Sema function? Or a local lambda?

erichkeane added inline comments.Apr 12 2022, 6:46 AM
clang/lib/Sema/SemaOverload.cpp
2960

Thanks for the clarification on 'Reversed'. The comment makes it more clear.

This whole 'for' header is... really tough to mentally parse, even BEFORE this, and now it is even worse with 'Reversed' involved. I would prefer that the iterators be initialized ahead of time. Additionally, can we use reverse_iterator for the 'NewType' instead of branching on Reversed here?

Any other suggestions you have to simplify this loop would also be appreciated. I might ALSO consider using 'zip' here?

2965

O AND O !=E? This condition reads wackily....

royjacobson marked an inline comment as not done.

Update for look inside FunctionParamTypesAreEqual to be index based and simpler.

royjacobson added inline comments.Apr 15 2022, 8:28 AM
clang/lib/Sema/SemaOverload.cpp
2960

I made it index based which IMO is easier to understand now.

I thought reverse_iterator would be annoying because I would need to make the code a template since it's a different type.

Also - ping about the comment in isBetterOverloadCandidate :)

erichkeane added inline comments.Apr 15 2022, 8:32 AM
clang/lib/Sema/SemaOverload.cpp
2960

Ah, right, you'd have 1 reverse iterator on one side of the 'zip'. Thats unfortunate. I guess this reads well-enough though, iti s definitely an improvement.

9848

Just a static function is fine, basically its a whole lot of work happening in this function for a single result, so I'm suggesting splitting off the calculation for CanCompareConstraints into its own function, so you get:

bool CanCompareConstrants = new_function(...);

Split the 'can compare constraints' code into a static function.

royjacobson marked 2 inline comments as done.Apr 15 2022, 8:59 AM
royjacobson added inline comments.
clang/lib/Sema/SemaOverload.cpp
9848

Done

erichkeane accepted this revision.Apr 15 2022, 9:02 AM

I'm happy with this.

This revision is now accepted and ready to land.Apr 15 2022, 9:02 AM
royjacobson marked an inline comment as done.

Rebase

Rebase again (HEAD CI was broken)

royjacobson added a reviewer: Restricted Project.Apr 16 2022, 1:18 AM

Thanks @erichkeane! I will land this on Monday if there are no further comments and the CI looks good.

Pretty sure those OMP bugs are unrelated, we've been seeing those a ton lately on just about every patch.

This revision was landed with ongoing or failed builds.Apr 19 2022, 1:45 AM
This revision was automatically updated to reflect the committed changes.

So, it seems like this broke one of basic_arg_format's private constructors.. Sorry for that.

//format_arg.h:167
explicit basic_format_arg(_Tp __v) noexcept
      requires(same_as<_Tp, char_type> ||
               (same_as<_Tp, char> && same_as<char_type, wchar_t>)) [....]

//format_arg.h:248
explicit basic_format_arg(const _Tp& __v) [...]

This is now ambiguous when calling basic_format_arg(char) because the argument type is different and comparing constraints is not allowed. @Mordante could you maybe take a look? I've reverted in the meantime.

So, it seems like this broke one of basic_arg_format's private constructors.. Sorry for that.

This is now ambiguous when calling basic_format_arg(char) because the argument type is different and comparing constraints is not allowed. @Mordante could you maybe take a look? I've reverted in the meantime.

Thanks for the ping!

I'll have a look, probably tomorrow.

royjacobson reopened this revision.Apr 23 2022, 1:33 PM
This revision is now accepted and ready to land.Apr 23 2022, 1:33 PM

Rebase after fix.

This revision was landed with ongoing or failed builds.Apr 23 2022, 2:25 PM
This revision was automatically updated to reflect the committed changes.

@nkreeger : Can you please explain your revert, both in the revert commit message (next time), as well as the patch so that the author/rest of us have SOME hint as to why it was reverted? Frequent reverts make it painful as a downstream, and confusing as a reviewer/implementer as to the state of things.

@nkreeger : Can you please explain your revert, both in the revert commit message (next time), as well as the patch so that the author/rest of us have SOME hint as to why it was reverted? Frequent reverts make it painful as a downstream, and confusing as a reviewer/implementer as to the state of things.

Apologies - I was reverting my commit and accidently had the wrong git-revert commit in my tree locally. I thought I had it cleaned up, but was wrong when I pushed. I ensured the tree was back in place with another revert. Please let me know if this is not the case. Sorry again :-(

@nkreeger : Can you please explain your revert, both in the revert commit message (next time), as well as the patch so that the author/rest of us have SOME hint as to why it was reverted? Frequent reverts make it painful as a downstream, and confusing as a reviewer/implementer as to the state of things.

Apologies - I was reverting my commit and accidently had the wrong git-revert commit in my tree locally. I thought I had it cleaned up, but was wrong when I pushed. I ensured the tree was back in place with another revert. Please let me know if this is not the case. Sorry again :-(

I see that now, thanks for the explanation! IN the future, even when reverting your OWN commit, it is appreciated if you explain the WHY to the revert so that it has some level of context. Particularly when you show some sort of example of the failure (like a link to the broken bot, etc), as it helps the downstream test-failure-analysis a ton.

@nkreeger : Can you please explain your revert, both in the revert commit message (next time), as well as the patch so that the author/rest of us have SOME hint as to why it was reverted? Frequent reverts make it painful as a downstream, and confusing as a reviewer/implementer as to the state of things.

Apologies - I was reverting my commit and accidently had the wrong git-revert commit in my tree locally. I thought I had it cleaned up, but was wrong when I pushed. I ensured the tree was back in place with another revert. Please let me know if this is not the case. Sorry again :-(

I see that now, thanks for the explanation! IN the future, even when reverting your OWN commit, it is appreciated if you explain the WHY to the revert so that it has some level of context. Particularly when you show some sort of example of the failure (like a link to the broken bot, etc), as it helps the downstream test-failure-analysis a ton.

Roger noted - apologies again I felt horrible!