llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Mythreya Kuricheti (MythreyaK)

<details>
<summary>Changes</summary>

Adds designator hints for direct init

Fixes clangd/clangd#<!-- -->2541 

---
Full diff: https://github.com/llvm/llvm-project/pull/176635.diff


5 Files Affected:

- (modified) clang-tools-extra/clangd/AST.cpp (+17-3) 
- (modified) clang-tools-extra/clangd/AST.h (+2-1) 
- (modified) clang-tools-extra/clangd/Hover.cpp (+9-1) 
- (modified) clang-tools-extra/clangd/InlayHints.cpp (+30-1) 
- (modified) clang-tools-extra/clangd/unittests/InlayHintTests.cpp (+61) 


``````````diff
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 3bcc89d360cdb..d30968f580e2b 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -38,6 +38,7 @@
 #include <iterator>
 #include <optional>
 #include <string>
+#include <utility>
 #include <vector>
 
 namespace clang {
@@ -824,6 +825,11 @@ class ForwardingCallVisitor
     return !Info.has_value();
   }
 
+  bool VisitCXXParenListInitExpr(CXXParenListInitExpr *E) {
+    RecordInfo = E->getType()->getAsCXXRecordDecl();
+    return true;
+  }
+
   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
     auto *Callee = E->getConstructor();
     if (Callee) {
@@ -857,6 +863,7 @@ class ForwardingCallVisitor
 
   // The output of this visitor
   std::optional<ForwardingInfo> Info;
+  const CXXRecordDecl *RecordInfo{};
 
 private:
   // inspects the given callee with the given args to check whether it
@@ -977,7 +984,7 @@ class ForwardingCallVisitor
 
 } // namespace
 
