https://github.com/etyloppihacilem updated 
https://github.com/llvm/llvm-project/pull/165916

>From f44e756236b96bee574736b13fd7a134f715f6b9 Mon Sep 17 00:00:00 2001
From: Hippolyte Melica <[email protected]>
Date: Fri, 31 Oct 2025 12:08:07 +0100
Subject: [PATCH] [clangd] Autocomplete fixes for methods and arguments

---
 .../clangd/unittests/CodeCompleteTests.cpp    | 131 ++++++++--
 clang/include/clang/Parse/Parser.h            |  27 +-
 .../include/clang/Sema/CodeCompleteConsumer.h |  16 +-
 clang/include/clang/Sema/SemaCodeCompletion.h |   9 +-
 clang/lib/Parse/ParseDecl.cpp                 |   4 +-
 clang/lib/Parse/ParseExpr.cpp                 |   5 +-
 clang/lib/Parse/ParseExprCXX.cpp              |   5 +-
 clang/lib/Parse/Parser.cpp                    |  10 +-
 clang/lib/Sema/SemaCodeComplete.cpp           | 231 +++++++++++++-----
 .../CodeCompletion/cpp23-explicit-object.cpp  |   4 +-
 clang/test/CodeCompletion/member-access.cpp   |   4 +-
 clang/test/Index/complete-qualified.cpp       |   4 +-
 12 files changed, 353 insertions(+), 97 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp 
