https://github.com/MythreyaK created 
https://github.com/llvm/llvm-project/pull/154041

Fixes #109608. (signature help still needs fixing. Will add a commit soon)

Include methods that use explicit object in code complete suggestions. 

```cpp
struct S {
  void foo1() const;
  void foo2();
  void foo3(this const S& self);
  void foo4(this S& self);
};

int foo(const S arg) {
  arg.f^ // Now suggests foo3 as well 
}
```

Signature for void `foo3(this const S& self)` is shown as `(int a)` instead of 
`(int a) const`. 

>From d730c1fce8f16ae8139a2108ff55d911769fb0fa Mon Sep 17 00:00:00 2001
From: Mythreya Kuricheti <g...@mythreya.dev>
Date: Sat, 16 Aug 2025 15:48:02 -0700
Subject: [PATCH] [clang] Include explicit object methods in overload
 suggestions

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 119 ++++++++++++++++++
 clang/include/clang/AST/DeclCXX.h             |   5 +-
 2 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 1a1c32c241602..f5989eca4e1b5 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -4473,6 +4473,125 @@ TEST(CompletionTest, SkipExplicitObjectParameter) {
                                   snippetSuffix(""))));
   }
 }
+
+TEST(CompletionTest, ListExplicitObjectOverloads) {
+  Annotations Code(R"cpp(
+    struct S {
+      void foo1(int a);
+      void foo2(int a) const;
+      void foo3(this const S& self, int a);
+      void foo4(this S& self, int a);
+    };
+
+    void S::foo1(int a) {
+      this->$c1^;
+    }
+
+    void S::foo2(int a) const {
+      this->$c2^;
+    }
+
+    void S::foo3(this const S& self, int a) {
+      self.$c3^;
+    }
+
+    void S::foo4(this S& self, int a) {
+      self.$c4^;
+    }
+
+    void test1(S s) {
+      s.$c5^;
+    }
+
+    void test2(const S s) {
+      s.$c6^;
+    }
+  )cpp");
+
+  auto TU = TestTU::withCode(Code.code());
+  TU.ExtraArgs = {"-std=c++23"};
+
+  auto Preamble = TU.preamble();
+  ASSERT_TRUE(Preamble);
+
+  CodeCompleteOptions Opts{};
+
+  MockFS FS;
+  auto Inputs = TU.inputs(FS);
+
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo1"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo4"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})"))));
+  }
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})"))));
+  }
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})"))));
+  }
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c4"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo1"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo4"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})"))));
+  }
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c5"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo1"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo4"), signature("(int a)"),
+                          snippetSuffix("(${1:int a})"))));
+  }
+  {
+    auto Result = codeComplete(testPath(TU.Filename), Code.point("c6"),
+                               Preamble.get(), Inputs, Opts);
+    EXPECT_THAT(Result.Completions,
+                UnorderedElementsAre(
+                    AllOf(named("foo2"), signature("(int a) const"),
+                          snippetSuffix("(${1:int a})")),
+                    AllOf(named("foo3"), signature("(int a)" /* const */),
+                          snippetSuffix("(${1:int a})"))));
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 1d2ef0f4f2319..5f0fe1580611e 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2288,7 +2288,10 @@ class CXXMethodDecl : public FunctionDecl {
                               const CXXRecordDecl *Decl);
 
   Qualifiers getMethodQualifiers() const {
-    return getType()->castAs<FunctionProtoType>()->getMethodQuals();
+    if (isExplicitObjectMemberFunction())
+      return getFunctionObjectParameterType().getQualifiers();
+    else
+      return getType()->castAs<FunctionProtoType>()->getMethodQuals();
   }
 
   /// Retrieve the ref-qualifier associated with this method.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to