From e5cc5505544d80f6e42664966250c0d1ed8c0201 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 22 Jun 2026 15:42:52 -0400 Subject: [PATCH] Import modified copy of MultiplexExternalSemaSource and drop LLVM patch (#7405) Copy MultiplexExternalSemaSource.h and MultiplexExternalSemaSource.cpp from https://github.com/llvm/llvm-project/pull/204458 into third_party/llvm, and apply a few minor changes to allow them to compile and pass precommit checks. This allows `0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch` to be removed, which brings Carbon closer to being able to compile on an unmodified LLVM toolchain. --- MODULE.bazel | 1 - ...uctor-and-GetSources-method-to-Multi.patch | 60 --- third_party/llvm/BUILD | 11 + .../llvm/multiplex_external_sema_source.cpp | 450 ++++++++++++++++++ .../llvm/multiplex_external_sema_source.h | 424 +++++++++++++++++ toolchain/check/BUILD | 1 + toolchain/check/cpp/generate_ast.cpp | 13 +- 7 files changed, 892 insertions(+), 68 deletions(-) delete mode 100644 bazel/llvm_project/0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch create mode 100644 third_party/llvm/multiplex_external_sema_source.cpp create mode 100644 third_party/llvm/multiplex_external_sema_source.h diff --git a/MODULE.bazel b/MODULE.bazel index f07977485373..3e1f41089af6 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -94,7 +94,6 @@ git_override( "//bazel/llvm_project:0005_Introduce_basic_sources_exporting_for_libcxx_and_libcxxabi.patch", "//bazel/llvm_project:0009_Introduce_starlark_exporting_compiler-rt_build_information.patch", "//bazel/llvm_project:0010_Expose_vptr_init.patch", - "//bazel/llvm_project:0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch", ], remote = "https://github.com/llvm/llvm-project.git", ) diff --git a/bazel/llvm_project/0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch b/bazel/llvm_project/0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch deleted file mode 100644 index e98a01b355a4..000000000000 --- a/bazel/llvm_project/0011-Add-empty-constructor-and-GetSources-method-to-Multi.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 2c7bb43e8800ef29d815f37422a2e56ee0e724b1 Mon Sep 17 00:00:00 2001 -From: Nicholas Bishop -Date: Wed, 10 Jun 2026 20:19:57 -0400 -Subject: [PATCH] Add empty constructor and GetSources method to - MultiplexExternalSemaSource - ---- - .../include/clang/Sema/MultiplexExternalSemaSource.h | 11 ++++++++++- - clang/lib/Sema/MultiplexExternalSemaSource.cpp | 3 +++ - 2 files changed, 13 insertions(+), 1 deletion(-) - -diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h -index 12015724b39f..9230d843e923 100644 ---- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h -+++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h -@@ -39,10 +39,16 @@ class MultiplexExternalSemaSource : public ExternalSemaSource { - /// LLVM-style RTTI. - static char ID; - -+public: -+ using SourceVector = SmallVector, 2>; -+ - private: -- SmallVector, 2> Sources; -+ SourceVector Sources; - - public: -+ /// Constructs an empty multiplexing external sema source. -+ MultiplexExternalSemaSource(); -+ - /// Constructs a new multiplexing external sema source and appends the - /// given element to it. - /// -@@ -58,6 +64,9 @@ public: - /// - void AddSource(llvm::IntrusiveRefCntPtr Source); - -+ /// Returns a reference to the sources vector. -+ SourceVector& GetSources() { return Sources; } -+ - //===--------------------------------------------------------------------===// - // ExternalASTSource. - //===--------------------------------------------------------------------===// -diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp -index be9582ce501f..4306143025c8 100644 ---- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp -+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp -@@ -16,6 +16,9 @@ using namespace clang; - - char MultiplexExternalSemaSource::ID; - -+/// Constructs an empty multiplexing external sema source. -+MultiplexExternalSemaSource::MultiplexExternalSemaSource() {} -+ - /// Constructs a new multiplexing external sema source and appends the - /// given element to it. - /// --- -2.54.0.1136.gdb2ca164c4-goog - diff --git a/third_party/llvm/BUILD b/third_party/llvm/BUILD index 97bab355a5fa..b00f9d42c41e 100644 --- a/third_party/llvm/BUILD +++ b/third_party/llvm/BUILD @@ -20,3 +20,14 @@ cc_library( "@llvm-project//llvm:Support", ], ) + +cc_library( + name = "multiplex_external_sema_source", + srcs = ["multiplex_external_sema_source.cpp"], + hdrs = ["multiplex_external_sema_source.h"], + visibility = ["//visibility:public"], + deps = [ + "@llvm-project//clang:sema", + "@llvm-project//llvm:Support", + ], +) diff --git a/third_party/llvm/multiplex_external_sema_source.cpp b/third_party/llvm/multiplex_external_sema_source.cpp new file mode 100644 index 000000000000..cb9b987f5f6c --- /dev/null +++ b/third_party/llvm/multiplex_external_sema_source.cpp @@ -0,0 +1,450 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// TODO: Remove this once https://github.com/llvm/llvm-project/pull/204458 +// is merged. + +#include "third_party/llvm/multiplex_external_sema_source.h" + +#include "clang/Sema/Lookup.h" + +namespace Carbon { + +// NOLINTBEGIN(modernize-loop-convert) +// NOLINTBEGIN(modernize-use-trailing-return-type) +// NOLINTBEGIN(readability-identifier-naming) +// NOLINTBEGIN(readability-redundant-nested-if) + +char MultiplexExternalSemaSource::ID; + +/// Constructs an empty multiplexing external sema source. +MultiplexExternalSemaSource::MultiplexExternalSemaSource() = default; + +/// Constructs a new multiplexing external sema source and appends the +/// given element to it. +/// +MultiplexExternalSemaSource::MultiplexExternalSemaSource( + llvm::IntrusiveRefCntPtr S1, + llvm::IntrusiveRefCntPtr S2) { + Sources.push_back(std::move(S1)); + Sources.push_back(std::move(S2)); +} + +/// Appends new source to the source list. +/// +///\param[in] source - An ExternalSemaSource. +/// +void MultiplexExternalSemaSource::AddSource( + llvm::IntrusiveRefCntPtr Source) { + Sources.push_back(std::move(Source)); +} + +//===----------------------------------------------------------------------===// +// ExternalASTSource. +//===----------------------------------------------------------------------===// + +clang::Decl* MultiplexExternalSemaSource::GetExternalDecl( + clang::GlobalDeclID ID) { + for (size_t i = 0; i < Sources.size(); ++i) { + if (clang::Decl* Result = Sources[i]->GetExternalDecl(ID)) { + return Result; + } + } + return nullptr; +} + +void MultiplexExternalSemaSource::CompleteRedeclChain(const clang::Decl* D) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->CompleteRedeclChain(D); + } +} + +clang::Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) { + clang::Selector Sel; + for (size_t i = 0; i < Sources.size(); ++i) { + Sel = Sources[i]->GetExternalSelector(ID); + if (!Sel.isNull()) { + return Sel; + } + } + return Sel; +} + +uint32_t MultiplexExternalSemaSource::GetNumExternalSelectors() { + uint32_t total = 0; + for (size_t i = 0; i < Sources.size(); ++i) { + total += Sources[i]->GetNumExternalSelectors(); + } + return total; +} + +clang::Stmt* MultiplexExternalSemaSource::GetExternalDeclStmt(uint64_t Offset) { + for (size_t i = 0; i < Sources.size(); ++i) { + if (clang::Stmt* Result = Sources[i]->GetExternalDeclStmt(Offset)) { + return Result; + } + } + return nullptr; +} + +clang::CXXBaseSpecifier* +MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers(uint64_t Offset) { + for (size_t i = 0; i < Sources.size(); ++i) { + if (clang::CXXBaseSpecifier* R = + Sources[i]->GetExternalCXXBaseSpecifiers(Offset)) { + return R; + } + } + return nullptr; +} + +clang::CXXCtorInitializer** +MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { + for (auto& S : Sources) { + if (auto* R = S->GetExternalCXXCtorInitializers(Offset)) { + return R; + } + } + return nullptr; +} + +clang::ExternalASTSource::ExtKind +MultiplexExternalSemaSource::hasExternalDefinitions(const clang::Decl* D) { + for (const auto& S : Sources) { + if (auto EK = S->hasExternalDefinitions(D)) { + if (EK != EK_ReplyHazy) { + return EK; + } + } + } + return EK_ReplyHazy; +} + +bool MultiplexExternalSemaSource::wasThisDeclarationADefinition( + const clang::FunctionDecl* FD) { + for (const auto& S : Sources) { + if (S->wasThisDeclarationADefinition(FD)) { + return true; + } + } + return false; +} + +bool MultiplexExternalSemaSource::FindExternalVisibleDeclsByName( + const clang::DeclContext* DC, clang::DeclarationName Name, + const clang::DeclContext* OriginalDC) { + bool AnyDeclsFound = false; + for (size_t i = 0; i < Sources.size(); ++i) { + AnyDeclsFound |= + Sources[i]->FindExternalVisibleDeclsByName(DC, Name, OriginalDC); + } + return AnyDeclsFound; +} + +bool MultiplexExternalSemaSource::LoadExternalSpecializations( + const clang::Decl* D, bool OnlyPartial) { + bool Loaded = false; + for (size_t i = 0; i < Sources.size(); ++i) { + Loaded |= Sources[i]->LoadExternalSpecializations(D, OnlyPartial); + } + return Loaded; +} + +bool MultiplexExternalSemaSource::LoadExternalSpecializations( + const clang::Decl* D, + llvm::ArrayRef TemplateArgs) { + bool AnyNewSpecsLoaded = false; + for (size_t i = 0; i < Sources.size(); ++i) { + AnyNewSpecsLoaded |= + Sources[i]->LoadExternalSpecializations(D, TemplateArgs); + } + return AnyNewSpecsLoaded; +} + +void MultiplexExternalSemaSource::completeVisibleDeclsMap( + const clang::DeclContext* DC) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->completeVisibleDeclsMap(DC); + } +} + +void MultiplexExternalSemaSource::FindExternalLexicalDecls( + const clang::DeclContext* DC, + llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl& Result) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->FindExternalLexicalDecls(DC, IsKindWeWant, Result); + } +} + +void MultiplexExternalSemaSource::FindFileRegionDecls( + clang::FileID File, unsigned Offset, unsigned Length, + llvm::SmallVectorImpl& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls); + } +} + +void MultiplexExternalSemaSource::CompleteType(clang::TagDecl* Tag) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->CompleteType(Tag); + } +} + +void MultiplexExternalSemaSource::CompleteType( + clang::ObjCInterfaceDecl* Class) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->CompleteType(Class); + } +} + +void MultiplexExternalSemaSource::ReadComments() { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadComments(); + } +} + +void MultiplexExternalSemaSource::StartedDeserializing() { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->StartedDeserializing(); + } +} + +void MultiplexExternalSemaSource::FinishedDeserializing() { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->FinishedDeserializing(); + } +} + +void MultiplexExternalSemaSource::StartTranslationUnit( + clang::ASTConsumer* Consumer) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->StartTranslationUnit(Consumer); + } +} + +void MultiplexExternalSemaSource::PrintStats() { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->PrintStats(); + } +} + +clang::Module* MultiplexExternalSemaSource::getModule(unsigned ID) { + for (size_t i = 0; i < Sources.size(); ++i) { + if (auto* M = Sources[i]->getModule(ID)) { + return M; + } + } + return nullptr; +} + +bool MultiplexExternalSemaSource::layoutRecordType( + const clang::RecordDecl* Record, uint64_t& Size, uint64_t& Alignment, + llvm::DenseMap& FieldOffsets, + llvm::DenseMap& BaseOffsets, + llvm::DenseMap& + VirtualBaseOffsets) { + for (size_t i = 0; i < Sources.size(); ++i) { + if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets, + BaseOffsets, VirtualBaseOffsets)) { + return true; + } + } + return false; +} + +void MultiplexExternalSemaSource::getMemoryBufferSizes( + MemoryBufferSizes& sizes) const { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->getMemoryBufferSizes(sizes); + } +} + +//===----------------------------------------------------------------------===// +// ExternalSemaSource. +//===----------------------------------------------------------------------===// + +void MultiplexExternalSemaSource::InitializeSema(clang::Sema& S) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->InitializeSema(S); + } +} + +void MultiplexExternalSemaSource::ForgetSema() { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ForgetSema(); + } +} + +void MultiplexExternalSemaSource::ReadMethodPool(clang::Selector Sel) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadMethodPool(Sel); + } +} + +void MultiplexExternalSemaSource::updateOutOfDateSelector(clang::Selector Sel) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->updateOutOfDateSelector(Sel); + } +} + +void MultiplexExternalSemaSource::ReadKnownNamespaces( + llvm::SmallVectorImpl& Namespaces) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadKnownNamespaces(Namespaces); + } +} + +void MultiplexExternalSemaSource::ReadUndefinedButUsed( + llvm::MapVector& Undefined) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadUndefinedButUsed(Undefined); + } +} + +void MultiplexExternalSemaSource::ReadMismatchingDeleteExpressions( + llvm::MapVector< + clang::FieldDecl*, + llvm::SmallVector, 4>>& Exprs) { + for (auto& Source : Sources) { + Source->ReadMismatchingDeleteExpressions(Exprs); + } +} + +bool MultiplexExternalSemaSource::LookupUnqualified(clang::LookupResult& R, + clang::Scope* S) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->LookupUnqualified(R, S); + } + + return !R.empty(); +} + +void MultiplexExternalSemaSource::ReadTentativeDefinitions( + llvm::SmallVectorImpl& TentativeDefs) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadTentativeDefinitions(TentativeDefs); + } +} + +void MultiplexExternalSemaSource::ReadUnusedFileScopedDecls( + llvm::SmallVectorImpl& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadUnusedFileScopedDecls(Decls); + } +} + +void MultiplexExternalSemaSource::ReadDelegatingConstructors( + llvm::SmallVectorImpl& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadDelegatingConstructors(Decls); + } +} + +void MultiplexExternalSemaSource::ReadExtVectorDecls( + llvm::SmallVectorImpl& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadExtVectorDecls(Decls); + } +} + +void MultiplexExternalSemaSource::ReadDeclsToCheckForDeferredDiags( + llvm::SmallSetVector& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadDeclsToCheckForDeferredDiags(Decls); + } +} + +void MultiplexExternalSemaSource::ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector& Decls) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadUnusedLocalTypedefNameCandidates(Decls); + } +} + +void MultiplexExternalSemaSource::ReadReferencedSelectors( + llvm::SmallVectorImpl>& + Sels) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadReferencedSelectors(Sels); + } +} + +void MultiplexExternalSemaSource::ReadWeakUndeclaredIdentifiers( + llvm::SmallVectorImpl>& + WI) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadWeakUndeclaredIdentifiers(WI); + } +} + +void MultiplexExternalSemaSource::ReadExtnameUndeclaredIdentifiers( + llvm::SmallVectorImpl< + std::pair>& EI) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadExtnameUndeclaredIdentifiers(EI); + } +} + +void MultiplexExternalSemaSource::ReadUsedVTables( + llvm::SmallVectorImpl& VTables) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadUsedVTables(VTables); + } +} + +void MultiplexExternalSemaSource::ReadPendingInstantiations( + llvm::SmallVectorImpl>& + Pending) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadPendingInstantiations(Pending); + } +} + +void MultiplexExternalSemaSource::ReadLateParsedTemplates( + llvm::MapVector>& LPTMap) { + for (size_t i = 0; i < Sources.size(); ++i) { + Sources[i]->ReadLateParsedTemplates(LPTMap); + } +} + +clang::TypoCorrection MultiplexExternalSemaSource::CorrectTypo( + const clang::DeclarationNameInfo& Typo, int LookupKind, clang::Scope* S, + clang::CXXScopeSpec* SS, clang::CorrectionCandidateCallback& CCC, + clang::DeclContext* MemberContext, bool EnteringContext, + const clang::ObjCObjectPointerType* OPT) { + for (size_t I = 0, E = Sources.size(); I < E; ++I) { + if (clang::TypoCorrection C = + Sources[I]->CorrectTypo(Typo, LookupKind, S, SS, CCC, MemberContext, + EnteringContext, OPT)) { + return C; + } + } + return clang::TypoCorrection(); +} + +bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType( + clang::SourceLocation Loc, clang::QualType T) { + for (size_t I = 0, E = Sources.size(); I < E; ++I) { + if (Sources[I]->MaybeDiagnoseMissingCompleteType(Loc, T)) { + return true; + } + } + return false; +} + +void MultiplexExternalSemaSource::AssignedLambdaNumbering( + clang::CXXRecordDecl* Lambda) { + for (auto& Source : Sources) { + Source->AssignedLambdaNumbering(Lambda); + } +} + +// NOLINTEND(readability-redundant-nested-if) +// NOLINTEND(readability-identifier-naming) +// NOLINTEND(modernize-use-trailing-return-type) +// NOLINTEND(modernize-loop-convert) + +} // namespace Carbon diff --git a/third_party/llvm/multiplex_external_sema_source.h b/third_party/llvm/multiplex_external_sema_source.h new file mode 100644 index 000000000000..3943db45d5fe --- /dev/null +++ b/third_party/llvm/multiplex_external_sema_source.h @@ -0,0 +1,424 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// TODO: Remove this once https://github.com/llvm/llvm-project/pull/204458 +// is merged. + +#ifndef CARBON_THIRD_PARTY_LLVM_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H_ +#define CARBON_THIRD_PARTY_LLVM_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H_ + +#include + +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Weak.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" + +namespace Carbon { + +class CXXConstructorDecl; +class CXXRecordDecl; +class DeclaratorDecl; +struct ExternalVTableUse; +class LookupResult; +class NamespaceDecl; +class Scope; +class Sema; +class TypedefNameDecl; +class ValueDecl; +class VarDecl; + +// NOLINTBEGIN(modernize-use-trailing-return-type) +// NOLINTBEGIN(readability-identifier-naming) + +/// An abstract interface that should be implemented by +/// external AST sources that also provide information for semantic +/// analysis. +class MultiplexExternalSemaSource : public clang::ExternalSemaSource { + /// LLVM-style RTTI. + static char ID; + + private: + llvm::SmallVector, 2> Sources; + + public: + /// Constructs an empty multiplexing external sema source. + MultiplexExternalSemaSource(); + + /// Constructs a new multiplexing external sema source and appends the + /// given element to it. + /// + ///\param[in] S1 - A non-null (old) ExternalSemaSource. + ///\param[in] S2 - A non-null (new) ExternalSemaSource. + /// + MultiplexExternalSemaSource(llvm::IntrusiveRefCntPtr S1, + llvm::IntrusiveRefCntPtr S2); + + /// Appends new source to the source list. + /// + ///\param[in] Source - An ExternalSemaSource. + /// + void AddSource(llvm::IntrusiveRefCntPtr Source); + + /// Remove all sources for which the predicate returns true. + /// + /// \param P - A predicate that takes an + /// IntrusiveRefCntPtr param and returns true if + /// the source should be removed, false otherwise. + template + void EraseIf(UnaryPredicate P) { + llvm::erase_if(Sources, P); + } + + //===--------------------------------------------------------------------===// + // ExternalASTSource. + //===--------------------------------------------------------------------===// + + /// Resolve a declaration ID into a declaration, potentially + /// building a new declaration. + clang::Decl* GetExternalDecl(clang::GlobalDeclID ID) override; + + /// Complete the redeclaration chain if it's been extended since the + /// previous generation of the AST source. + void CompleteRedeclChain(const clang::Decl* D) override; + + /// Resolve a selector ID into a selector. + clang::Selector GetExternalSelector(uint32_t ID) override; + + /// Returns the number of selectors known to the external AST + /// source. + uint32_t GetNumExternalSelectors() override; + + /// Resolve the offset of a statement in the decl stream into + /// a statement. + clang::Stmt* GetExternalDeclStmt(uint64_t Offset) override; + + /// Resolve the offset of a set of C++ base specifiers in the decl + /// stream into an array of specifiers. + clang::CXXBaseSpecifier* GetExternalCXXBaseSpecifiers( + uint64_t Offset) override; + + /// Resolve a handle to a list of ctor initializers into the list of + /// initializers themselves. + clang::CXXCtorInitializer** GetExternalCXXCtorInitializers( + uint64_t Offset) override; + + ExtKind hasExternalDefinitions(const clang::Decl* D) override; + + bool wasThisDeclarationADefinition(const clang::FunctionDecl* FD) override; + + /// Find all declarations with the given name in the + /// given context. + bool FindExternalVisibleDeclsByName( + const clang::DeclContext* DC, clang::DeclarationName Name, + const clang::DeclContext* OriginalDC) override; + + bool LoadExternalSpecializations(const clang::Decl* D, + bool OnlyPartial) override; + + bool LoadExternalSpecializations( + const clang::Decl* D, + llvm::ArrayRef TemplateArgs) override; + + /// Ensures that the table of all visible declarations inside this + /// context is up to date. + void completeVisibleDeclsMap(const clang::DeclContext* DC) override; + + /// Finds all declarations lexically contained within the given + /// DeclContext, after applying an optional filter predicate. + /// + /// \param IsKindWeWant a predicate function that returns true if the passed + /// declaration kind is one we are looking for. + void FindExternalLexicalDecls( + const clang::DeclContext* DC, + llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl& Result) override; + + /// Get the decls that are contained in a file in the Offset/Length + /// range. \p Length can be 0 to indicate a point at \p Offset instead of + /// a range. + void FindFileRegionDecls(clang::FileID File, unsigned Offset, unsigned Length, + llvm::SmallVectorImpl& Decls) override; + + /// Gives the external AST source an opportunity to complete + /// an incomplete type. + void CompleteType(clang::TagDecl* Tag) override; + + /// Gives the external AST source an opportunity to complete an + /// incomplete Objective-C class. + /// + /// This routine will only be invoked if the "externally completed" bit is + /// set on the ObjCInterfaceDecl via the function + /// \c ObjCInterfaceDecl::setExternallyCompleted(). + void CompleteType(clang::ObjCInterfaceDecl* Class) override; + + /// Loads comment ranges. + void ReadComments() override; + + /// Notify ExternalASTSource that we started deserialization of + /// a decl or type so until FinishedDeserializing is called there may be + /// decls that are initializing. Must be paired with FinishedDeserializing. + void StartedDeserializing() override; + + /// Notify ExternalASTSource that we finished the deserialization of + /// a decl or type. Must be paired with StartedDeserializing. + void FinishedDeserializing() override; + + /// Function that will be invoked when we begin parsing a new + /// translation unit involving this external AST source. + void StartTranslationUnit(clang::ASTConsumer* Consumer) override; + + /// Print any statistics that have been gathered regarding + /// the external AST source. + void PrintStats() override; + + /// Retrieve the module that corresponds to the given module ID. + clang::Module* getModule(unsigned ID) override; + + /// Perform layout on the given record. + /// + /// This routine allows the external AST source to provide an specific + /// layout for a record, overriding the layout that would normally be + /// constructed. It is intended for clients who receive specific layout + /// details rather than source code (such as LLDB). The client is expected + /// to fill in the field offsets, base offsets, virtual base offsets, and + /// complete object size. + /// + /// \param Record The record whose layout is being requested. + /// + /// \param Size The final size of the record, in bits. + /// + /// \param Alignment The final alignment of the record, in bits. + /// + /// \param FieldOffsets The offset of each of the fields within the record, + /// expressed in bits. All of the fields must be provided with offsets. + /// + /// \param BaseOffsets The offset of each of the direct, non-virtual base + /// classes. If any bases are not given offsets, the bases will be laid + /// out according to the ABI. + /// + /// \param VirtualBaseOffsets The offset of each of the virtual base classes + /// (either direct or not). If any bases are not given offsets, the bases will + /// be laid out according to the ABI. + /// + /// \returns true if the record layout was provided, false otherwise. + bool layoutRecordType( + const clang::RecordDecl* Record, uint64_t& Size, uint64_t& Alignment, + llvm::DenseMap& FieldOffsets, + llvm::DenseMap& + BaseOffsets, + llvm::DenseMap& + VirtualBaseOffsets) override; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + void getMemoryBufferSizes(MemoryBufferSizes& sizes) const override; + + //===--------------------------------------------------------------------===// + // ExternalSemaSource. + //===--------------------------------------------------------------------===// + + /// Initialize the semantic source with the Sema instance + /// being used to perform semantic analysis on the abstract syntax + /// tree. + void InitializeSema(clang::Sema& S) override; + + /// Inform the semantic consumer that Sema is no longer available. + void ForgetSema() override; + + /// Load the contents of the global method pool for a given + /// selector. + void ReadMethodPool(clang::Selector Sel) override; + + /// Load the contents of the global method pool for a given + /// selector if necessary. + void updateOutOfDateSelector(clang::Selector Sel) override; + + /// Load the set of namespaces that are known to the external source, + /// which will be used during typo correction. + void ReadKnownNamespaces( + llvm::SmallVectorImpl& Namespaces) override; + + /// Load the set of used but not defined functions or variables with + /// internal linkage, or used but not defined inline functions. + void ReadUndefinedButUsed( + llvm::MapVector& Undefined) + override; + + void ReadMismatchingDeleteExpressions( + llvm::MapVector, + 4>>& Exprs) override; + + /// Do last resort, unqualified lookup on a LookupResult that + /// Sema cannot find. + /// + /// \param R a LookupResult that is being recovered. + /// + /// \param S the Scope of the identifier occurrence. + /// + /// \return true to tell Sema to recover using the LookupResult. + bool LookupUnqualified(clang::LookupResult& R, clang::Scope* S) override; + + /// Read the set of tentative definitions known to the external Sema + /// source. + /// + /// The external source should append its own tentative definitions to the + /// given vector of tentative definitions. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadTentativeDefinitions( + llvm::SmallVectorImpl& Defs) override; + + /// Read the set of unused file-scope declarations known to the + /// external Sema source. + /// + /// The external source should append its own unused, filed-scope to the + /// given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadUnusedFileScopedDecls( + llvm::SmallVectorImpl& Decls) override; + + /// Read the set of delegating constructors known to the + /// external Sema source. + /// + /// The external source should append its own delegating constructors to the + /// given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadDelegatingConstructors( + llvm::SmallVectorImpl& Decls) override; + + /// Read the set of ext_vector type declarations known to the + /// external Sema source. + /// + /// The external source should append its own ext_vector type declarations to + /// the given vector of declarations. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadExtVectorDecls( + llvm::SmallVectorImpl& Decls) override; + + /// Read the set of potentially unused typedefs known to the source. + /// + /// The external source should append its own potentially unused local + /// typedefs to the given vector of declarations. Note that this routine may + /// be invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector& Decls) override; + + /// Read the set of referenced selectors known to the + /// external Sema source. + /// + /// The external source should append its own referenced selectors to the + /// given vector of selectors. Note that this routine + /// may be invoked multiple times; the external source should take care not + /// to introduce the same selectors repeatedly. + void ReadReferencedSelectors( + llvm::SmallVectorImpl>& + Sels) override; + + /// Read the set of weak, undeclared identifiers known to the + /// external Sema source. + /// + /// The external source should append its own weak, undeclared identifiers to + /// the given vector. Note that this routine may be invoked multiple times; + /// the external source should take care not to introduce the same identifiers + /// repeatedly. + void ReadWeakUndeclaredIdentifiers( + llvm::SmallVectorImpl>& + WI) override; + + /// Read the set of #pragma redefine_extname'd, undeclared identifiers known + /// to the external Sema source. + /// + /// The external source should append its own #pragma redefine_extname'd, + /// undeclared identifiers to the given vector. Note that this routine may be + /// invoked multiple times; the external source should take care not to + /// introduce the same identifiers repeatedly. + void ReadExtnameUndeclaredIdentifiers( + llvm::SmallVectorImpl>& EI) override; + + /// Read the set of used vtables known to the external Sema source. + /// + /// The external source should append its own used vtables to the given + /// vector. Note that this routine may be invoked multiple times; the external + /// source should take care not to introduce the same vtables repeatedly. + void ReadUsedVTables( + llvm::SmallVectorImpl& VTables) override; + + /// Read the set of pending instantiations known to the external + /// Sema source. + /// + /// The external source should append its own pending instantiations to the + /// given vector. Note that this routine may be invoked multiple times; the + /// external source should take care not to introduce the same instantiations + /// repeatedly. + void ReadPendingInstantiations( + llvm::SmallVectorImpl< + std::pair>& Pending) + override; + + /// Read the set of late parsed template functions for this source. + /// + /// The external source should insert its own late parsed template functions + /// into the map. Note that this routine may be invoked multiple times; the + /// external source should take care not to introduce the same map entries + /// repeatedly. + void ReadLateParsedTemplates( + llvm::MapVector>& LPTMap) + override; + + /// Read the set of decls to be checked for deferred diags. + /// + /// The external source should append its own potentially emitted function + /// and variable decls which may cause deferred diags. Note that this routine + /// may be invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadDeclsToCheckForDeferredDiags( + llvm::SmallSetVector& Decls) override; + + /// \copydoc ExternalSemaSource::CorrectTypo + /// \note Returns the first nonempty correction. + clang::TypoCorrection CorrectTypo( + const clang::DeclarationNameInfo& Typo, int LookupKind, clang::Scope* S, + clang::CXXScopeSpec* SS, clang::CorrectionCandidateCallback& CCC, + clang::DeclContext* MemberContext, bool EnteringContext, + const clang::ObjCObjectPointerType* OPT) override; + + /// Produces a diagnostic note if one of the attached sources + /// contains a complete definition for \p T. Queries the sources in list + /// order until the first one claims that a diagnostic was produced. + /// + /// \param Loc the location at which a complete type was required but not + /// provided + /// + /// \param T the \c QualType that should have been complete at \p Loc + /// + /// \return true if a diagnostic was produced, false otherwise. + bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc, + clang::QualType T) override; + + // Inform all attached sources that a mangling number was assigned. + void AssignedLambdaNumbering(clang::CXXRecordDecl* Lambda) override; + + /// LLVM-style RTTI. + /// \{ + bool isA(const void* ClassID) const override { + return ClassID == &ID || ExternalSemaSource::isA(ClassID); + } + static bool classof(const clang::ExternalASTSource* S) { return S->isA(&ID); } + /// \} +}; + +// NOLINTEND(readability-identifier-naming) +// NOLINTEND(modernize-use-trailing-return-type) + +} // namespace Carbon + +#endif // CARBON_THIRD_PARTY_LLVM_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H_ diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index 5e66adf09518..4d78af73342e 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -164,6 +164,7 @@ cc_library( "//common:raw_string_ostream", "//common:set", "//common:vlog", + "//third_party/llvm:multiplex_external_sema_source", "//toolchain/base:canonical_value_store", "//toolchain/base:index_base", "//toolchain/base:int", diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index 4b369a07a7a7..e1571eaf40c6 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -18,7 +18,6 @@ #include "clang/Lex/PreprocessorOptions.h" #include "clang/Parse/Parser.h" #include "clang/Sema/ExternalSemaSource.h" -#include "clang/Sema/MultiplexExternalSemaSource.h" #include "clang/Sema/Sema.h" #include "common/check.h" #include "common/map.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" +#include "third_party/llvm/multiplex_external_sema_source.h" #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/cpp/access.h" @@ -898,9 +898,9 @@ auto GenerateAst(Context& context, // using `MultiplexExternalSemaSource`, we can keep the top-level // `ExternalASTSource` pointer the same, and only update its children. auto multiplex_source_ref_cnt_ptr = - llvm::makeIntrusiveRefCnt(); - auto* multiplex_source = cast( - multiplex_source_ref_cnt_ptr.get()); + llvm::makeIntrusiveRefCnt(); + auto* multiplex_source = + cast(multiplex_source_ref_cnt_ptr.get()); if (auto* existing_source = llvm::cast_or_null( ast.getExternalSource())) { multiplex_source->AddSource(existing_source); @@ -965,10 +965,9 @@ auto FinishAst(Context& context) -> void { // the source may be accessed later during lowering, but the // `CarbonExternalASTSource` has a pointer to `Check::Context` that // will not remain valid. - auto* multiplex_source = cast( + auto* multiplex_source = cast( context.ast_context().getExternalSource()); - auto& child_sources = multiplex_source->GetSources(); - llvm::erase_if(child_sources, [](const auto& src) { + multiplex_source->EraseIf([](const auto& src) { // `CarbonExternalASTSource` inherits from `ReadOnlyASTSource`. return llvm::isa(src.get()); });