[clang] [clang-tools-extra] [clang] Include explicit object methods in overload suggestions (PR #154041)
Mythreya Kuricheti via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 17 15:50:55 PDT 2025
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 <git at 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.
More information about the cfe-commits
mailing list