-SmallVector<const ParmVarDecl *>
+std::variant<SmallVector<const ParmVarDecl *>, const CXXRecordDecl *>
 resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) {
   auto Parameters = D->parameters();
   // If the function has a template parameter pack
@@ -1006,9 +1013,15 @@ resolveForwardingParameters(const FunctionDecl *D, 
unsigned MaxDepth) {
       // Find call expressions involving the pack
       ForwardingCallVisitor V{Pack};
       V.TraverseStmt(CurrentFunction->getBody());
+
+      // if fields are direct-initialized, then no more forwarding
+      if (V.RecordInfo)
+        return V.RecordInfo;
+
       if (!V.Info) {
         break;
       }
+
       // If we found something: Fill in non-pack parameters
       auto Info = *V.Info;
       HeadIt = std::copy(Info.Head.begin(), Info.Head.end(), HeadIt);
@@ -1022,7 +1035,8 @@ resolveForwardingParameters(const FunctionDecl *D, 
unsigned MaxDepth) {
         if (const auto *Template = CurrentFunction->getPrimaryTemplate()) {
           bool NewFunction = SeenTemplates.insert(Template).second;
           if (!NewFunction) {
-            return {Parameters.begin(), Parameters.end()};
+            return SmallVector<const ParmVarDecl *>{Parameters.begin(),
+                                                    Parameters.end()};
           }
         }
       }
@@ -1032,7 +1046,7 @@ resolveForwardingParameters(const FunctionDecl *D, 
unsigned MaxDepth) {
     assert(TailIt.base() == HeadIt);
     return Result;
   }
-  return {Parameters.begin(), Parameters.end()};
+  return SmallVector<const ParmVarDecl *>{Parameters.begin(), 
Parameters.end()};
 }
 
 bool isExpandedFromParameterPack(const ParmVarDecl *D) {
diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h
index 2bb4943b6de0b..09fd109515d62 100644
--- a/clang-tools-extra/clangd/AST.h
+++ b/clang-tools-extra/clangd/AST.h
@@ -17,6 +17,7 @@
 #include "index/Symbol.h"
 #include "index/SymbolID.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/SourceLocation.h"
@@ -244,7 +245,7 @@ bool isDeeplyNested(const Decl *D, unsigned MaxDepth = 10);
 /// parameters to another function via variadic template parameters. This can
 /// for example be used to retrieve the constructor parameter ParmVarDecl for a
 /// make_unique or emplace_back call.
-llvm::SmallVector<const ParmVarDecl *>
+std::variant<SmallVector<const ParmVarDecl *>, const CXXRecordDecl *>
 resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth = 10);
 
 /// Checks whether D is instantiated from a function parameter pack
diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 3ce0d6258ea62..86d2b3ee83b25 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -63,6 +63,7 @@
 #include <algorithm>
 #include <optional>
 #include <string>
+#include <variant>
 #include <vector>
 
 namespace clang {
@@ -1062,7 +1063,14 @@ void maybeAddCalleeArgInfo(const SelectionTree::Node *N, 
HoverInfo &HI,
 
   HoverInfo::PassType PassType;
 
-  auto Parameters = resolveForwardingParameters(FD);
+  const auto Params = resolveForwardingParameters(FD);
+
+  auto Parameters = [&]() -> SmallVector<const ParmVarDecl *> {
+    if (std::holds_alternative<SmallVector<const ParmVarDecl *>>(Params)) {
+      return std::get<SmallVector<const ParmVarDecl *>>(Params);
+    }
+    return {};
+  }();
 
   // Find argument index for N.
   for (unsigned I = 0; I < Args.size() && I < Parameters.size(); ++I) {
diff --git a/clang-tools-extra/clangd/InlayHints.cpp 
b/clang-tools-extra/clangd/InlayHints.cpp
index 2290fbd98056d..3d3dbff2a4d14 100644
--- a/clang-tools-extra/clangd/InlayHints.cpp
+++ b/clang-tools-extra/clangd/InlayHints.cpp
@@ -773,11 +773,26 @@ class InlayHintVisitor : public 
RecursiveASTVisitor<InlayHintVisitor> {
     bool HasNonDefaultArgs = false;
 
     ArrayRef<const ParmVarDecl *> Params, ForwardedParams;
+
     // Resolve parameter packs to their forwarded parameter
     SmallVector<const ParmVarDecl *> ForwardedParamsStorage;
+    // If args are direct-initialized
+    const CXXRecordDecl *CxxRecord{};
+
     if (Callee.Decl) {
       Params = maybeDropCxxExplicitObjectParameters(Callee.Decl->parameters());
-      ForwardedParamsStorage = resolveForwardingParameters(Callee.Decl);
+
+      [&]() {
+        auto Params = resolveForwardingParameters(Callee.Decl);
+        if (std::holds_alternative<decltype(ForwardedParamsStorage)>(Params)) {
+          ForwardedParamsStorage =
+              std::get<decltype(ForwardedParamsStorage)>(Params);
+        }
+        if (std::holds_alternative<decltype(CxxRecord)>(Params)) {
+          CxxRecord = std::get<decltype(CxxRecord)>(Params);
+        }
+      }();
+
       ForwardedParams =
           maybeDropCxxExplicitObjectParameters(ForwardedParamsStorage);
     } else {
@@ -787,6 +802,20 @@ class InlayHintVisitor : public 
RecursiveASTVisitor<InlayHintVisitor> {
 
     NameVec ParameterNames = chooseParameterNames(ForwardedParams);
 
+    if (CxxRecord) {
+      const auto ParamArgs = Args.drop_front(CxxRecord->getNumBases());
+      const auto Iter = llvm::zip(ParamArgs, CxxRecord->fields());
+
+      for (const auto &[ParamArg, Field] : Iter) {
+        addInlayHint(ParamArg->getSourceRange(), HintSide::Left,
+                     InlayHintKind::Parameter,
+                     Field->getType()->isReferenceType() ? "&." : ".",
+                     Field->getName(), ": ");
+      }
+
+      return;
+    }
+
     // Exclude setters (i.e. functions with one argument whose name begins with
     // "set"), and builtins like std::move/forward/... as their parameter name
     // is also not likely to be interesting.
diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp 
b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
index 5552aa178a354..f6ed9683fd0db 100644
--- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -1955,6 +1955,67 @@ TEST(ParameterHints, DoesntExpandAllArgs) {
       ExpectedHint{"c: ", "param3"});
 }
 
+TEST(ParameterHints, CXX20AggregateParenInitNoCtor) {
+  assertParameterHints(
+      R"cpp(
+    namespace std { 
+      // This prototype of std::forward is sufficient for clang to recognize it
+      template <typename T> T&& forward(T&);
+    }
+      
+    template<typename T, typename ...Args>
+    T* make_unique(Args&&...args) {
+      return new T(std::forward<Args>(args)...);
+    }
+
+    struct Point {
+      int& x;
+      int y;
+      int z;
+    };
+
+    int foo() {
+      int t = 42;
+      make_unique<Point>($px[[t]], $py[[2]]);
+    }
+  )cpp",
+      ExpectedHint{"&.x: ", "px"}, ExpectedHint{".y: ", "py"});
+}
+
+TEST(ParameterHints, CXX20AggregateParenInitNoCtorDerived) {
+  assertParameterHints(
+      R"cpp(
+    namespace std { 
+      // This prototype of std::forward is sufficient for clang to recognize it
+      template <typename T> T&& forward(T&);
+    }
+      
+    template<typename T, typename ...Args>
+    T* make_unique(Args&&...args) {
+      return new T(std::forward<Args>(args)...);
+    }
+
+    struct Col {
+      unsigned short r {};
+      unsigned short g {};
+      unsigned short b {};
+    };
+
+    struct Point : public Col {
+      int& x;
+      int y;
+      int z;
+    };
+
+    int foo() {
+      Col c {};
+      int t = 42;
+      make_unique<Point>(c, $px[[t]], $py[[2]]);
+    }
+  )cpp",
+      ExpectedHint{"&.x: ", "px"}, ExpectedHint{".y: ", "py"});
+}
+
 TEST(BlockEndHints, Functions) {
   assertBlockEndHints(R"cpp(
     int foo() {

``````````

</details>


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

Reply via email to