upsj updated this revision to Diff 427854.
upsj added a comment.

accidentally pushed to the wrong revision, this is the previous version


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124688/new/

https://reviews.llvm.org/D124688

Files:
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Preamble.cpp
  clang-tools-extra/clangd/Preamble.h
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/tool/Check.cpp
  clang-tools-extra/clangd/tool/ClangdMain.cpp
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
  clang-tools-extra/clangd/unittests/FileIndexTests.cpp
  clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
  clang-tools-extra/clangd/unittests/PreambleTests.cpp
  clang-tools-extra/clangd/unittests/TestTU.cpp

Index: clang-tools-extra/clangd/unittests/TestTU.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/TestTU.cpp
+++ clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -101,7 +101,9 @@
   auto ModuleCacheDeleter = llvm::make_scope_exit(
       std::bind(deleteModuleCache, CI->getHeaderSearchOpts().ModuleCachePath));
   return clang::clangd::buildPreamble(testPath(Filename), *CI, Inputs,
-                                      /*StoreInMemory=*/true, PreambleCallback);
+                                      /*StoreInMemory=*/true,
+                                      /*ParseForwardingFunctions=*/false,
+                                      PreambleCallback);
 }
 
 ParsedAST TestTU::build() const {
@@ -115,9 +117,10 @@
   auto ModuleCacheDeleter = llvm::make_scope_exit(
       std::bind(deleteModuleCache, CI->getHeaderSearchOpts().ModuleCachePath));
 
-  auto Preamble = clang::clangd::buildPreamble(testPath(Filename), *CI, Inputs,
-                                               /*StoreInMemory=*/true,
-                                               /*PreambleCallback=*/nullptr);
+  auto Preamble =
+      clang::clangd::buildPreamble(testPath(Filename), *CI, Inputs,
+                                   /*StoreInMemory=*/true,
+                                   /*PreambleCallback=*/false, nullptr);
   auto AST = ParsedAST::build(testPath(Filename), Inputs, std::move(CI),
                               Diags.take(), Preamble);
   if (!AST.hasValue()) {
Index: clang-tools-extra/clangd/unittests/PreambleTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -173,7 +173,8 @@
   TU.AdditionalFiles["c.h"] = "";
   auto PI = TU.inputs(FS);
   auto BaselinePreamble = buildPreamble(
-      TU.Filename, *buildCompilerInvocation(PI, Diags), PI, true, nullptr);
+      TU.Filename, *buildCompilerInvocation(PI, Diags), PI,
+      /*StoreInMemory=*/true, /*ParseForwardingFunctions=*/false, nullptr);
   // We drop c.h from modified and add a new header. Since the latter is patched
   // we should only get a.h in preamble includes.
   TU.Code = R"cpp(
Index: clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
+++ clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
@@ -497,7 +497,8 @@
   auto Inputs = TU.inputs(FS);
   auto CI = buildCompilerInvocation(Inputs, Diags);
   auto EmptyPreamble =
-      buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
+      buildPreamble(testPath("foo.cpp"), *CI, Inputs, /*StoreInMemory=*/true,
+                    /*PreambleCallback=*/false, nullptr);
   ASSERT_TRUE(EmptyPreamble);
   EXPECT_THAT(EmptyPreamble->Includes.MainFileIncludes, IsEmpty());
 
@@ -540,7 +541,8 @@
   auto Inputs = TU.inputs(FS);
   auto CI = buildCompilerInvocation(Inputs, Diags);
   auto BaselinePreamble =
-      buildPreamble(testPath("foo.cpp"), *CI, Inputs, true, nullptr);
+      buildPreamble(testPath("foo.cpp"), *CI, Inputs, /*StoreInMemory=*/true,
+                    /*PreambleCallback=*/false, nullptr);
   ASSERT_TRUE(BaselinePreamble);
   EXPECT_THAT(BaselinePreamble->Includes.MainFileIncludes,
               ElementsAre(testing::Field(&Inclusion::Written, "<foo.h>")));
Index: clang-tools-extra/clangd/unittests/FileIndexTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FileIndexTests.cpp
+++ clang-tools-extra/clangd/unittests/FileIndexTests.cpp
@@ -306,7 +306,7 @@
   FileIndex Index;
   bool IndexUpdated = false;
   buildPreamble(FooCpp, *CI, PI,
-                /*StoreInMemory=*/true,
+                /*StoreInMemory=*/true, /*ParseForwardingFunctions=*/false,
                 [&](ASTContext &Ctx, Preprocessor &PP,
                     const CanonicalIncludes &CanonIncludes) {
                   EXPECT_FALSE(IndexUpdated)
Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -121,8 +121,10 @@
     ADD_FAILURE() << "Couldn't build CompilerInvocation";
     return {};
   }
-  auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
-                                /*InMemory=*/true, /*Callback=*/nullptr);
+  auto Preamble =
+      buildPreamble(testPath(TU.Filename), *CI, Inputs,
+                    /*StoreInMemory=*/true,
+                    /*PreambleCallback=*/false, /*Callback=*/nullptr);
   return codeComplete(testPath(TU.Filename), Point, Preamble.get(), Inputs,
                       Opts);
 }
