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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits