[PATCH] D124688: [clangd] parse all make_unique-like functions in preamble

Tobias Ribizel via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 29 11:00:26 PDT 2022


upsj created this revision.
upsj added a reviewer: nridge.
Herald added subscribers: usaxena95, kadircet, arphaman.
Herald added a project: All.
upsj requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

I am working on support for forwarding parameter names in make_unique-like functions, first for inlay hints, later maybe for signature help.
For that to work generically, I'd like to parse all of these functions in the preamble. Not sure how this impacts performance on large codebases though.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124688

Files:
  clang-tools-extra/clangd/Preamble.cpp


Index: clang-tools-extra/clangd/Preamble.cpp
===================================================================
--- clang-tools-extra/clangd/Preamble.cpp
+++ clang-tools-extra/clangd/Preamble.cpp
@@ -137,14 +137,42 @@
   }
 
   bool shouldSkipFunctionBody(Decl *D) override {
-    // Generally we skip function bodies in preambles for speed.
-    // We can make exceptions for functions that are cheap to parse and
-    // instantiate, widely used, and valuable (e.g. commonly produce errors).
-    if (const auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
-      if (const auto *II = FT->getDeclName().getAsIdentifierInfo())
-        // std::make_unique is trivial, and we diagnose bad constructor calls.
-        if (II->isStr("make_unique") && FT->isInStdNamespace())
-          return false;
+    // Find functions with variadic template arguments:
+    // Any templated function...
+    if (auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
+      // ... with a template parameter pack...
+      if (FT->getTemplateParameters()->hasParameterPack()) {
+        auto PackIt = std::find_if(
+            FT->getInjectedTemplateArgs().begin(),
+            FT->getInjectedTemplateArgs().end(), [](const auto &Arg) {
+              return Arg.getKind() == TemplateArgument::Pack;
+            });
+        assert(PackIt != FT->getInjectedTemplateArgs().end() &&
+               "Can't find parameter pack in argument list!");
+        const auto &Pack = PackIt->getPackAsArray();
+
+        // ... that is a type parameter pack...
+        if (Pack.size() == 1 && Pack[0].getKind() == TemplateArgument::Type) {
+          const auto *PackType =
+              Pack[0].getAsType().getNonPackExpansionType().getTypePtr();
+          const auto *FD = FT->getAsFunction();
+          const auto NumParams = FD->getNumParams();
+          if (NumParams > 0) {
+            const auto *LastParam = FD->getParamDecl(NumParams - 1);
+            // ... with its type matching the last parameter (pack) of the
+            // function (minus references)...
+            if (LastParam->isParameterPack()) {
+              if (LastParam->getType()
+                      .getNonPackExpansionType()
+                      .getNonReferenceType()
+                      .getTypePtr() == PackType) {
+                // ... we need to parse the body
+                return false;
+              }
+            }
+          }
+        }
+      }
     }
     return true;
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D124688.426120.patch
Type: text/x-patch
Size: 2486 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220429/b6c3da6f/attachment-0001.bin>


More information about the cfe-commits mailing list