@@ -1191,8 +1193,10 @@
     ADD_FAILURE() << "Couldn't build CompilerInvocation";
     return {};
   }
-  auto Preamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
-                                /*InMemory=*/true, /*Callback=*/nullptr);
+  auto Preamble =
+      buildPreamble(testPath(TU.Filename), *CI, Inputs,
+                    /*StoreInMemory=*/true,
+                    /*PreambleCallback=*/false, /*Callback=*/nullptr);
   if (!Preamble) {
     ADD_FAILURE() << "Couldn't build Preamble";
     return {};
@@ -1439,8 +1443,10 @@
   auto Inputs = TU.inputs(FS);
   auto CI = buildCompilerInvocation(Inputs, Diags);
   ASSERT_TRUE(CI);
-  auto EmptyPreamble = buildPreamble(testPath(TU.Filename), *CI, Inputs,
-                                     /*InMemory=*/true, /*Callback=*/nullptr);
+  auto EmptyPreamble =
+      buildPreamble(testPath(TU.Filename), *CI, Inputs,
+                    /*StoreInMemory=*/true,
+                    /*PreambleCallback=*/false, /*Callback=*/nullptr);
   ASSERT_TRUE(EmptyPreamble);
 
   TU.AdditionalFiles["a.h"] = "int foo(int x);";
Index: clang-tools-extra/clangd/tool/ClangdMain.cpp
===================================================================
--- clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -498,6 +498,11 @@
                           Hidden,
                           init(ClangdServer::Options().UseDirtyHeaders)};
 
+opt<bool> PreambleParseForwardingFunctions{
+    "preamble-parse-forwarding", cat(Misc),
+    desc("Parse all make_unique-like functions in the preamble"), Hidden,
+    init(ClangdServer::Options().PreambleParseForwardingFunctions)};
+
 #if defined(__GLIBC__) && CLANGD_MALLOC_TRIM
 opt<bool> EnableMallocTrim{
     "malloc-trim",
@@ -935,6 +940,7 @@
     Opts.ClangTidyProvider = ClangTidyOptProvider;
   }
   Opts.UseDirtyHeaders = UseDirtyHeaders;
