This is an archive of the discontinued LLVM Phabricator instance.

Fix a rejects-valid with consteval on overloaded operators
ClosedPublic

Authored by aaron.ballman on Oct 14 2021, 9:45 AM.

Details

Summary

It seems that Clang 11 regressed functionality that was working in Clang 10 regarding calling a few overloaded operators in an immediate context. Specifically, we were not checking for immediate invocations of array subscripting and the arrow operators, but we properly handle the other overloaded operators.

This fixes the two problematic operators and adds some test coverage to show they're equivalent to calling the operator directly. This addresses PR50779.

Diff Detail

Event Timeline

aaron.ballman requested review of this revision.Oct 14 2021, 9:45 AM
aaron.ballman created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptOct 14 2021, 9:45 AM

This seems like two places this was missed in: https://reviews.llvm.org/D63960 however I see a another place grepping around we might have missed too? Can you find a way to write tests for that?

Also, perhaps 1 more cleanup?

clang/lib/Sema/SemaOverload.cpp
13800

Wonder if as a 'while we're here' we should make this the same as the others? Does CheckForImmediateInvocation handle an invalid result without the extra check like we have here?

14290

Was this one missed too?

aaron.ballman added inline comments.Oct 14 2021, 10:02 AM
clang/lib/Sema/SemaOverload.cpp
13800

CheckForImmediateInvocation handles invalid results (I checked), so we could remove the isInvalid() lines below if we wanted (that's really an NFC cleanup).

14290

I couldn't devise a test case that was failing with member function call expressions, so I left this one alone. We have a bunch of existing test coverage for calling a consteval member function, so I'm assuming this is correct, but if someone finds a test case that fails here, it's easy enough to fix.

rsmith accepted this revision.Oct 14 2021, 10:11 AM

Looks good to me.

clang/lib/Sema/SemaOverload.cpp
14290

This code is only reachable for a call through a pointer-to-member. We don't need to worry about consteval member function pointers because they can't escape constant-evaluated contexts anyway. Eg, (p->*&Class::consteval_fn)() is ill-formed outside of a constant-evaluated context -- we should make sure we have a test for that.

This revision is now accepted and ready to land.Oct 14 2021, 10:11 AM
erichkeane accepted this revision.Oct 14 2021, 10:12 AM
erichkeane added inline comments.
clang/lib/Sema/SemaOverload.cpp
14290

I can't come up with one either, I think we're fine for now.

aaron.ballman added inline comments.Oct 14 2021, 10:27 AM
clang/lib/Sema/SemaOverload.cpp
14290
struct test {
  consteval int f() const { return 12; }
};

constexpr test t;
int main() {
  constexpr int i = (t.*&test::f)();
}

@rsmith -- would you expect us to accept or reject this? GCC accepts, MSVC rejects, Clang currently rejects. This is different from your test case (because this is in a constant evaluated context), which we do already reject with a decent message: https://godbolt.org/z/3nv4bco9M

aaron.ballman added inline comments.Oct 14 2021, 11:43 AM
clang/lib/Sema/SemaOverload.cpp
14290

Thinking about this a bit more, I think that code should be accepted.

struct test {
  consteval int f() const { return 12; }
};

constexpr test t;
int main() {
  constexpr int i = t.f(); // If this works
  constexpr int j = (t.*&test::f)(); // This should also work
}

However, when I make the obvious changes in this patch to support it, we stop getting the diagnostic outside of a constant evaluated context. So my plan is to land the small fixes we know are correct and are happy with, and we can debate this case more later.

Updated the patch to add new test cases.