Skip to content

Commit 471fa8c

Browse files
committed
[clang] Include explicit object methods in overload suggestions
1 parent 93189ec commit 471fa8c

File tree

2 files changed

+129
-1
lines changed

2 files changed

+129
-1
lines changed

clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4532,6 +4532,126 @@ TEST(CompletionTest, MemberAccessInExplicitObjMemfn) {
45324532
EXPECT_THAT(Result.Completions, ElementsAre());
45334533
}
45344534
}
4535+
4536+
TEST(CompletionTest, ListExplicitObjectOverloads) {
4537+
Annotations Code(R"cpp(
4538+
struct S {
4539+
void foo1(int a);
4540+
void foo2(int a) const;
4541+
void foo3(this const S& self, int a);
4542+
void foo4(this S& self, int a);
4543+
};
4544+
4545+
void S::foo1(int a) {
4546+
this->$c1^;
4547+
}
4548+
4549+
void S::foo2(int a) const {
4550+
this->$c2^;
4551+
}
4552+
4553+
void S::foo3(this const S& self, int a) {
4554+
self.$c3^;
4555+
}
4556+
4557+
void S::foo4(this S& self, int a) {
4558+
self.$c4^;
4559+
}
4560+
4561+
void test1(S s) {
4562+
s.$c5^;
4563+
}
4564+
4565+
void test2(const S s) {
4566+
s.$c6^;
4567+
}
4568+
)cpp");
4569+
4570+
auto TU = TestTU::withCode(Code.code());
4571+
TU.ExtraArgs = {"-std=c++23"};
4572+
4573+
auto Preamble = TU.preamble();
4574+
ASSERT_TRUE(Preamble);
4575+
4576+
CodeCompleteOptions Opts{};
4577+
4578+
MockFS FS;
4579+
auto Inputs = TU.inputs(FS);
4580+
4581+
{
4582+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c1"),
4583+
Preamble.get(), Inputs, Opts);
4584+
EXPECT_THAT(Result.Completions,
4585+
UnorderedElementsAre(
4586+
AllOf(named("foo1"), signature("(int a)"),
4587+
snippetSuffix("(${1:int a})")),
4588+
AllOf(named("foo2"), signature("(int a) const"),
4589+
snippetSuffix("(${1:int a})")),
4590+
AllOf(named("foo3"), signature("(int a)" /* const */),
4591+
snippetSuffix("(${1:int a})")),
4592+
AllOf(named("foo4"), signature("(int a)"),
4593+
snippetSuffix("(${1:int a})"))));
4594+
}
4595+
{
4596+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c2"),
4597+
Preamble.get(), Inputs, Opts);
4598+
EXPECT_THAT(Result.Completions,
4599+
UnorderedElementsAre(
4600+
AllOf(named("foo2"), signature("(int a) const"),
4601+
snippetSuffix("(${1:int a})")),
4602+
AllOf(named("foo3"), signature("(int a)" /* const */),
4603+
snippetSuffix("(${1:int a})"))));
4604+
}
4605+
{
4606+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c3"),
4607+
Preamble.get(), Inputs, Opts);
4608+
EXPECT_THAT(Result.Completions,
4609+
UnorderedElementsAre(
4610+
AllOf(named("foo2"), signature("(int a) const"),
4611+
snippetSuffix("(${1:int a})")),
4612+
AllOf(named("foo3"), signature("(int a)" /* const */),
4613+
snippetSuffix("(${1:int a})"))));
4614+
}
4615+
{
4616+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c4"),
4617+
Preamble.get(), Inputs, Opts);
4618+
EXPECT_THAT(Result.Completions,
4619+
UnorderedElementsAre(
4620+
AllOf(named("foo1"), signature("(int a)"),
4621+
snippetSuffix("(${1:int a})")),
4622+
AllOf(named("foo2"), signature("(int a) const"),
4623+
snippetSuffix("(${1:int a})")),
4624+
AllOf(named("foo3"), signature("(int a)" /* const */),
4625+
snippetSuffix("(${1:int a})")),
4626+
AllOf(named("foo4"), signature("(int a)"),
4627+
snippetSuffix("(${1:int a})"))));
4628+
}
4629+
{
4630+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c5"),
4631+
Preamble.get(), Inputs, Opts);
4632+
EXPECT_THAT(Result.Completions,
4633+
UnorderedElementsAre(
4634+
AllOf(named("foo1"), signature("(int a)"),
4635+
snippetSuffix("(${1:int a})")),
4636+
AllOf(named("foo2"), signature("(int a) const"),
4637+
snippetSuffix("(${1:int a})")),
4638+
AllOf(named("foo3"), signature("(int a)" /* const */),
4639+
snippetSuffix("(${1:int a})")),
4640+
AllOf(named("foo4"), signature("(int a)"),
4641+
snippetSuffix("(${1:int a})"))));
4642+
}
4643+
{
4644+
auto Result = codeComplete(testPath(TU.Filename), Code.point("c6"),
4645+
Preamble.get(), Inputs, Opts);
4646+
EXPECT_THAT(Result.Completions,
4647+
UnorderedElementsAre(
4648+
AllOf(named("foo2"), signature("(int a) const"),
4649+
snippetSuffix("(${1:int a})")),
4650+
AllOf(named("foo3"), signature("(int a)" /* const */),
4651+
snippetSuffix("(${1:int a})"))));
4652+
}
4653+
}
4654+
45354655
} // namespace
45364656
} // namespace clangd
45374657
} // namespace clang

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,14 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
14351435

14361436
AdjustResultPriorityForDecl(R);
14371437

1438+
// Account for explicit object parameter
1439+
const auto getQualifiers = [&](const CXXMethodDecl *MethodDecl) {
1440+
if (MethodDecl->isExplicitObjectMemberFunction())
1441+
return MethodDecl->getFunctionObjectParameterType().getQualifiers();
1442+
else
1443+
return MethodDecl->getMethodQualifiers();
1444+
};
1445+
14381446
if (IsExplicitObjectMemberFunction &&
14391447
R.Kind == CodeCompletionResult::RK_Declaration &&
14401448
(isa<CXXMethodDecl>(R.Declaration) || isa<FieldDecl>(R.Declaration))) {
@@ -1447,7 +1455,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
14471455
if (HasObjectTypeQualifiers)
14481456
if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
14491457
if (Method->isInstance()) {
1450-
Qualifiers MethodQuals = Method->getMethodQualifiers();
1458+
Qualifiers MethodQuals = getQualifiers(Method);
14511459
if (ObjectTypeQualifiers == MethodQuals)
14521460
R.Priority += CCD_ObjectQualifierMatch;
14531461
else if (ObjectTypeQualifiers - MethodQuals) {

0 commit comments

Comments
 (0)