+  Opts.PreambleParseForwardingFunctions = PreambleParseForwardingFunctions;
   Opts.QueryDriverGlobs = std::move(QueryDriverGlobs);
   Opts.TweakFilter = [&](const Tweak &T) {
     if (T.hidden() && !HiddenFeatures)
Index: clang-tools-extra/clangd/tool/Check.cpp
===================================================================
--- clang-tools-extra/clangd/tool/Check.cpp
+++ clang-tools-extra/clangd/tool/Check.cpp
@@ -159,6 +159,7 @@
   bool buildAST() {
     log("Building preamble...");
     Preamble = buildPreamble(File, *Invocation, Inputs, /*StoreInMemory=*/true,
+                             Opts.PreambleParseForwardingFunctions,
                              [&](ASTContext &Ctx, Preprocessor &PP,
                                  const CanonicalIncludes &Includes) {
                                if (!Opts.BuildDynamicSymbolIndex)
Index: clang-tools-extra/clangd/TUScheduler.h
===================================================================
--- clang-tools-extra/clangd/TUScheduler.h
+++ clang-tools-extra/clangd/TUScheduler.h
@@ -204,6 +204,9 @@
     /// Typically to inject per-file configuration.
     /// If the path is empty, context sholud be "generic".
     std::function<Context(PathRef)> ContextProvider;
+
+    // If true, parse make_unique-like functions in the preamble.
+    bool PreambleParseForwardingFunctions = false;
   };
 
   TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,
Index: clang-tools-extra/clangd/TUScheduler.cpp
===================================================================
--- clang-tools-extra/clangd/TUScheduler.cpp
+++ clang-tools-extra/clangd/TUScheduler.cpp
@@ -389,11 +389,12 @@
 public:
   PreambleThread(llvm::StringRef FileName, ParsingCallbacks &Callbacks,
                  bool StorePreambleInMemory, bool RunSync,
-                 SynchronizedTUStatus &Status,
+                 bool ParseForwardingFunctions, SynchronizedTUStatus &Status,
                  TUScheduler::HeaderIncluderCache &HeaderIncluders,
                  ASTWorker &AW)
       : FileName(FileName), Callbacks(Callbacks),
-        StoreInMemory(StorePreambleInMemory), RunSync(RunSync), Status(Status),
+        StoreInMemory(StorePreambleInMemory), RunSync(RunSync),
+        ParseForwardingFunctions(ParseForwardingFunctions), Status(Status),
         ASTPeer(AW), HeaderIncluders(HeaderIncluders) {}
 
   /// It isn't guaranteed that each requested version will be built. If there
@@ -518,6 +519,7 @@
   ParsingCallbacks &Callbacks;
   const bool StoreInMemory;
   const bool RunSync;
+  bool ParseForwardingFunctions;
 
   SynchronizedTUStatus &Status;
   ASTWorker &ASTPeer;
@@ -778,7 +780,8 @@
       ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks),
       Barrier(Barrier), Done(false), Status(FileName, Callbacks),
       PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync,
-                   Status, HeaderIncluders, *this) {
+                   Opts.PreambleParseForwardingFunctions, Status,
+                   HeaderIncluders, *this) {
   // Set a fallback command because compile command can be accessed before
   // `Inputs` is initialized. Other fields are only used after initialization
   // from client inputs.
@@ -1012,7 +1015,7 @@
   PreambleBuildStats Stats;
   bool IsFirstPreamble = !LatestBuild;
   LatestBuild = clang::clangd::buildPreamble(
-      FileName, *Req.CI, Inputs, StoreInMemory,
+      FileName, *Req.CI, Inputs, StoreInMemory, ParseForwardingFunctions,
       [this, Version(Inputs.Version)](ASTContext &Ctx, Preprocessor &PP,
                                       const CanonicalIncludes &CanonIncludes) {
         Callbacks.onPreambleAST(FileName, Version, Ctx, PP, CanonIncludes);
Index: clang-tools-extra/clangd/Preamble.h
===================================================================
--- clang-tools-extra/clangd/Preamble.h
+++ clang-tools-extra/clangd/Preamble.h
@@ -100,6 +100,7 @@
 std::shared_ptr<const PreambleData>
 buildPreamble(PathRef FileName, CompilerInvocation CI,
               const ParseInputs &Inputs, bool StoreInMemory,
+              bool ParseForwardingFunctions,
               PreambleParsedCallback PreambleCallback,
               PreambleBuildStats *Stats = nullptr);
 
Index: clang-tools-extra/clangd/Preamble.cpp
===================================================================
--- clang-tools-extra/clangd/Preamble.cpp
+++ clang-tools-extra/clangd/Preamble.cpp
@@ -66,9 +66,10 @@
 public:
   CppFilePreambleCallbacks(
       PathRef File, PreambleParsedCallback ParsedCallback,
-      PreambleBuildStats *Stats,
+      PreambleBuildStats *Stats, bool ParseForwardingFunctions,
       std::function<void(CompilerInstance &)> BeforeExecuteCallback)
       : File(File), ParsedCallback(ParsedCallback), Stats(Stats),
+        ParseForwardingFunctions(ParseForwardingFunctions),
         BeforeExecuteCallback(std::move(BeforeExecuteCallback)) {}
 
   IncludeStructure takeIncludes() { return std::move(Includes); }
@@ -139,12 +140,38 @@
   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;
+    // instantiate, widely used, and valuable (e.g. commonly produce errors,
+    // necessary for code completion/inlay hints).
+    if (auto *FT = llvm::dyn_cast<clang::FunctionTemplateDecl>(D)) {
+      // Fast path: only take care of make_unique
+      if (!ParseForwardingFunctions) {
+        if (const auto *II = FT->getDeclName().getAsIdentifierInfo()) {
+          // std::make_unique is trivial, and we diagnose bad constructor calls.
+          if (FT->isInStdNamespace() && II->isStr("make_unique"))
+            return false;
+        }
+        return true;
+      }
+      // Slow path: Check whether its last parameter is a parameter pack...
+      if (const auto *FD = FT->getAsFunction()) {
+        const auto NumParams = FD->getNumParams();
+        if (NumParams > 0) {
+          const auto *LastParam = FD->getParamDecl(NumParams - 1);
+          if (isa<PackExpansionType>(LastParam->getType())) {
+            const auto *PackTypePtr =
+                dyn_cast<TemplateTypeParmType>(LastParam->getType()
+                                                   .getNonPackExpansionType()
+                                                   .getNonReferenceType()
+                                                   .getTypePtr());
+            // ... whose template parameter comes from the function directly
+            if (FT->getTemplateParameters()->getDepth() ==
+                PackTypePtr->getDepth()) {
+              return false;
+            }
+          }
+        }
+        return true;
+      }
     }
     return true;
   }
@@ -161,6 +188,7 @@
   const clang::LangOptions *LangOpts = nullptr;
   const SourceManager *SourceMgr = nullptr;
   PreambleBuildStats *Stats;
+  bool ParseForwardingFunctions;
   std::function<void(CompilerInstance &)> BeforeExecuteCallback;
 };
 
@@ -426,11 +454,10 @@
 
 } // namespace
 
-std::shared_ptr<const PreambleData>
-buildPreamble(PathRef FileName, CompilerInvocation CI,
-              const ParseInputs &Inputs, bool StoreInMemory,
-              PreambleParsedCallback PreambleCallback,
-              PreambleBuildStats *Stats) {
+std::shared_ptr<const PreambleData> buildPreamble(
+    PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs,
+    bool StoreInMemory, bool ParseForwardingFunctions,
+    PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats) {
   // Note that we don't need to copy the input contents, preamble can live
   // without those.
   auto ContentsBuffer =
@@ -484,6 +511,7 @@
   CI.getPreprocessorOpts().WriteCommentListToPCH = false;
 
   CppFilePreambleCallbacks CapturedInfo(FileName, PreambleCallback, Stats,
+                                        ParseForwardingFunctions,
                                         [&ASTListeners](CompilerInstance &CI) {
                                           for (const auto &L : ASTListeners)
                                             L->beforeExecute(CI);
Index: clang-tools-extra/clangd/ClangdServer.h
===================================================================
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -164,6 +164,9 @@
     /// If true, use the dirty buffer contents when building Preambles.
     bool UseDirtyHeaders = false;
 
+    // If true, parse make_unique-like functions in the preamble.
+    bool PreambleParseForwardingFunctions = false;
+
     explicit operator TUScheduler::Options() const;
   };
   // Sensible default options for use in tests.
@@ -416,6 +419,8 @@
 
   bool UseDirtyHeaders = false;
 
+  bool PreambleParseForwardingFunctions = false;
+
   // GUARDED_BY(CachedCompletionFuzzyFindRequestMutex)
   llvm::StringMap<llvm::Optional<FuzzyFindRequest>>
       CachedCompletionFuzzyFindRequestByFile;
Index: clang-tools-extra/clangd/ClangdServer.cpp
===================================================================
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -137,6 +137,7 @@
   Opts.AsyncThreadsCount = AsyncThreadsCount;
   Opts.RetentionPolicy = RetentionPolicy;
   Opts.StorePreamblesInMemory = StorePreamblesInMemory;
+  Opts.PreambleParseForwardingFunctions = PreambleParseForwardingFunctions;
   Opts.UpdateDebounce = UpdateDebounce;
   Opts.ContextProvider = ContextProvider;
   return Opts;
@@ -148,7 +149,9 @@
     : FeatureModules(Opts.FeatureModules), CDB(CDB), TFS(TFS),
       DynamicIdx(Opts.BuildDynamicSymbolIndex ? new FileIndex() : nullptr),
       ClangTidyProvider(Opts.ClangTidyProvider),
-      UseDirtyHeaders(Opts.UseDirtyHeaders), WorkspaceRoot(Opts.WorkspaceRoot),
+      UseDirtyHeaders(Opts.UseDirtyHeaders),
+      PreambleParseForwardingFunctions(Opts.PreambleParseForwardingFunctions),
+      WorkspaceRoot(Opts.WorkspaceRoot),
       Transient(Opts.ImplicitCancellation ? TUScheduler::InvalidateOnUpdate
                                           : TUScheduler::NoInvalidation),
       DirtyFS(std::make_unique<DraftStoreFS>(TFS, DraftMgr)) {
@@ -910,7 +913,7 @@
           // It's safe to pass in the TU, as dumpAST() does not
           // deserialize the preamble.
           auto Node = DynTypedNode::create(
-                *Inputs->AST.getASTContext().getTranslationUnitDecl());
+              *Inputs->AST.getASTContext().getTranslationUnitDecl());
           return CB(dumpAST(Node, Inputs->AST.getTokens(),
                             Inputs->AST.getASTContext()));
         }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to