[PATCH] D153331: [clangd][c++20]Consider rewritten binary operators in TargetFinder

Jens Massberg via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 20 04:28:11 PDT 2023


massberg created this revision.
massberg added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
massberg requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

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==".


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153331

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -4048,6 +4048,38 @@
   EXPECT_TRUE(H->Type);
 }
 
+TEST(Hover, RewrittenBinaryOperatorSpaceshipMassberg) {
+  Annotations T(R"cpp(
+  namespace std {
+  struct strong_ordering {
+    int n;
+    constexpr operator int() const { return n; }
+    static const strong_ordering equal, greater, less;
+  };
+  constexpr strong_ordering strong_ordering::equal = {0};
+  constexpr strong_ordering strong_ordering::greater = {1};
+  constexpr strong_ordering strong_ordering::less = {-1};
+  }
+
+  struct Foo
+  {
+    int x;
+    // Foo spaceship
+    auto operator<=>(const Foo&) const = default;
+  };
+
+  static_assert(Foo(1) !^= Foo(2));
+  )cpp");
+
+  TestTU TU = TestTU::withCode(T.code());
+  TU.ExtraArgs.push_back("-std=c++20");
+  auto AST = TU.build();
+  auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
+  EXPECT_EQ(HI->Type,
+            HoverInfo::PrintedType("bool (const Foo &) const noexcept"));
+  EXPECT_EQ(HI->Documentation, "Foo spaceship");
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -347,6 +347,10 @@
       void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE) {
         Outer.add(CDE->getOperatorDelete(), Flags);
       }
+      void
+      VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
+        Outer.add(RBO->getDecomposedForm().InnerBinOp, Flags);
+      }
     };
     Visitor(*this, Flags).Visit(S);
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D153331.532866.patch
Type: text/x-patch
Size: 1842 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230620/13f889df/attachment.bin>


More information about the cfe-commits mailing list