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

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

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 120 ++++++++++++++++++
 clang/lib/Sema/SemaCodeComplete.cpp           |  10 +-
 2 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 3f1623904d8cc..022eca4cf5395 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -4532,6 +4532,126 @@ TEST(CompletionTest, MemberAccessInExplicitObjMemfn) {
     EXPECT_THAT(Result.Completions, ElementsAre());
   }
 }
+
+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/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index eb1bbec82b645..5bd1ef72e724c 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -1435,6 +1435,14 @@ void ResultBuilder::AddResult(Result R, DeclContext 
*CurContext,
 
   AdjustResultPriorityForDecl(R);
 
+  // Account for explicit object parameter
+  const auto getQualifiers = [&](const CXXMethodDecl *MethodDecl) {
+    if (MethodDecl->isExplicitObjectMemberFunction())
+      return MethodDecl->getFunctionObjectParameterType().getQualifiers();
+    else
+      return MethodDecl->getMethodQualifiers();
+  };
+
   if (IsExplicitObjectMemberFunction &&
       R.Kind == CodeCompletionResult::RK_Declaration &&
       (isa<CXXMethodDecl>(R.Declaration) || isa<FieldDecl>(R.Declaration))) {
@@ -1447,7 +1455,7 @@ void ResultBuilder::AddResult(Result R, DeclContext 
*CurContext,
   if (HasObjectTypeQualifiers)
     if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
       if (Method->isInstance()) {
-        Qualifiers MethodQuals = Method->getMethodQualifiers();
+        Qualifiers MethodQuals = getQualifiers(Method);
         if (ObjectTypeQualifiers == MethodQuals)
           R.Priority += CCD_ObjectQualifierMatch;
         else if (ObjectTypeQualifiers - MethodQuals) {

>From aa2c6fe5d8c6ab6ba492c1dd6800fe816bbb72a6 Mon Sep 17 00:00:00 2001
From: Mythreya Kuricheti <g...@mythreya.dev>
Date: Mon, 18 Aug 2025 00:45:13 -0700
Subject: [PATCH 2/4] Add const to signature string

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 96 +++++++++----------
 clang/lib/Sema/SemaCodeComplete.cpp           | 27 ++++++
 2 files changed, 75 insertions(+), 48 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 022eca4cf5395..5e60cce303bb9 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -4581,74 +4581,74 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
   {
     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})"))));
+    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})"))));
+    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})"))));
+    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})"))));
+    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})"))));
+    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})"))));
+    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})"))));
   }
 }
 
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 5bd1ef72e724c..28b4900452849 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -3434,9 +3434,36 @@ static void 
AddQualifierToCompletionString(CodeCompletionBuilder &Result,
     Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
 }
 
+// Sets the function qualifiers completion string by inspecting the explicit
+// object
+static void AddCXXExplicitObjectFunctionTypeQualsToCompletionString(
+    CodeCompletionBuilder &Result, const CXXMethodDecl *Function) {
+  const auto Quals = Function->getFunctionObjectParameterType();
+
+  if (!Quals.hasQualifiers())
+    return;
+
+  std::string QualsStr;
+  if (Quals.getQualifiers().hasConst())
+    QualsStr += " const";
+  if (Quals.getQualifiers().hasVolatile())
+    QualsStr += " volatile";
+  if (Quals.getQualifiers().hasRestrict())
+    QualsStr += " restrict";
+  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+}
+
 static void
 AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
                                        const FunctionDecl *Function) {
+  if (auto *CxxMethodDecl = llvm::dyn_cast_if_present<CXXMethodDecl>(Function);
+      CxxMethodDecl && CxxMethodDecl->hasCXXExplicitFunctionObjectParameter()) 
{
+    // if explicit object method, infer quals from the object parameter
+    AddCXXExplicitObjectFunctionTypeQualsToCompletionString(Result,
+                                                            CxxMethodDecl);
+    return;
+  }
+
   const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
   if (!Proto || !Proto->getMethodQuals())
     return;

>From 639da07724cc542cd430203226e2d332199f8346 Mon Sep 17 00:00:00 2001
From: Mythreya Kuricheti <g...@mythreya.dev>
Date: Mon, 18 Aug 2025 02:05:58 -0700
Subject: [PATCH 3/4] Update tests

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 13 ++++
 .../CodeCompletion/cpp23-explicit-object.cpp  | 70 +++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 5e60cce303bb9..7640569128172 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -4538,6 +4538,7 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
     struct S {
       void foo1(int a);
       void foo2(int a) const;
+      void foo2(this const S& self, float a);
       void foo3(this const S& self, int a);
       void foo4(this S& self, int a);
     };
@@ -4587,6 +4588,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo4"), signature("(int a)"),
@@ -4599,6 +4602,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
         Result.Completions,
         UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})"))));
   }
