This is an archive of the discontinued LLVM Phabricator instance.

[clangd][c++20]Consider rewritten binary operators in TargetFinder
ClosedPublic

Authored by massberg on Jun 20 2023, 4:28 AM.

Details

Summary

In C++20 some binary operations can be rewritten, e.g. a != b
can be rewritten to !(a == b) if != is not explicitly defined.
The TargetFinder hasn't considered the corresponding CXXRewrittenBinaryOperator yet. This resulted that the definition of such operators couldn't be found
when navigating to such a != operator, see https://github.com/clangd/clangd/issues/1476.

In this patch we add support of CXXRewrittenBinaryOperator in FindTarget.
In such a case we redirect to the inner binary operator of the decomposed form.
E.g. in case that a != b has been rewritten to !(a == b) we go to the
== operator. The == operator might be implicitly defined (e.g. by a <=>
operator), but this case is already handled, see the new test.

I'm not sure if I the hover test which is added in this patch is the right one,
but at least is passed with this patch and fails without it :)

Note, that it might be a bit missleading that hovering over a != refers to
"instance method operator==".

Diff Detail

Event Timeline

massberg created this revision.Jun 20 2023, 4:28 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 20 2023, 4:28 AM
Herald added a subscriber: arphaman. · View Herald Transcript
massberg requested review of this revision.Jun 20 2023, 4:28 AM

Thanks, this looks pretty good!

I'm not sure if I the hover test which is added in this patch is the right one,
but at least is passed with this patch and fails without it :)

This is nice to have, but you add a unittest to FindTargetTest too? That's the most direct way to test this code.

This won't affect find-refs BTW, that would be handled in refInStmt() in FindTarget.cpp

clang-tools-extra/clangd/unittests/HoverTests.cpp
4051

no need to sign your work :-)

4051

can you add this to HoverTest__All instead? That way we test all details of the hover card

4079

if we're describing this as the spaceship operator, then the type looks wrong

massberg updated this revision to Diff 532867.Jun 20 2023, 5:01 AM

Fix test name

massberg updated this revision to Diff 532921.Jun 20 2023, 7:31 AM

Add test to FindTargetTests and extend test in HoverTests.

massberg marked 2 inline comments as done.Jun 20 2023, 7:45 AM

Thanks for the comments, I have added an additional test to FindTargetTest. See also my other comments.

clang-tools-extra/clangd/unittests/HoverTests.cpp
4051

Upps, sorry.

4051

can you add this to HoverTest__All instead? That way we test all details of the hover card

The (Hover, All) test tests with std=c++17 while this test tests c++20 features.
We could add an additional field with the version to the struct in the (Hover, All) test.
Or add a (Hover, All_Cpp20) test for testing C++20 (what is probably not worth at the moment with just one test requiring C++20).

4079

I have added a test checking the whole definition.
Actually the following is happening here:
The != operator isn't explicitly defined, so the binary operator is rewritten to !(Foo(1) == Foo(2),
i.e. we are now using the == operator.
However, the == operator is also not explicitly defined, but there is a defaulted spaceship operator.
Thus the == operator is implicitly defined through the <=> operator.
So the type and definition here are from the implicitly defined == operator, while the original source of it is the <=> operator.

sammccall accepted this revision.Jun 20 2023, 8:13 AM
sammccall added inline comments.
clang-tools-extra/clangd/unittests/FindTargetTests.cpp
648

this template pattern vs instantiation is really surprising, but it's a reasonable analogy, I don't see any particular problems. (Also, operator<=> looks like a template over whatever = is!)

Do you know whether this means go-to-definition gives you two options to navigate to?
(No need to write a test, just curious)

clang-tools-extra/clangd/unittests/HoverTests.cpp
4051

Does anything break if you switch everything to C++20?
The intention of "std=c++17" there was certainly "not 14", rather than "not 20" :-)

This revision is now accepted and ready to land.Jun 20 2023, 8:13 AM
massberg updated this revision to Diff 533204.Jun 21 2023, 3:40 AM
massberg marked 2 inline comments as done.

Switched the "Hover, All" test to run with C++20 instead of C++17 and moved the
RewrittenBinaryOperatorSpaceship test to it.

massberg marked an inline comment as done.Jun 21 2023, 3:41 AM
massberg added inline comments.
clang-tools-extra/clangd/unittests/HoverTests.cpp
4051

Test test passed with C++20. I have switch it to C++20 and moved the new test as a new case in this test.

massberg updated this revision to Diff 533211.Jun 21 2023, 4:00 AM
massberg marked an inline comment as done.

clang-format code