diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -78,6 +78,8 @@ } void onMainAST(PathRef Path, ParsedAST &AST, PublishFn Publish) override { + WithContextValue ASTCtx(ParsedAST::CurrentASTContext, &AST.getASTContext()); + if (FIndex) FIndex->updateMain(Path, AST); diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -8,6 +8,8 @@ #include "FindTarget.h" #include "AST.h" +#include "ParsedAST.h" +#include "support/Context.h" #include "support/Logger.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" @@ -98,21 +100,18 @@ // name (e.g. if it's an operator name), but the caller may not have // access to an ASTContext. std::vector getMembersReferencedViaDependentName( - const Type *T, - llvm::function_ref NameFactory, + const Type *T, DeclarationName Name, llvm::function_ref Filter) { if (!T) return {}; if (auto *ET = T->getAs()) { - auto Result = - ET->getDecl()->lookup(NameFactory(ET->getDecl()->getASTContext())); + auto Result = ET->getDecl()->lookup(Name); return {Result.begin(), Result.end()}; } if (auto *RD = resolveTypeToRecordDecl(T)) { if (!RD->hasDefinition()) return {}; RD = RD->getDefinition(); - DeclarationName Name = NameFactory(RD->getASTContext()); return RD->lookupDependentName(Name, Filter); } return {}; @@ -147,9 +146,9 @@ // smart pointer type. auto ArrowOps = getMembersReferencedViaDependentName( T, - [](ASTContext &Ctx) { - return Ctx.DeclarationNames.getCXXOperatorName(OO_Arrow); - }, + Context::current() + .getExisting(ParsedAST::CurrentASTContext) + ->DeclarationNames.getCXXOperatorName(OO_Arrow), NonStaticFilter); if (ArrowOps.empty()) return nullptr; @@ -194,14 +193,12 @@ BaseType = resolveExprToType(Base); } } - return getMembersReferencedViaDependentName( - BaseType, [ME](ASTContext &) { return ME->getMember(); }, - NonStaticFilter); + return getMembersReferencedViaDependentName(BaseType, ME->getMember(), + NonStaticFilter); } if (const auto *RE = dyn_cast(E)) { return getMembersReferencedViaDependentName( - RE->getQualifier()->getAsType(), - [RE](ASTContext &) { return RE->getDeclName(); }, StaticFilter); + RE->getQualifier()->getAsType(), RE->getDeclName(), StaticFilter); } if (const auto *CE = dyn_cast(E)) { const auto *CalleeType = resolveExprToType(CE->getCallee()); @@ -253,8 +250,7 @@ case NestedNameSpecifier::Identifier: { return resolveDeclsToType(getMembersReferencedViaDependentName( resolveNestedNameSpecifierToType(NNS->getPrefix()), - [&](const ASTContext &) { return NNS->getAsIdentifier(); }, - TypeFilter)); + NNS->getAsIdentifier(), TypeFilter)); } default: break; @@ -380,8 +376,7 @@ } else if (const UnresolvedUsingValueDecl *UUVD = dyn_cast(D)) { for (const NamedDecl *Target : getMembersReferencedViaDependentName( - UUVD->getQualifier()->getAsType(), - [UUVD](ASTContext &) { return UUVD->getNameInfo().getName(); }, + UUVD->getQualifier()->getAsType(), UUVD->getNameInfo().getName(), ValueFilter)) { add(Target, Flags); // no Underlying as this is a non-renaming alias } @@ -567,8 +562,7 @@ void VisitDependentNameType(const DependentNameType *DNT) { for (const NamedDecl *ND : getMembersReferencedViaDependentName( resolveNestedNameSpecifierToType(DNT->getQualifier()), - [DNT](ASTContext &) { return DNT->getIdentifier(); }, - TypeFilter)) { + DNT->getIdentifier(), TypeFilter)) { Outer.add(ND, Flags); } } @@ -576,8 +570,7 @@ const DependentTemplateSpecializationType *DTST) { for (const NamedDecl *ND : getMembersReferencedViaDependentName( resolveNestedNameSpecifierToType(DTST->getQualifier()), - [DTST](ASTContext &) { return DTST->getIdentifier(); }, - TemplateFilter)) { + DTST->getIdentifier(), TemplateFilter)) { Outer.add(ND, Flags); } } diff --git a/clang-tools-extra/clangd/ParsedAST.h b/clang-tools-extra/clangd/ParsedAST.h --- a/clang-tools-extra/clangd/ParsedAST.h +++ b/clang-tools-extra/clangd/ParsedAST.h @@ -26,6 +26,7 @@ #include "Headers.h" #include "Preamble.h" #include "index/CanonicalIncludes.h" +#include "support/Context.h" #include "support/Path.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/PrecompiledPreamble.h" @@ -109,6 +110,10 @@ /// AST. Might be None if no Preamble is used. llvm::Optional preambleVersion() const; + /// This context variable makes available the ASTContext of the AST being + /// operated on currently. + static Key CurrentASTContext; + private: ParsedAST(llvm::StringRef Version, std::shared_ptr Preamble, diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -237,6 +237,8 @@ } // namespace +Key ParsedAST::CurrentASTContext; + llvm::Optional ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr CI, diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -721,6 +721,8 @@ return Action(error(llvm::errc::invalid_argument, "invalid AST")); vlog("ASTWorker running {0} on version {2} of {1}", Name, FileName, FileInputs.Version); + WithContextValue Ctx(ParsedAST::CurrentASTContext, + &(*AST)->getASTContext()); Action(InputsAndAST{FileInputs, **AST}); }; startTask(Name, std::move(Task), /*UpdateType=*/None, Invalidation); diff --git a/clang-tools-extra/clangd/unittests/TestTU.h b/clang-tools-extra/clangd/unittests/TestTU.h --- a/clang-tools-extra/clangd/unittests/TestTU.h +++ b/clang-tools-extra/clangd/unittests/TestTU.h @@ -76,6 +76,10 @@ // to eliminate this option some day. bool OverlayRealFileSystemForModules = false; + // This is used to add the ASTContext of the AST produced by build() to the + // clangd Context. + mutable std::unique_ptr ASTCtx; + // By default, build() will report Error diagnostics as GTest errors. // Suppress this behavior by adding an 'error-ok' comment to the code. ParsedAST build() const; diff --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp --- a/clang-tools-extra/clangd/unittests/TestTU.cpp +++ b/clang-tools-extra/clangd/unittests/TestTU.cpp @@ -139,6 +139,8 @@ break; // Just report first error for simplicity. } } + ASTCtx = std::make_unique(ParsedAST::CurrentASTContext, + &AST->getASTContext()); return std::move(*AST); }