@@ -4609,6 +4614,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
         Result.Completions,
         UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})"))));
   }
@@ -4621,6 +4628,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo4"), signature("(int a)"),
@@ -4635,6 +4644,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
                              AllOf(named("foo4"), signature("(int a)"),
@@ -4647,6 +4658,8 @@ TEST(CompletionTest, ListExplicitObjectOverloads) {
         Result.Completions,
         UnorderedElementsAre(AllOf(named("foo2"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})")),
+                             AllOf(named("foo2"), signature("(float a) const"),
+                                   snippetSuffix("(${1:float a})")),
                              AllOf(named("foo3"), signature("(int a) const"),
                                    snippetSuffix("(${1:int a})"))));
   }
diff --git a/clang/test/CodeCompletion/cpp23-explicit-object.cpp 
b/clang/test/CodeCompletion/cpp23-explicit-object.cpp
index 08e5565f3d186..ea97237ecd24b 100644
--- a/clang/test/CodeCompletion/cpp23-explicit-object.cpp
+++ b/clang/test/CodeCompletion/cpp23-explicit-object.cpp
@@ -81,3 +81,73 @@ struct C {
   }
 };
 
+
+struct S {
+  void foo1(int a);
+  void foo2(int a) const;
+  void foo2(this const S& self, float a);  
+  void foo3(this const S& self, int a);
+  void foo4(this S& self, int a);
+};
+
+void S::foo1(int a) {
+  this->;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):9 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC7 %s
+// CHECK-CC7: COMPLETION: foo1 : [#void#]foo1(<#int a#>)
+// CHECK-CC7: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC7: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC7: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+// CHECK-CC7: COMPLETION: foo4 : [#void#]foo4(<#int a#>)
+}
+
+void S::foo2(int a) const {
+  this->;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):9 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC8 %s
+// CHECK-CC8: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC8: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC8: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+}
+
+void S::foo3(this const S& self, int a) {
+  self.;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):8 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC9 %s
+// CHECK-CC9: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC9: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC9: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+}
+
+void S::foo4(this S& self, int a) {
+  self.;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):8 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC10 %s
+// CHECK-CC10: COMPLETION: foo1 : [#void#]foo1(<#int a#>)
+// CHECK-CC10: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC10: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC10: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+// CHECK-CC10: COMPLETION: foo4 : [#void#]foo4(<#int a#>)
+}
+
+void test1(S s) {
+  s.;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):5 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC11 %s
+// CHECK-CC11: COMPLETION: foo1 : [#void#]foo1(<#int a#>)
+// CHECK-CC11: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC11: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC11: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+// CHECK-CC11: COMPLETION: foo4 : [#void#]foo4(<#int a#>)
+}
+
+void test2(const S s) {
+  s.;
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):5 -std=c++23 
%s | FileCheck -check-prefix=CHECK-CC12 %s
+// CHECK-CC12: COMPLETION: foo2 : [#void#]foo2(<#int a#>)[# const#]
+// CHECK-CC12: COMPLETION: foo2 : [#void#]foo2(<#float a#>)[# const#]
+// CHECK-CC12: COMPLETION: foo3 : [#void#]foo3(<#int a#>)[# const#]
+}
+
+void test3(S s) {
+  s.foo2();
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-1):10 
-std=c++23 %s | FileCheck -check-prefix=CHECK-CC13 %s
+// CHECK-CC13: OVERLOAD: [#void#]foo2(<#int a#>)
+// CHECK-CC13: OVERLOAD: [#void#]foo2(float a)
+// TODO: foo2 should be OVERLOAD: [#void#]foo2(<#float a#>)
+}

>From d2476ed6018439149b803b94edcdaecf6efbf387 Mon Sep 17 00:00:00 2001
From: Mythreya Kuricheti <g...@mythreya.dev>
Date: Wed, 20 Aug 2025 01:48:52 -0700
Subject: [PATCH 4/4] code review

---
 clang/lib/Sema/SemaCodeComplete.cpp | 86 ++++++++++++++---------------
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 28b4900452849..eb27432edb15d 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -413,6 +413,37 @@ class ResultBuilder {
   bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
   //@}
 };