b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 31f2d8bd68703..80103ac7f96a1 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -531,19 +531,26 @@ TEST(CompletionTest, 
HeuristicsForMemberFunctionCompletion) {
 
   Annotations Code(R"cpp(
       struct Foo {
-        static int staticMethod(int);
-        int method(int) const;
+        static int staticMethod(int name);
+        int method(int name) const;
         template <typename T, typename U, typename V = int>
-        T generic(U, V);
+        T generic(U nameU, V nameV);
         template <typename T, int U>
         static T staticGeneric();
         Foo() {
-          this->$canBeCall^
+          this->$canBeCallNoStatic^
           $canBeCall^
           Foo::$canBeCall^
         }
       };
 
+      int Foo::$isDefinition^ {
+      }
+      ;
+
+      int i = Foo::$canBeCallStaticOnly^
+      ;
+
       struct Derived : Foo {
         using Foo::method;
         using Foo::generic;
@@ -556,9 +563,10 @@ TEST(CompletionTest, 
HeuristicsForMemberFunctionCompletion) {
         OtherClass() {
           Foo f;
           Derived d;
-          f.$canBeCall^
+          f.$canBeCallNoStatic^
           ; // Prevent parsing as 'f.f'
           f.Foo::$canBeCall^
+          ;
           &Foo::$canNotBeCall^
           ;
           d.Foo::$canBeCall^
@@ -573,6 +581,7 @@ TEST(CompletionTest, HeuristicsForMemberFunctionCompletion) 
{
         f.$canBeCall^
         ; // Prevent parsing as 'f.f'
         f.Foo::$canBeCall^
+        ;
         &Foo::$canNotBeCall^
         ;
         d.Foo::$canBeCall^
@@ -585,39 +594,127 @@ TEST(CompletionTest, 
HeuristicsForMemberFunctionCompletion) {
   for (const auto &P : Code.points("canNotBeCall")) {
     auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
     EXPECT_THAT(Results.Completions,
-                Contains(AllOf(named("method"), signature("(int) const"),
+                Contains(AllOf(named("method"), signature("(int name) const"),
                                snippetSuffix(""))));
-    // We don't have any arguments to deduce against if this isn't a call.
-    // Thus, we should emit these deducible template arguments explicitly.
     EXPECT_THAT(
         Results.Completions,
         Contains(AllOf(named("generic"),
-                       signature("<typename T, typename U>(U, V)"),
+                       signature("<typename T, typename U>(U nameU, V nameV)"),
                        snippetSuffix("<${1:typename T}, ${2:typename U}>"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("staticMethod"), signature("(int name)"),
+                               snippetSuffix(""))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(
+                    named("staticGeneric"), signature("<typename T, int U>()"),
+                    snippetSuffix("<${1:typename T}, ${2:int U}>"))));
   }
 
   for (const auto &P : Code.points("canBeCall")) {
     auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
     EXPECT_THAT(Results.Completions,
-                Contains(AllOf(named("method"), signature("(int) const"),
-                               snippetSuffix("(${1:int})"))));
+                Contains(AllOf(named("method"), signature("(int name) const"),
+                               snippetSuffix("(${1:int name})"))));
+    EXPECT_THAT(
+        Results.Completions,
+        Contains(AllOf(
+            named("generic"), signature("<typename T>(U nameU, V nameV)"),
+            snippetSuffix("<${1:typename T}>(${2:U nameU}, ${3:V nameV})"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("staticMethod"), signature("(int name)"),
+                               snippetSuffix("(${1:int name})"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(
+                    named("staticGeneric"), signature("<typename T, int U>()"),
+                    snippetSuffix("<${1:typename T}, ${2:int U}>()"))));
+  }
+
+  for (const auto &P : Code.points("canBeCallNoStatic")) {
+    auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("method"), signature("(int name) const"),
+                               snippetSuffix("(${1:int name})"))));
     EXPECT_THAT(
         Results.Completions,
-        Contains(AllOf(named("generic"), signature("<typename T>(U, V)"),
-                       snippetSuffix("<${1:typename T}>(${2:U}, ${3:V})"))));
+        Contains(AllOf(
+            named("generic"), signature("<typename T>(U nameU, V nameV)"),
+            snippetSuffix("<${1:typename T}>(${2:U nameU}, ${3:V nameV})"))));
   }
 
-  // static method will always keep the snippet
-  for (const auto &P : Code.points()) {
+  for (const auto &P : Code.points("canBeCallStaticOnly")) {
     auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
     EXPECT_THAT(Results.Completions,
-                Contains(AllOf(named("staticMethod"), signature("(int)"),
-                               snippetSuffix("(${1:int})"))));
+                Contains(AllOf(named("method"), signature("(int name) const"),
+                               snippetSuffix(""))));
+    EXPECT_THAT(
+        Results.Completions,
+        Contains(AllOf(named("generic"),
+                       signature("<typename T, typename U>(U nameU, V nameV)"),
+                       snippetSuffix("<${1:typename T}, ${2:typename U}>"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("staticMethod"), signature("(int name)"),
+                               snippetSuffix("(${1:int name})"))));
     EXPECT_THAT(Results.Completions,
                 Contains(AllOf(
                     named("staticGeneric"), signature("<typename T, int U>()"),
                     snippetSuffix("<${1:typename T}, ${2:int U}>()"))));
   }
+
+  for (const auto &P : Code.points("isDefinition")) {
+    auto Results = completions(TU, P, /*IndexSymbols*/ {}, Opts);
+
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("method"), signature("(int name) const"),
+                               snippetSuffix("(int name) const"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("generic"),
+                               signature("<typename T>(U nameU, V nameV)"),
+                               snippetSuffix("(U nameU, V nameV)"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("staticMethod"), signature("(int name)"),
+                               snippetSuffix("(int name)"))));
+    EXPECT_THAT(Results.Completions,
+                Contains(AllOf(named("staticGeneric"),
+                               signature("<typename T, int U>()"),
+                               snippetSuffix("()"))));
+  }
+}
+
+TEST(CompletionTest, PrivateMemberDefinition) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.EnableSnippets = true;
+  auto Results = completions(
+      R"cpp(
+    class Foo {
+        int func(int a, int b);
+    };
+    int Foo::func^
+  )cpp",
+      /*IndexSymbols=*/{}, Opts);
+  EXPECT_THAT(Results.Completions,
+              Contains(AllOf(named("func"), signature("(int a, int b)"),
+                             snippetSuffix("(int a, int b)"))));
+}
+
+TEST(CompletionTest, DefaultArgsWithValues) {
+  clangd::CodeCompleteOptions Opts;
+  Opts.EnableSnippets = true;
+  auto Results = completions(
+      R"cpp(
+    struct Arg {
+        Arg(int a, int b);
+    };
+    struct Foo {
+      void foo(int x = 42, int y = 0, Arg arg = Arg(42,  0));
+    };
+    void Foo::foo^
+  )cpp",
+      /*IndexSymbols=*/{}, Opts);
+  EXPECT_THAT(Results.Completions,
+              Contains(AllOf(
+                  named("foo"),
+                  signature("(int x = 42, int y = 0, Arg arg = Arg(42,  0))"),
+                  snippetSuffix("(int x, int y, Arg arg)"))));
 }
 
 TEST(CompletionTest, NoSnippetsInUsings) {
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 5ae02e2b4e8ad..12f9e30d5fad3 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -356,7 +356,14 @@ class Parser : public CodeCompletionHandler {
   /// are invalid.
   bool
   TryAnnotateTypeOrScopeToken(ImplicitTypenameContext AllowImplicitTypename =
-                                  ImplicitTypenameContext::No);
+                                  ImplicitTypenameContext::No,
+                              bool IsAddressOfOperand = false);
+
+  bool TryAnnotateTypeOrScopeToken(bool IsAddressOfOperand) {
+    return TryAnnotateTypeOrScopeToken(
+        /*AllowImplicitTypename=*/ImplicitTypenameContext::No,
+        /*IsAddressOfOperand=*/IsAddressOfOperand);
+  }
 
   /// Try to annotate a type or scope token, having already parsed an
   /// optional scope specifier. \p IsNewScope should be \c true unless the 
scope
@@ -4568,7 +4575,23 @@ class Parser : public CodeCompletionHandler {
       bool EnteringContext, bool *MayBePseudoDestructor = nullptr,
       bool IsTypename = false, const IdentifierInfo **LastII = nullptr,
       bool OnlyNamespace = false, bool InUsingDeclaration = false,
-      bool Disambiguation = false);
+      bool Disambiguation = false, bool IsAddressOfOperand = false,
+      bool IsInDeclarationContext = false);
+
+  bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType,
+                                      bool ObjectHasErrors,
+                                      bool EnteringContext,
+                                      bool IsAddressOfOperand) {
+    return ParseOptionalCXXScopeSpecifier(
+        SS, ObjectType, ObjectHasErrors, EnteringContext,
+        /*MayBePseudoDestructor=*/nullptr,
+        /*IsTypename=*/false,
+        /*LastII=*/nullptr,
+        /*OnlyNamespace=*/false,
+        /*InUsingDeclaration=*/false,
+        /*Disambiguation=*/false,
+        /*IsAddressOfOperand=*/IsAddressOfOperand);
+  }
 
   
//===--------------------------------------------------------------------===//
   // C++11 5.1.2: Lambda expressions
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h 
b/clang/include/clang/Sema/CodeCompleteConsumer.h
index c26f4e33d289c..babb7288247d2 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -865,6 +865,9 @@ class CodeCompletionResult {
   /// be a call.
   bool FunctionCanBeCall : 1;
 
+  /// Whether the completion expects the address of the operand.
+  bool IsAddressOfOperand : 1;
+
   /// If the result should have a nested-name-specifier, this is it.
   /// When \c QualifierIsInformative, the nested-name-specifier is
   /// informative rather than required.
@@ -891,7 +894,8 @@ class CodeCompletionResult {
         FixIts(std::move(FixIts)), Hidden(false), InBaseClass(false),
         QualifierIsInformative(QualifierIsInformative),
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        DeclaringEntity(false), FunctionCanBeCall(true), Qualifier(Qualifier) {
+        DeclaringEntity(false), FunctionCanBeCall(true),
+        IsAddressOfOperand(false), Qualifier(Qualifier) {
     // FIXME: Add assert to check FixIts range requirements.
     computeCursorKindAndAvailability(Accessible);
   }
@@ -902,7 +906,7 @@ class CodeCompletionResult {
         CursorKind(CXCursor_NotImplemented), Hidden(false), InBaseClass(false),
         QualifierIsInformative(false), StartsNestedNameSpecifier(false),
         AllParametersAreInformative(false), DeclaringEntity(false),
-        FunctionCanBeCall(true) {}
+        FunctionCanBeCall(true), IsAddressOfOperand(false) {}
 
   /// Build a result that refers to a macro.
   CodeCompletionResult(const IdentifierInfo *Macro,
@@ -912,7 +916,7 @@ class CodeCompletionResult {
         CursorKind(CXCursor_MacroDefinition), Hidden(false), 
InBaseClass(false),
         QualifierIsInformative(false), StartsNestedNameSpecifier(false),
         AllParametersAreInformative(false), DeclaringEntity(false),
-        FunctionCanBeCall(true), MacroDefInfo(MI) {}
+        FunctionCanBeCall(true), IsAddressOfOperand(false), MacroDefInfo(MI) {}
 
   /// Build a result that refers to a pattern.
   CodeCompletionResult(
@@ -924,7 +928,8 @@ class CodeCompletionResult {
         CursorKind(CursorKind), Availability(Availability), Hidden(false),
         InBaseClass(false), QualifierIsInformative(false),
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        DeclaringEntity(false), FunctionCanBeCall(true) {}
+        DeclaringEntity(false), FunctionCanBeCall(true),
+        IsAddressOfOperand(false) {}
 
   /// Build a result that refers to a pattern with an associated
   /// declaration.
@@ -933,7 +938,8 @@ class CodeCompletionResult {
       : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern),
         Hidden(false), InBaseClass(false), QualifierIsInformative(false),
         StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
-        DeclaringEntity(false), FunctionCanBeCall(true) {
+        DeclaringEntity(false), FunctionCanBeCall(true),
+        IsAddressOfOperand(false) {
     computeCursorKindAndAvailability();
   }
 
diff --git a/clang/include/clang/Sema/SemaCodeCompletion.h 
b/clang/include/clang/Sema/SemaCodeCompletion.h
index 3029e56e5cfe2..abdfb51900318 100644
--- a/clang/include/clang/Sema/SemaCodeCompletion.h
+++ b/clang/include/clang/Sema/SemaCodeCompletion.h
@@ -101,9 +101,11 @@ class SemaCodeCompletion : public SemaBase {
                             bool AllowNestedNameSpecifiers);
 
   struct CodeCompleteExpressionData;
-  void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData 
&Data);
+  void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data,
+                              bool IsAddressOfOperand = false);
   void CodeCompleteExpression(Scope *S, QualType PreferredType,
-                              bool IsParenthesized = false);
+                              bool IsParenthesized = false,
+                              bool IsAddressOfOperand = false);
   void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase,
                                        SourceLocation OpLoc, bool IsArrow,
                                        bool IsBaseExprStatement,
@@ -156,7 +158,8 @@ class SemaCodeCompletion : public SemaBase {
   void CodeCompleteAfterIf(Scope *S, bool IsBracedThen);
 
   void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool 
EnteringContext,
-                               bool IsUsingDeclaration, QualType BaseType,
+                               bool IsUsingDeclaration, bool 
IsAddressOfOperand,
+                               bool IsInDeclarationContext, QualType BaseType,
                                QualType PreferredType);
   void CodeCompleteUsing(Scope *S);
   void CodeCompleteUsingDirective(Scope *S);
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index d0d006a78274e..2d489fbbf497b 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -6415,7 +6415,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
                                        /*IsTypename=*/false, 
/*LastII=*/nullptr,
                                        /*OnlyNamespace=*/false,
                                        /*InUsingDeclaration=*/false,
-                                       /*Disambiguation=*/EnteringContext) ||
+                                       /*Disambiguation=*/EnteringContext,
+                                       /*IsAddressOfOperand=*/false,
+                                       /*IsInDeclarationContext=*/true) ||
 
         SS.isEmpty() || SS.isInvalid() || !EnteringContext ||
         Tok.is(tok::star)) {
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index be6c7824cdbae..9c4dfe83fd622 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -923,7 +923,7 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool 
isAddressOfOperand,
                Next.isOneOf(tok::coloncolon, tok::less, tok::l_paren,
                             tok::l_brace)) {
         // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
-        if (TryAnnotateTypeOrScopeToken())
+        if (TryAnnotateTypeOrScopeToken(isAddressOfOperand))
           return ExprError();
         if (!Tok.is(tok::identifier))
           return ParseCastExpression(ParseKind, isAddressOfOperand, 
NotCastExpr,
@@ -1560,7 +1560,8 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool 
isAddressOfOperand,
   case tok::code_completion: {
     cutOffParsing();
     Actions.CodeCompletion().CodeCompleteExpression(
-        getCurScope(), PreferredType.get(Tok.getLocation()));
+        getCurScope(), PreferredType.get(Tok.getLocation()),
+        /*IsParenthesized=*/false, /*IsAddressOfOperand=*/isAddressOfOperand);
     return ExprError();
   }
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index b3d50daf66b10..d0d9def01a4c2 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -108,7 +108,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
     CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors,
     bool EnteringContext, bool *MayBePseudoDestructor, bool IsTypename,
     const IdentifierInfo **LastII, bool OnlyNamespace, bool InUsingDeclaration,
-    bool Disambiguation) {
+    bool Disambiguation, bool IsAddressOfOperand, bool IsInDeclarationContext) 
{
   assert(getLangOpts().CPlusPlus &&
          "Call sites of this function should be guarded by checking for C++");
 
@@ -237,7 +237,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(
         // completion token follows the '::'.
         Actions.CodeCompletion().CodeCompleteQualifiedId(
             getCurScope(), SS, EnteringContext, InUsingDeclaration,
-            ObjectType.get(), SavedType.get(SS.getBeginLoc()));
+            IsAddressOfOperand, IsInDeclarationContext, ObjectType.get(),
+            SavedType.get(SS.getBeginLoc()));
         // Include code completion token into the range of the scope otherwise
         // when we try to annotate the scope tokens the dangling code 
completion
         // token will cause assertion in
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 5d18414b1a746..c4f745612e06c 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1853,7 +1853,7 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) 
{
 }
 
 bool Parser::TryAnnotateTypeOrScopeToken(
-    ImplicitTypenameContext AllowImplicitTypename) {
+    ImplicitTypenameContext AllowImplicitTypename, bool IsAddressOfOperand) {
   assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
           Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) ||
           Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) ||
@@ -1969,9 +1969,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(
 
   CXXScopeSpec SS;
   if (getLangOpts().CPlusPlus)
-    if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
-                                       /*ObjectHasErrors=*/false,
-                                       /*EnteringContext*/ false))
+    if (ParseOptionalCXXScopeSpecifier(
+            SS, /*ObjectType=*/nullptr,
+            /*ObjectHasErrors=*/false,
+            /*EnteringContext=*/false,
+            /*IsAddressOfOperand=*/IsAddressOfOperand))
       return true;
 
   return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation,
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp 
b/clang/lib/Sema/SemaCodeComplete.cpp
index 1a7564eab99cd..696507507f92e 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -369,7 +369,8 @@ class ResultBuilder {
   /// \param BaseExprType the type of expression that precedes the "." or "->"
   /// in a member access expression.
   void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
-                 bool InBaseClass, QualType BaseExprType);
+                 bool InBaseClass, QualType BaseExprType,
+                 bool IsInDeclarationContext, bool IsAddressOfOperand);
 
   /// Add a new non-declaration result to this result set.
   void AddResult(Result R);
@@ -1365,7 +1366,9 @@ bool ResultBuilder::canFunctionBeCalled(const NamedDecl 
*ND,
 
 void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
                               NamedDecl *Hiding, bool InBaseClass = false,
-                              QualType BaseExprType = QualType()) {
+                              QualType BaseExprType = QualType(),
+                              bool IsInDeclarationContext = false,
+                              bool IsAddressOfOperand = false) {
   if (R.Kind != Result::RK_Declaration) {
     // For non-declaration results, just add the result.
     Results.push_back(R);
@@ -1503,8 +1506,27 @@ void ResultBuilder::AddResult(Result R, DeclContext 
*CurContext,
         }
         OverloadSet.Add(Method, Results.size());
       }
-
-  R.FunctionCanBeCall = canFunctionBeCalled(R.getDeclaration(), BaseExprType);
+  R.DeclaringEntity = IsInDeclarationContext;
+  R.IsAddressOfOperand = IsAddressOfOperand;
+  R.FunctionCanBeCall = canFunctionBeCalled(R.getDeclaration(), BaseExprType) 
||
+                        IsInDeclarationContext;
+
+  // We need to force IsAddressOfOperand when completing a ScopeSpecifier
+  // for non static member function that could be a call.
+  if (!IsInDeclarationContext && !IsAddressOfOperand) { // it may be a call
+    const CXXMethodDecl *Method =
+        llvm::dyn_cast<clang::CXXMethodDecl>(R.Declaration);
+    if (!Method) {
+      if (auto *FTD =
+              llvm::dyn_cast<clang::FunctionTemplateDecl>(R.Declaration)) {
+        Method = llvm::dyn_cast<clang::CXXMethodDecl>(FTD->getTemplatedDecl());
+      }
+    }
+    if (Method) {
+      // No call completion after :: for non static member function.
+      R.IsAddressOfOperand = !Method->isStatic() && BaseExprType.isNull();
+    }
+  }
 
   // Insert this result into the set of results.
   Results.push_back(R);
@@ -1762,7 +1784,8 @@ class CodeCompletionDeclConsumer : public 
VisibleDeclConsumer {
       QualType BaseType = QualType(),
       std::vector<FixItHint> FixIts = std::vector<FixItHint>())
       : Results(Results), InitialLookupCtx(InitialLookupCtx),
-        FixIts(std::move(FixIts)) {
+        FixIts(std::move(FixIts)), IsInDeclarationContext(false),
+        IsAddressOfOperand(false) {
     NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
     // If BaseType was not provided explicitly, emulate implicit 'this->'.
     if (BaseType.isNull()) {
@@ -1777,13 +1800,22 @@ class CodeCompletionDeclConsumer : public 
VisibleDeclConsumer {
     this->BaseType = BaseType;
   }
 
+  void setIsInDeclarationContext(bool IsInDeclarationContext) {
+    this->IsInDeclarationContext = IsInDeclarationContext;
+  }
+
+  void setIsAddressOfOperand(bool isAddressOfOperand) {
+    IsAddressOfOperand = isAddressOfOperand;
+  }
+
   void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
                  bool InBaseClass) override {
     ResultBuilder::Result Result(ND, Results.getBasePriority(ND),
                                  /*Qualifier=*/std::nullopt,
                                  /*QualifierIsInformative=*/false,
                                  IsAccessible(ND, Ctx), FixIts);
-    Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass, BaseType);
+    Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass, BaseType,
+                      IsInDeclarationContext, IsAddressOfOperand);
   }
 
   void EnteredContext(DeclContext *Ctx) override {
@@ -1791,6 +1823,8 @@ class CodeCompletionDeclConsumer : public 
VisibleDeclConsumer {
   }
 
 private:
+  bool IsInDeclarationContext;
+  bool IsAddressOfOperand;
   bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
     // Naming class to use for access check. In most cases it was provided
     // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
@@ -3273,18 +3307,18 @@ static std::string GetDefaultValueString(const 
ParmVarDecl *Param,
 }
 
 /// Add function parameter chunks to the given code completion string.
-static void AddFunctionParameterChunks(Preprocessor &PP,
-                                       const PrintingPolicy &Policy,
-                                       const FunctionDecl *Function,
-                                       CodeCompletionBuilder &Result,
-                                       unsigned Start = 0,
-                                       bool InOptional = false) {
+static void AddFunctionParameterChunks(
+    Preprocessor &PP, const PrintingPolicy &Policy,
+    const FunctionDecl *Function, CodeCompletionBuilder &Result,
+    unsigned Start = 0, bool InOptional = false, bool OnlyInformative = false,
+    bool IsInDeclarationContext = false) {
   bool FirstParameter = true;
 
   for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
     const ParmVarDecl *Param = Function->getParamDecl(P);
 
-    if (Param->hasDefaultArg() && !InOptional) {
+    if (Param->hasDefaultArg() && !InOptional && !IsInDeclarationContext &&
+        !OnlyInformative) {
       // When we see an optional default argument, put that argument and
       // the remaining default arguments into a new, optional string.
       CodeCompletionBuilder Opt(Result.getAllocator(),
@@ -3305,23 +3339,42 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
 
     if (FirstParameter)
       FirstParameter = false;
-    else
-      Result.AddChunk(CodeCompletionString::CK_Comma);
+    else {
+      if (OnlyInformative)
+        Result.AddInformativeChunk(", ");
+      else
+        Result.AddChunk(CodeCompletionString::CK_Comma);
+    }
 
     InOptional = false;
 
     // Format the placeholder string.
     std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
-    if (Param->hasDefaultArg())
-      PlaceholderStr +=
-          GetDefaultValueString(Param, PP.getSourceManager(), 
PP.getLangOpts());
+    std::string DefaultValue;
+    if (Param->hasDefaultArg()) {
+      if (IsInDeclarationContext)
+        DefaultValue = GetDefaultValueString(Param, PP.getSourceManager(),
+                                             PP.getLangOpts());
+      else
+        PlaceholderStr += GetDefaultValueString(Param, PP.getSourceManager(),
+                                                PP.getLangOpts());
+    }
 
     if (Function->isVariadic() && P == N - 1)
       PlaceholderStr += ", ...";
 
     // Add the placeholder string.
-    Result.AddPlaceholderChunk(
-        Result.getAllocator().CopyString(PlaceholderStr));
+    if (OnlyInformative)
+      Result.AddInformativeChunk(
+          Result.getAllocator().CopyString(PlaceholderStr));
+    else if (IsInDeclarationContext) { // No placeholders in declaration 
context
+      Result.AddTextChunk(Result.getAllocator().CopyString(PlaceholderStr));
+      if (DefaultValue.length() != 0)
+        Result.AddInformativeChunk(
+            Result.getAllocator().CopyString(DefaultValue));
+    } else
+      Result.AddPlaceholderChunk(
+          Result.getAllocator().CopyString(PlaceholderStr));
   }
 
   if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
@@ -3337,7 +3390,8 @@ static void AddFunctionParameterChunks(Preprocessor &PP,
 static void AddTemplateParameterChunks(
     ASTContext &Context, const PrintingPolicy &Policy,
     const TemplateDecl *Template, CodeCompletionBuilder &Result,
-    unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) 
{
+    unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false,
+    bool OnlyInformative = false) {
   bool FirstParameter = true;
 
   // Prefer to take the template parameter names from the first declaration of
@@ -3388,7 +3442,7 @@ static void AddTemplateParameterChunks(
       HasDefaultArg = TTP->hasDefaultArgument();
     }
 
-    if (HasDefaultArg && !InDefaultArg) {
+    if (HasDefaultArg && !InDefaultArg && !OnlyInformative) {
       // When we see an optional default argument, put that argument and
       // the remaining default arguments into a new, optional string.
       CodeCompletionBuilder Opt(Result.getAllocator(),
@@ -3405,12 +3459,19 @@ static void AddTemplateParameterChunks(
 
     if (FirstParameter)
       FirstParameter = false;
-    else
-      Result.AddChunk(CodeCompletionString::CK_Comma);
+    else {
+      if (OnlyInformative)
+        Result.AddInformativeChunk(", ");
+      else
+        Result.AddChunk(CodeCompletionString::CK_Comma);
+    }
 
-    // Add the placeholder string.
-    Result.AddPlaceholderChunk(
-        Result.getAllocator().CopyString(PlaceholderStr));
+    if (OnlyInformative)
+      Result.AddInformativeChunk(
+          Result.getAllocator().CopyString(PlaceholderStr));
+    else // Add the placeholder string.
+      Result.AddPlaceholderChunk(
+          Result.getAllocator().CopyString(PlaceholderStr));
   }
 }
 
@@ -3436,22 +3497,32 @@ static void 
AddQualifierToCompletionString(CodeCompletionBuilder &Result,
 }
 
 static void AddFunctionTypeQuals(CodeCompletionBuilder &Result,
-                                 const Qualifiers Quals) {
+                                 const Qualifiers Quals,
+                                 bool AsInformativeChunks = true) {
   // FIXME: Add ref-qualifier!
 
   // Handle single qualifiers without copying
   if (Quals.hasOnlyConst()) {
-    Result.AddInformativeChunk(" const");
+    if (AsInformativeChunks)
+      Result.AddInformativeChunk(" const");
+    else
+      Result.AddTextChunk(" const");
     return;
   }
 
   if (Quals.hasOnlyVolatile()) {
-    Result.AddInformativeChunk(" volatile");
+    if (AsInformativeChunks)
+      Result.AddInformativeChunk(" volatile");
+    else
+      Result.AddTextChunk(" volatile");
     return;
   }
 
   if (Quals.hasOnlyRestrict()) {
-    Result.AddInformativeChunk(" restrict");
+    if (AsInformativeChunks)
+      Result.AddInformativeChunk(" restrict");
+    else
+      Result.AddTextChunk(" restrict");
     return;
   }
 
@@ -3463,12 +3534,17 @@ static void AddFunctionTypeQuals(CodeCompletionBuilder 
&Result,
     QualsStr += " volatile";
   if (Quals.hasRestrict())
     QualsStr += " restrict";
-  Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+
+  if (AsInformativeChunks)
+    Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
+  else
+    Result.AddTextChunk(Result.getAllocator().CopyString(QualsStr));
 }
 
 static void
 AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
-                                       const FunctionDecl *Function) {
+                                       const FunctionDecl *Function,
+                                       bool AsInformativeChunks = true) {
   if (auto *CxxMethodDecl = llvm::dyn_cast_if_present<CXXMethodDecl>(Function);
       CxxMethodDecl && CxxMethodDecl->hasCXXExplicitFunctionObjectParameter()) 
{
     // if explicit object method, infer quals from the object parameter
@@ -3476,13 +3552,13 @@ 
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
     if (!Quals.hasQualifiers())
       return;
 
-    AddFunctionTypeQuals(Result, Quals.getQualifiers());
+    AddFunctionTypeQuals(Result, Quals.getQualifiers(), AsInformativeChunks);
   } else {
     const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
     if (!Proto || !Proto->getMethodQuals())
       return;
 
-    AddFunctionTypeQuals(Result, Proto->getMethodQuals());
+    AddFunctionTypeQuals(Result, Proto->getMethodQuals(), AsInformativeChunks);
   }
 }
 
@@ -3774,10 +3850,20 @@ CodeCompletionString 
*CodeCompletionResult::createCodeCompletionStringForDecl(
     AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
                                    Ctx, Policy);
     AddTypedNameChunk(Ctx, Policy, ND, Result);
-    Result.AddChunk(CodeCompletionString::CK_LeftParen);
-    AddFunctionParameterChunks(PP, Policy, Function, Result);
-    Result.AddChunk(CodeCompletionString::CK_RightParen);
-    AddFunctionTypeQualsToCompletionString(Result, Function);
+    if (!IsAddressOfOperand)
+      Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    else
+      Result.AddInformativeChunk("(");
+    AddFunctionParameterChunks(PP, Policy, Function, Result, /*Start=*/0,
+                               /*InOptional=*/false,
+                               /*OnlyInformative=*/IsAddressOfOperand,
+                               /*IsInDeclarationContext=*/DeclaringEntity);
+    if (!IsAddressOfOperand)
+      Result.AddChunk(CodeCompletionString::CK_RightParen);
+    else
+      Result.AddInformativeChunk(")");
+    AddFunctionTypeQualsToCompletionString(
+        Result, Function, /*AsInformativeChunks=*/!DeclaringEntity);
   };
 
   if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
@@ -3849,16 +3935,34 @@ CodeCompletionString 
*CodeCompletionResult::createCodeCompletionStringForDecl(
       // e.g.,
       // template <class T> void foo(T);
       // void (*f)(int) = foo;
-      Result.AddChunk(CodeCompletionString::CK_LeftAngle);
-      AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
-                                 LastDeducibleArgument);
-      Result.AddChunk(CodeCompletionString::CK_RightAngle);
+      if (!DeclaringEntity)
+        Result.AddChunk(CodeCompletionString::CK_LeftAngle);
+      else
+        Result.AddInformativeChunk("<");
+      AddTemplateParameterChunks(
+          Ctx, Policy, FunTmpl, Result, LastDeducibleArgument, /*Start=*/0,
+          /*InDefaultArg=*/false, /*OnlyInformative=*/DeclaringEntity);
+      // Only adds template arguments as informative chunks in declaration
+      // context.
+      if (!DeclaringEntity)
+        Result.AddChunk(CodeCompletionString::CK_RightAngle);
+      else
+        Result.AddInformativeChunk(">");
     }
 
     // Add the function parameters
-    Result.AddChunk(CodeCompletionString::CK_LeftParen);
-    AddFunctionParameterChunks(PP, Policy, Function, Result);
-    Result.AddChunk(CodeCompletionString::CK_RightParen);
+    if (!IsAddressOfOperand)
+      Result.AddChunk(CodeCompletionString::CK_LeftParen);
+    else
+      Result.AddInformativeChunk("(");
+    AddFunctionParameterChunks(PP, Policy, Function, Result, /*Start=*/0,
+                               /*InOptional=*/false,
+                               /*OnlyInformative=*/IsAddressOfOperand,
+                               /*IsInDeclarationContext=*/DeclaringEntity);
+    if (!IsAddressOfOperand)
+      Result.AddChunk(CodeCompletionString::CK_RightParen);
+    else
+      Result.AddInformativeChunk(")");
     AddFunctionTypeQualsToCompletionString(Result, Function);
     return Result.TakeString();
   }
@@ -5073,7 +5177,7 @@ static void AddLambdaCompletion(ResultBuilder &Results,
 /// Perform code-completion in an expression context when we know what
 /// type we're looking for.
 void SemaCodeCompletion::CodeCompleteExpression(
-    Scope *S, const CodeCompleteExpressionData &Data) {
+    Scope *S, const CodeCompleteExpressionData &Data, bool IsAddressOfOperand) 
{
   ResultBuilder Results(
       SemaRef, CodeCompleter->getAllocator(),
       CodeCompleter->getCodeCompletionTUInfo(),
@@ -5101,6 +5205,7 @@ void SemaCodeCompletion::CodeCompleteExpression(
     Results.Ignore(Data.IgnoreDecls[I]);
 
   CodeCompletionDeclConsumer Consumer(Results, SemaRef.CurContext);
+  Consumer.setIsAddressOfOperand(IsAddressOfOperand);
   SemaRef.LookupVisibleDecls(S, Sema::LookupOrdinaryName, Consumer,
                              CodeCompleter->includeGlobals(),
                              CodeCompleter->loadExternal());
@@ -5144,9 +5249,11 @@ void SemaCodeCompletion::CodeCompleteExpression(
 
 void SemaCodeCompletion::CodeCompleteExpression(Scope *S,
                                                 QualType PreferredType,
-                                                bool IsParenthesized) {
+                                                bool IsParenthesized,
+                                                bool IsAddressOfOperand) {
   return CodeCompleteExpression(
-      S, CodeCompleteExpressionData(PreferredType, IsParenthesized));
+      S, CodeCompleteExpressionData(PreferredType, IsParenthesized),
+      IsAddressOfOperand);
 }
 
 void SemaCodeCompletion::CodeCompletePostfixExpression(Scope *S, ExprResult E,
@@ -6821,11 +6928,10 @@ void SemaCodeCompletion::CodeCompleteAfterIf(Scope *S, 
bool IsBracedThen) {
                             Results.size());
 }
 
-void SemaCodeCompletion::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
-                                                 bool EnteringContext,
-                                                 bool IsUsingDeclaration,
-                                                 QualType BaseType,
-                                                 QualType PreferredType) {
+void SemaCodeCompletion::CodeCompleteQualifiedId(
+    Scope *S, CXXScopeSpec &SS, bool EnteringContext, bool IsUsingDeclaration,
+    bool IsAddressOfOperand, bool IsInDeclarationContext, QualType BaseType,
+    QualType PreferredType) {
   if (SS.isEmpty() || !CodeCompleter)
     return;
 
@@ -6860,12 +6966,23 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope 
*S, CXXScopeSpec &SS,
   // resolves to a dependent record.
   DeclContext *Ctx = SemaRef.computeDeclContext(SS, /*EnteringContext=*/true);
 
+  DeclContext *SavedContext = nullptr;
+  // When completing a definition, simulate that we are in class scope to 
access
+  // private methods.
+  if (IsInDeclarationContext && Ctx != nullptr) {
+    SavedContext = SemaRef.CurContext;
+    SemaRef.CurContext = Ctx;
+  }
+
   // Try to instantiate any non-dependent declaration contexts before
   // we look in them. Bail out if we fail.
   NestedNameSpecifier NNS = SS.getScopeRep();
   if (NNS && !NNS.isDependent()) {
-    if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx))
+    if (Ctx == nullptr || SemaRef.RequireCompleteDeclContext(SS, Ctx)) {
+      if (SavedContext)
+        SemaRef.CurContext = SavedContext;
       return;
+    }
   }
 
   ResultBuilder Results(SemaRef, CodeCompleter->getAllocator(),
@@ -6906,11 +7023,15 @@ void SemaCodeCompletion::CodeCompleteQualifiedId(Scope 
*S, CXXScopeSpec &SS,
   if (Ctx &&
       (CodeCompleter->includeNamespaceLevelDecls() || !Ctx->isFileContext())) {
     CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
+    Consumer.setIsInDeclarationContext(IsInDeclarationContext);
+    Consumer.setIsAddressOfOperand(IsAddressOfOperand);
     SemaRef.LookupVisibleDecls(Ctx, Sema::LookupOrdinaryName, Consumer,
                                /*IncludeGlobalScope=*/true,
                                /*IncludeDependentBases=*/true,
                                CodeCompleter->loadExternal());
   }
+  if (SavedContext)
+    SemaRef.CurContext = SavedContext;
 
   HandleCodeCompleteResults(&SemaRef, CodeCompleter,
                             Results.getCompletionContext(), Results.data(),
diff --git a/clang/test/CodeCompletion/cpp23-explicit-object.cpp 
b/clang/test/CodeCompletion/cpp23-explicit-object.cpp
index ea97237ecd24b..82888b76fb918 100644
--- a/clang/test/CodeCompletion/cpp23-explicit-object.cpp
+++ b/clang/test/CodeCompletion/cpp23-explicit-object.cpp
@@ -36,9 +36,9 @@ int func3() {
   (&A::bar)
 }
 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-3):10 
-std=c++23 %s | FileCheck -check-prefix=CHECK-CC3 %s
-// CHECK-CC3: COMPLETION: foo : [#void#]foo<<#class self:auto#>>(<#int arg#>)
+// CHECK-CC3: COMPLETION: foo : [#void#]foo<<#class self:auto#>>[#(#][#int 
arg#][#)#]
 // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-4):10 
-std=c++23 %s | FileCheck -check-prefix=CHECK-CC4 %s
-// CHECK-CC4: COMPLETION: bar : [#void#]bar(<#int arg#>)
+// CHECK-CC4: COMPLETION: bar : [#void#]bar[#(#][#int arg#][#)#]
 
 int func4() {
   // TODO (&A::foo)(
diff --git a/clang/test/CodeCompletion/member-access.cpp 
b/clang/test/CodeCompletion/member-access.cpp
index 8526ed7273474..2de96b43ff2ba 100644
--- a/clang/test/CodeCompletion/member-access.cpp
+++ b/clang/test/CodeCompletion/member-access.cpp
@@ -171,7 +171,7 @@ class Template {
 template<typename T>
 void dependentColonColonCompletion() {
   Template<T>::staticFn();
-// CHECK-CC7: function : [#void#]function()
+// CHECK-CC7: function : [#void#]function[#(#][#)#]
 // CHECK-CC7: Nested : Nested
 // CHECK-CC7: o1 : [#BaseTemplate<int>#]o1
 // CHECK-CC7: o2 : [#BaseTemplate<T>#]o2
@@ -352,7 +352,7 @@ namespace function_can_be_call {
     &S::f
   }
   // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:352:9 %s -o - | 
FileCheck -check-prefix=CHECK_FUNCTION_CAN_BE_CALL %s
-  // CHECK_FUNCTION_CAN_BE_CALL: COMPLETION: foo : [#T#]foo<<#typename T#>, 
<#typename U#>>(<#U#>, <#V#>)
+  // CHECK_FUNCTION_CAN_BE_CALL: COMPLETION: foo : [#T#]foo<<#typename T#>, 
<#typename U#>>[#(#][#U#][#, #][#V#][#)#]
 }
 
 namespace deref_dependent_this {
diff --git a/clang/test/Index/complete-qualified.cpp 
b/clang/test/Index/complete-qualified.cpp
index 11abd53b86c28..dcb06439e5778 100644
--- a/clang/test/Index/complete-qualified.cpp
+++ b/clang/test/Index/complete-qualified.cpp
@@ -16,5 +16,5 @@ void foo()
 // RUN: c-index-test -code-completion-at=%s:14:8 %s -o - | FileCheck 
-check-prefix=CHECK-CC1 %s
 // CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35)
 // CHECK-CC1: ClassDecl:{TypedText Foo} (35)
-// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen 
(}{Placeholder const Foo &}{RightParen )}
-// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen 
(}{RightParen )} (80)
+// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{Informative 
(}{Informative const Foo &}{Informative )} (80)
+// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{Informative 
(}{Informative )} (80)

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to