+
+void AddFunctionTypeQuals(CodeCompletionBuilder &Result,
+                          const Qualifiers Quals) {
+  // FIXME: Add ref-qualifier!
+
+  // Handle single qualifiers without copying
+  if (Quals.hasOnlyConst()) {
+    Result.AddInformativeChunk(" const");
+    return;
+  }
+
+  if (Quals.hasOnlyVolatile()) {
+    Result.AddInformativeChunk(" volatile");
+    return;
+  }
+
+  if (Quals.hasOnlyRestrict()) {
+    Result.AddInformativeChunk(" restrict");
+    return;
+  }
+
+  // Handle multiple qualifiers.
+  std::string QualsStr;
+  if (Quals.hasConst())
+    QualsStr += " const";
+  if (Quals.hasVolatile())
+    QualsStr += " volatile";
+  if (Quals.hasRestrict())
+    QualsStr += " restrict";
+  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+}
 } // namespace
 
 void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) {
@@ -1436,7 +1467,7 @@ void ResultBuilder::AddResult(Result R, DeclContext 
*CurContext,
   AdjustResultPriorityForDecl(R);
 
   // Account for explicit object parameter
-  const auto getQualifiers = [&](const CXXMethodDecl *MethodDecl) {
+  const auto GetQualifiers = [&](const CXXMethodDecl *MethodDecl) {
     if (MethodDecl->isExplicitObjectMemberFunction())
       return MethodDecl->getFunctionObjectParameterType().getQualifiers();
     else
@@ -1455,7 +1486,7 @@ void ResultBuilder::AddResult(Result R, DeclContext 
*CurContext,
   if (HasObjectTypeQualifiers)
     if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
       if (Method->isInstance()) {
-        Qualifiers MethodQuals = getQualifiers(Method);
+        Qualifiers MethodQuals = GetQualifiers(Method);
         if (ObjectTypeQualifiers == MethodQuals)
           R.Priority += CCD_ObjectQualifierMatch;
         else if (ObjectTypeQualifiers - MethodQuals) {
@@ -3438,19 +3469,15 @@ static void 
AddQualifierToCompletionString(CodeCompletionBuilder &Result,
 // object
 static void AddCXXExplicitObjectFunctionTypeQualsToCompletionString(
     CodeCompletionBuilder &Result, const CXXMethodDecl *Function) {
-  const auto Quals = Function->getFunctionObjectParameterType();
+  assert(isa<CXXMethodDecl>(Function) &&
+         Function->hasCXXExplicitFunctionObjectParameter() &&
+         "Valid only on CXX explicit object methods");
 
+  const auto Quals = Function->getFunctionObjectParameterType();
   if (!Quals.hasQualifiers())
     return;
 
-  std::string QualsStr;
-  if (Quals.getQualifiers().hasConst())
-    QualsStr += " const";
-  if (Quals.getQualifiers().hasVolatile())
-    QualsStr += " volatile";
-  if (Quals.getQualifiers().hasRestrict())
-    QualsStr += " restrict";
-  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+  AddFunctionTypeQuals(Result, Quals.getQualifiers());
 }
 
 static void
@@ -3461,40 +3488,13 @@ 
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
     // if explicit object method, infer quals from the object parameter
     AddCXXExplicitObjectFunctionTypeQualsToCompletionString(Result,
                                                             CxxMethodDecl);
-    return;
-  }
-
-  const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
-  if (!Proto || !Proto->getMethodQuals())
-    return;
-
-  // FIXME: Add ref-qualifier!
-
-  // Handle single qualifiers without copying
-  if (Proto->getMethodQuals().hasOnlyConst()) {
-    Result.AddInformativeChunk(" const");
-    return;
-  }
-
-  if (Proto->getMethodQuals().hasOnlyVolatile()) {
-    Result.AddInformativeChunk(" volatile");
-    return;
-  }
+  } else {
+    const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
+    if (!Proto || !Proto->getMethodQuals())
+      return;
 
-  if (Proto->getMethodQuals().hasOnlyRestrict()) {
-    Result.AddInformativeChunk(" restrict");
-    return;
+    AddFunctionTypeQuals(Result, Proto->getMethodQuals());
   }
-
-  // Handle multiple qualifiers.
-  std::string QualsStr;
-  if (Proto->isConst())
-    QualsStr += " const";
-  if (Proto->isVolatile())
-    QualsStr += " volatile";
-  if (Proto->isRestrict())
-    QualsStr += " restrict";
-  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
 }
 
 static void

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

Reply via email to