From 7901fb38578b7058537365efcfa4c0d53b487065 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 7 Jun 2026 09:27:22 -0700 Subject: [PATCH] Don't include expensive Clang headers in widely-included headers (#7319) Fundamentally, this uses forward declarations of Clang types to reduce the overall compile time cost of Clang headers across the codebase. Tracing and profiling showed ~2s of every check TU's ~8-12s compile time going just to parsing Clang frontend and AST headers pulled in via a few sem_ir and check headers that only use the Clang types by pointer or reference: - sem_ir/cpp_file.h (reached via sem_ir/file.h by ~150 TUs) included clang/Frontend/CompilerInstance.h, clang/CodeGen/ModuleBuilder.h, clang/AST/Mangle.h, and llvm/IR/Module.h. CppFile's accessors move out of line to a new cpp_file.cpp and the header now forward-declares the Clang types. - check/cpp/context.h (reached via check/context.h by ~100 TUs) included clang/Frontend/FrontendAction.h and clang/Parse/Parser.h, pulling in clang's Sema.h and ASTUnit.h. - sem_ir/clang_decl.h included clang/AST/Decl.h; the three small functions that need complete Clang types move out of line. - sem_ir/cpp_overload_set.h included clang/Sema/Overload.h solely for the three-field OverloadCandidateSet::OperatorRewriteInfo, which is now mirrored as CppOverloadSet::OperatorRewriteInfo, and clang/AST/Decl.h solely for a pointer. - sem_ir/name_scope.h's clang/AST/DeclBase.h include was vestigial. TUs (and more narrowly included headers) that genuinely use the Clang definitions now include the Clang headers directly. Representative compile times (fastbuild, aarch64), combined with the preceding instantiation-cost changes, relative to trunk: - check/eval.cpp: 11.85s -> 6.94s (-41%) - check/handle_operator.cpp: 7.71s -> 3.30s (-57%) - language_server.cpp: 6.68s -> 3.16s (-53%) - lower/handle.cpp: 6.75s -> 3.66s (-46%) - sem_ir/file.cpp: 8.60s -> 6.11s (-29%) - driver.cpp: 6.68s -> 4.78s (-28%) Measured full-rebuild impact (316 first-party TUs, fastbuild): -689.5s CPU, -29.9% relative to trunk. Assisted-by: Claude --- .clang-tidy | 4 ++ toolchain/check/cpp/access.cpp | 2 + toolchain/check/cpp/access.h | 2 + toolchain/check/cpp/call.h | 5 ++ toolchain/check/cpp/constant.cpp | 2 + toolchain/check/cpp/constant.h | 4 ++ toolchain/check/cpp/context.cpp | 2 + toolchain/check/cpp/context.h | 12 +++- toolchain/check/cpp/export.cpp | 2 + toolchain/check/cpp/export.h | 5 ++ toolchain/check/cpp/generate_ast.h | 4 ++ toolchain/check/cpp/impl_lookup.cpp | 2 + toolchain/check/cpp/import.cpp | 5 +- toolchain/check/cpp/import.h | 9 ++- toolchain/check/cpp/location.cpp | 2 + toolchain/check/cpp/macros.cpp | 1 + toolchain/check/cpp/macros.h | 4 ++ toolchain/check/cpp/overload_resolution.cpp | 7 ++- toolchain/check/cpp/overload_resolution.h | 1 + toolchain/check/cpp/type_mapping.cpp | 2 + toolchain/lower/context.cpp | 1 + toolchain/sem_ir/BUILD | 3 + toolchain/sem_ir/clang_decl.cpp | 15 +++++ toolchain/sem_ir/clang_decl.h | 18 +++--- toolchain/sem_ir/cpp_file.cpp | 57 +++++++++++++++++ toolchain/sem_ir/cpp_file.h | 63 ++++++++----------- toolchain/sem_ir/cpp_overload_set.h | 25 +++++++- toolchain/sem_ir/diagnostic_loc_converter.cpp | 1 + toolchain/sem_ir/name_scope.h | 1 - toolchain/sem_ir/type_info.cpp | 1 + 30 files changed, 203 insertions(+), 59 deletions(-) create mode 100644 toolchain/sem_ir/cpp_file.cpp diff --git a/.clang-tidy b/.clang-tidy index f279587e1c11..c3a53752672b 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -121,6 +121,10 @@ CheckOptions: value: CamelCase - key: readability-identifier-naming.NamespaceCase value: CamelCase + # Headers re-open LLVM and Clang namespaces to forward-declare their types, + # which is much cheaper to compile than including their headers. + - key: readability-identifier-naming.NamespaceIgnoredRegexp + value: '^(clang|llvm)$' - key: readability-identifier-naming.StructCase value: CamelCase - key: readability-identifier-naming.TemplateParameterCase diff --git a/toolchain/check/cpp/access.cpp b/toolchain/check/cpp/access.cpp index 8250e4af63b4..107a0303733a 100644 --- a/toolchain/check/cpp/access.cpp +++ b/toolchain/check/cpp/access.cpp @@ -4,6 +4,8 @@ #include "toolchain/check/cpp/access.h" +#include "clang/AST/Decl.h" + namespace Carbon::Check { static auto CalculateEffectiveAccess(clang::DeclAccessPair access_pair) diff --git a/toolchain/check/cpp/access.h b/toolchain/check/cpp/access.h index 04b7d070dd85..a48507f2a200 100644 --- a/toolchain/check/cpp/access.h +++ b/toolchain/check/cpp/access.h @@ -5,6 +5,8 @@ #ifndef CARBON_TOOLCHAIN_CHECK_CPP_ACCESS_H_ #define CARBON_TOOLCHAIN_CHECK_CPP_ACCESS_H_ +#include "clang/AST/DeclAccessPair.h" +#include "clang/Basic/Specifiers.h" #include "toolchain/sem_ir/name_scope.h" namespace Carbon::Check { diff --git a/toolchain/check/cpp/call.h b/toolchain/check/cpp/call.h index 816b894437bf..770bb4d4342d 100644 --- a/toolchain/check/cpp/call.h +++ b/toolchain/check/cpp/call.h @@ -8,6 +8,11 @@ #include "toolchain/check/context.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class TemplateArgumentListInfo; +class TemplateDecl; +} // namespace clang + namespace Carbon::Check { // Converts a call argument list into a Clang template argument list for a given diff --git a/toolchain/check/cpp/constant.cpp b/toolchain/check/cpp/constant.cpp index d16f52f9448d..3602cc9c0cb2 100644 --- a/toolchain/check/cpp/constant.cpp +++ b/toolchain/check/cpp/constant.cpp @@ -4,6 +4,8 @@ #include "toolchain/check/cpp/constant.h" +#include "clang/Basic/DiagnosticSema.h" +#include "clang/Sema/Sema.h" #include "toolchain/check/cpp/import.h" #include "toolchain/check/cpp/location.h" #include "toolchain/check/cpp/type_mapping.h" diff --git a/toolchain/check/cpp/constant.h b/toolchain/check/cpp/constant.h index 52ad34c4d9e3..c55d164d65ca 100644 --- a/toolchain/check/cpp/constant.h +++ b/toolchain/check/cpp/constant.h @@ -11,6 +11,10 @@ #include "toolchain/check/context.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class VarDecl; +} // namespace clang + namespace Carbon::Check { // Converts an `APValue` to a Carbon `ConstantId`. diff --git a/toolchain/check/cpp/context.cpp b/toolchain/check/cpp/context.cpp index aba3f6d51105..4593347bbc55 100644 --- a/toolchain/check/cpp/context.cpp +++ b/toolchain/check/cpp/context.cpp @@ -5,6 +5,8 @@ #include "toolchain/check/cpp/context.h" #include "clang/AST/Mangle.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Parse/Parser.h" namespace Carbon::Check { diff --git a/toolchain/check/cpp/context.h b/toolchain/check/cpp/context.h index 2cce3d4f3f58..2ebc83ef1157 100644 --- a/toolchain/check/cpp/context.h +++ b/toolchain/check/cpp/context.h @@ -8,12 +8,18 @@ #include #include "clang/Basic/SourceLocation.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Parse/Parser.h" #include "common/check.h" #include "llvm/ADT/SmallVector.h" +namespace clang { +class ASTContext; +class CompilerInstance; +class FunctionDecl; +class MangleContext; +class Parser; +class Sema; +} // namespace clang + namespace Carbon::Check { // Context for C++ code during check. diff --git a/toolchain/check/cpp/export.cpp b/toolchain/check/cpp/export.cpp index faed1f9f032e..03cc847c00f6 100644 --- a/toolchain/check/cpp/export.cpp +++ b/toolchain/check/cpp/export.cpp @@ -6,6 +6,8 @@ #include +#include "clang/AST/ASTConsumer.h" +#include "clang/Sema/Sema.h" #include "llvm/Support/Casting.h" #include "toolchain/check/cpp/access.h" #include "toolchain/check/cpp/import.h" diff --git a/toolchain/check/cpp/export.h b/toolchain/check/cpp/export.h index f064430baad3..0e6e95b9b8a2 100644 --- a/toolchain/check/cpp/export.h +++ b/toolchain/check/cpp/export.h @@ -9,6 +9,11 @@ #include "toolchain/check/context.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class CXXDestructorDecl; +class CXXRecordDecl; +} // namespace clang + namespace Carbon::Check { // Exports a Carbon name scope into C++ as a namespace or class, or returns the diff --git a/toolchain/check/cpp/generate_ast.h b/toolchain/check/cpp/generate_ast.h index ebf96532d0e7..b4ffeef0d49a 100644 --- a/toolchain/check/cpp/generate_ast.h +++ b/toolchain/check/cpp/generate_ast.h @@ -15,6 +15,10 @@ #include "toolchain/parse/tree.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class CompilerInvocation; +} // namespace clang + namespace Carbon::Check { // Generates a Clang AST for the given C++ imports and sets it as the context's diff --git a/toolchain/check/cpp/impl_lookup.cpp b/toolchain/check/cpp/impl_lookup.cpp index 12e8774143a9..00e12cdbd729 100644 --- a/toolchain/check/cpp/impl_lookup.cpp +++ b/toolchain/check/cpp/impl_lookup.cpp @@ -5,7 +5,9 @@ #include "toolchain/check/cpp/impl_lookup.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" #include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" diff --git a/toolchain/check/cpp/import.cpp b/toolchain/check/cpp/import.cpp index 81c976422baa..54e27a091dce 100644 --- a/toolchain/check/cpp/import.cpp +++ b/toolchain/check/cpp/import.cpp @@ -16,8 +16,11 @@ #include "clang/AST/UnresolvedSet.h" #include "clang/AST/VTableBuilder.h" #include "clang/Frontend/CompilerInvocation.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" +#include "clang/Sema/Sema.h" #include "common/check.h" #include "common/ostream.h" #include "common/raw_string_ostream.h" @@ -2375,7 +2378,7 @@ auto ImportCppOverloadSet( Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, SemIR::NameId name_id, clang::CXXRecordDecl* naming_class, clang::UnresolvedSet<4>&& overload_set, - clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info) + SemIR::CppOverloadSet::OperatorRewriteInfo operator_rewrite_info) -> SemIR::InstId { SemIR::CppOverloadSetId overload_set_id = context.cpp_overload_sets().Add( SemIR::CppOverloadSet{.name_id = name_id, diff --git a/toolchain/check/cpp/import.h b/toolchain/check/cpp/import.h index f94a04e0bffa..951ed22dac5c 100644 --- a/toolchain/check/cpp/import.h +++ b/toolchain/check/cpp/import.h @@ -5,6 +5,7 @@ #ifndef CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_ #define CARBON_TOOLCHAIN_CHECK_CPP_IMPORT_H_ +#include "clang/AST/Type.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" @@ -16,6 +17,12 @@ #include "toolchain/sem_ir/clang_decl.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class CompilerInvocation; +class IdentifierInfo; +class VarDecl; +} // namespace clang + namespace Carbon::Check { // Returns whether the given function is an object member function. This is true @@ -84,7 +91,7 @@ auto ImportCppOverloadSet( Context& context, SemIR::LocId loc_id, SemIR::NameScopeId scope_id, SemIR::NameId name_id, clang::CXXRecordDecl* naming_class, clang::UnresolvedSet<4>&& overload_set, - clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info) + SemIR::CppOverloadSet::OperatorRewriteInfo operator_rewrite_info) -> SemIR::InstId; // Looks up the given name in the Clang AST generated when importing C++ code diff --git a/toolchain/check/cpp/location.cpp b/toolchain/check/cpp/location.cpp index 2d5c9c5e0a8d..ca39927570ee 100644 --- a/toolchain/check/cpp/location.cpp +++ b/toolchain/check/cpp/location.cpp @@ -4,6 +4,8 @@ #include "toolchain/check/cpp/location.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/SourceManager.h" #include "toolchain/sem_ir/absolute_node_ref.h" #include "toolchain/sem_ir/ids.h" diff --git a/toolchain/check/cpp/macros.cpp b/toolchain/check/cpp/macros.cpp index 91b0570878ba..8267af39c8cd 100644 --- a/toolchain/check/cpp/macros.cpp +++ b/toolchain/check/cpp/macros.cpp @@ -6,6 +6,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Sema.h" #include "common/check.h" diff --git a/toolchain/check/cpp/macros.h b/toolchain/check/cpp/macros.h index 27b9a5a5f2d7..dbf046770852 100644 --- a/toolchain/check/cpp/macros.h +++ b/toolchain/check/cpp/macros.h @@ -7,6 +7,10 @@ #include "toolchain/check/context.h" +namespace clang { +class MacroInfo; +} // namespace clang + namespace Carbon::Check { // Tries to evaluate the given macro. The macro will be evaluated as a diff --git a/toolchain/check/cpp/overload_resolution.cpp b/toolchain/check/cpp/overload_resolution.cpp index b179a0733750..4ff5bf30b9b5 100644 --- a/toolchain/check/cpp/overload_resolution.cpp +++ b/toolchain/check/cpp/overload_resolution.cpp @@ -290,12 +290,15 @@ auto PerformCppOverloadResolution( clang::SourceLocation loc = GetCppLocation(context, loc_id); // Add candidate functions from the name lookup. + const auto& rewrite_info = overload_set.operator_rewrite_info; clang::OverloadCandidateSet candidate_set( loc, - overload_set.operator_rewrite_info.OriginalOperator + rewrite_info.original_operator ? clang::OverloadCandidateSet::CandidateSetKind::CSK_Operator : clang::OverloadCandidateSet::CandidateSetKind::CSK_Normal, - overload_set.operator_rewrite_info); + clang::OverloadCandidateSet::OperatorRewriteInfo( + rewrite_info.original_operator, rewrite_info.op_loc, + rewrite_info.allow_rewritten_candidates)); AddOverloadCandidates(context, candidate_set, overload_set.candidate_functions, template_arg_ids, diff --git a/toolchain/check/cpp/overload_resolution.h b/toolchain/check/cpp/overload_resolution.h index 39453a780819..49d7fe4ee9b7 100644 --- a/toolchain/check/cpp/overload_resolution.h +++ b/toolchain/check/cpp/overload_resolution.h @@ -5,6 +5,7 @@ #ifndef CARBON_TOOLCHAIN_CHECK_CPP_OVERLOAD_RESOLUTION_H_ #define CARBON_TOOLCHAIN_CHECK_CPP_OVERLOAD_RESOLUTION_H_ +#include "clang/Sema/Overload.h" #include "toolchain/check/context.h" #include "toolchain/sem_ir/function.h" #include "toolchain/sem_ir/ids.h" diff --git a/toolchain/check/cpp/type_mapping.cpp b/toolchain/check/cpp/type_mapping.cpp index 86d0d8ae34d3..4ff4974559ee 100644 --- a/toolchain/check/cpp/type_mapping.cpp +++ b/toolchain/check/cpp/type_mapping.cpp @@ -11,7 +11,9 @@ #include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/SmallVector.h" #include "toolchain/base/int.h" #include "toolchain/base/kind_switch.h" diff --git a/toolchain/lower/context.cpp b/toolchain/lower/context.cpp index 37d0b5db6deb..bc805a0b5ab5 100644 --- a/toolchain/lower/context.cpp +++ b/toolchain/lower/context.cpp @@ -4,6 +4,7 @@ #include "toolchain/lower/context.h" +#include "clang/Basic/SourceManager.h" #include "common/check.h" #include "common/growing_range.h" #include "common/raw_string_ostream.h" diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 2ac528de5a8b..3dcafff73a97 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -88,6 +88,7 @@ cc_library( "class.cpp", "constant.cpp", "core_interface.cpp", + "cpp_file.cpp", "cpp_initializer_list.cpp", "cpp_overload_set.cpp", "facet_type_info.cpp", @@ -178,6 +179,7 @@ cc_library( "//toolchain/parse:node_kind", "//toolchain/parse:tree", "@llvm-project//clang:ast", + "@llvm-project//clang:basic", "@llvm-project//clang:frontend", "@llvm-project//clang:sema", "@llvm-project//llvm:Support", @@ -302,6 +304,7 @@ cc_library( ":typed_insts", "//toolchain/diagnostics:emitter", "//toolchain/parse:tree", + "@llvm-project//clang:basic", "@llvm-project//clang:frontend", "@llvm-project//llvm:Support", ], diff --git a/toolchain/sem_ir/clang_decl.cpp b/toolchain/sem_ir/clang_decl.cpp index 8fc830892fe2..6c96abae11ae 100644 --- a/toolchain/sem_ir/clang_decl.cpp +++ b/toolchain/sem_ir/clang_decl.cpp @@ -57,6 +57,21 @@ auto ClangDeclSignature::Print(llvm::raw_ostream& out) const -> void { out << "}"; } +auto ClangDeclKey::ForFunctionDecl(clang::FunctionDecl* decl, + ClangDeclSignatureId signature_id) + -> ClangDeclKey { + return ClangDeclKey(decl, signature_id, UncheckedTag()); +} + +auto ClangDeclKey::ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey { + CARBON_CHECK(!isa(decl)); + return ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag()); +} + +ClangDeclKey::ClangDeclKey(clang::Decl* decl, ClangDeclSignatureId signature_id, + UncheckedTag /*_*/) + : decl(decl->getCanonicalDecl()), signature_id(signature_id) {} + auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void { RawStringOstream decl_stream; auto policy = decl->getASTContext().getPrintingPolicy(); diff --git a/toolchain/sem_ir/clang_decl.h b/toolchain/sem_ir/clang_decl.h index f65d33390ea4..7179eccb06ea 100644 --- a/toolchain/sem_ir/clang_decl.h +++ b/toolchain/sem_ir/clang_decl.h @@ -7,12 +7,16 @@ #include -#include "clang/AST/Decl.h" #include "common/hashtable_key_context.h" #include "common/ostream.h" #include "toolchain/base/canonical_value_store.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class Decl; +class FunctionDecl; +} // namespace clang + namespace Carbon::SemIR { // Information about how to form the Carbon function signature from the Clang @@ -126,16 +130,11 @@ struct ClangDeclKey : public Printable { // count is required. static auto ForFunctionDecl(clang::FunctionDecl* decl, ClangDeclSignatureId signature_id) - -> ClangDeclKey { - return ClangDeclKey(decl, signature_id, UncheckedTag()); - } + -> ClangDeclKey; // Factory function for clang declaration that is dynamically known to not be // a function declaration. - static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey { - CARBON_CHECK(!isa(decl)); - return ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag()); - } + static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey; auto Print(llvm::raw_ostream& out) const -> void; @@ -163,8 +162,7 @@ struct ClangDeclKey : public Printable { explicit UncheckedTag() = default; }; ClangDeclKey(clang::Decl* decl, ClangDeclSignatureId signature_id, - UncheckedTag /*_*/) - : decl(decl->getCanonicalDecl()), signature_id(signature_id) {} + UncheckedTag /*_*/); }; // A Clang declaration mapped to a Carbon instruction. diff --git a/toolchain/sem_ir/cpp_file.cpp b/toolchain/sem_ir/cpp_file.cpp new file mode 100644 index 000000000000..9477ea901c13 --- /dev/null +++ b/toolchain/sem_ir/cpp_file.cpp @@ -0,0 +1,57 @@ +// 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 + +#include "toolchain/sem_ir/cpp_file.h" + +#include "clang/AST/Mangle.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Frontend/CompilerInstance.h" +#include "common/check.h" + +namespace Carbon::SemIR { + +CppFile::CppFile(std::unique_ptr clang, + llvm::LLVMContext* llvm_context) + : clang_(std::move(clang)), llvm_context_(llvm_context) {} + +CppFile::~CppFile() = default; + +auto CppFile::diagnostic_options() const -> const clang::DiagnosticOptions& { + return clang_->getDiagnostics().getDiagnosticOptions(); +} + +auto CppFile::lang_options() const -> const clang::LangOptions& { + return clang_->getLangOpts(); +} + +auto CppFile::source_manager() -> clang::SourceManager& { + return clang_->getSourceManager(); +} + +auto CppFile::source_manager() const -> const clang::SourceManager& { + return clang_->getSourceManager(); +} + +auto CppFile::diagnostics() const -> clang::DiagnosticsEngine& { + return clang_->getDiagnostics(); +} + +auto CppFile::ast_context() -> clang::ASTContext& { + return clang_->getASTContext(); +} + +auto CppFile::ast_context() const -> const clang::ASTContext& { + return clang_->getASTContext(); +} + +auto CppFile::CreateMangleContext() -> void { + CARBON_CHECK(!mangle_context_); + mangle_context_.reset(ast_context().createMangleContext()); +} + +auto CppFile::mangle_context() const -> clang::MangleContext& { + return *mangle_context_; +} + +} // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/cpp_file.h b/toolchain/sem_ir/cpp_file.h index f3ab7a3043a0..3968ffdc83e8 100644 --- a/toolchain/sem_ir/cpp_file.h +++ b/toolchain/sem_ir/cpp_file.h @@ -7,16 +7,20 @@ #include -#include "clang/AST/Mangle.h" -#include "clang/Basic/CodeGenOptions.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Lex/PreprocessorOptions.h" -#include "common/check.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/FileSystem.h" +namespace clang { +class ASTContext; +class CodeGenerator; +class CompilerInstance; +class DiagnosticOptions; +class DiagnosticsEngine; +class LangOptions; +class MangleContext; +class SourceManager; +} // namespace clang + +namespace llvm { +class LLVMContext; +} // namespace llvm namespace Carbon::SemIR { @@ -25,46 +29,29 @@ namespace Carbon::SemIR { class CppFile { public: explicit CppFile(std::unique_ptr clang, - llvm::LLVMContext* llvm_context) - : clang_(std::move(clang)), llvm_context_(llvm_context) {} + llvm::LLVMContext* llvm_context); + ~CppFile(); // Access to compilation options. - auto diagnostic_options() const -> const clang::DiagnosticOptions& { - return clang_->getDiagnostics().getDiagnosticOptions(); - } - auto lang_options() const -> const clang::LangOptions& { - return clang_->getLangOpts(); - } + auto diagnostic_options() const -> const clang::DiagnosticOptions&; + auto lang_options() const -> const clang::LangOptions&; // Access to Clang's compilation environment. - auto source_manager() -> clang::SourceManager& { - return clang_->getSourceManager(); - } - auto source_manager() const -> const clang::SourceManager& { - return clang_->getSourceManager(); - } + auto source_manager() -> clang::SourceManager&; + auto source_manager() const -> const clang::SourceManager&; // TODO: This doesn't really belong here, but is currently used by lowering // because Clang's code generation may produce diagnostics. - auto diagnostics() const -> clang::DiagnosticsEngine& { - return clang_->getDiagnostics(); - } + auto diagnostics() const -> clang::DiagnosticsEngine&; // Access to layers of Clang's C++ representation. - auto ast_context() -> clang::ASTContext& { return clang_->getASTContext(); } - auto ast_context() const -> const clang::ASTContext& { - return clang_->getASTContext(); - } + auto ast_context() -> clang::ASTContext&; + auto ast_context() const -> const clang::ASTContext&; // Creates the mangle context for this file's C++ AST. Must be called once the // AST context is available (after the frontend begins the source file) and // before `mangle_context()` is used. - auto CreateMangleContext() -> void { - CARBON_CHECK(!mangle_context_); - mangle_context_.reset(ast_context().createMangleContext()); - } - auto mangle_context() const -> clang::MangleContext& { - return *mangle_context_; - } + auto CreateMangleContext() -> void; + auto mangle_context() const -> clang::MangleContext&; auto llvm_context() const -> llvm::LLVMContext* { return llvm_context_; } auto SetCodeGenerator(clang::CodeGenerator* code_generator) -> void { diff --git a/toolchain/sem_ir/cpp_overload_set.h b/toolchain/sem_ir/cpp_overload_set.h index 31716a3f4740..f5385669974a 100644 --- a/toolchain/sem_ir/cpp_overload_set.h +++ b/toolchain/sem_ir/cpp_overload_set.h @@ -5,17 +5,36 @@ #ifndef CARBON_TOOLCHAIN_SEM_IR_CPP_OVERLOAD_SET_H_ #define CARBON_TOOLCHAIN_SEM_IR_CPP_OVERLOAD_SET_H_ -#include "clang/AST/Decl.h" #include "clang/AST/UnresolvedSet.h" -#include "clang/Sema/Overload.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" #include "common/ostream.h" #include "toolchain/base/value_store.h" #include "toolchain/sem_ir/ids.h" +namespace clang { +class CXXRecordDecl; +} // namespace clang + namespace Carbon::SemIR { // An overloaded C++ function. struct CppOverloadSet : public Printable { + // Information about operator rewrites to consider when adding operator + // functions to a candidate set. + // + // This mirrors `clang::OverloadCandidateSet::OperatorRewriteInfo` so that + // this header doesn't need `clang/Sema/Overload.h`; the use sites construct + // the Clang type from these fields. + struct OperatorRewriteInfo { + // The original operator as written in the source. + clang::OverloadedOperatorKind original_operator = clang::OO_None; + // The source location of the operator. + clang::SourceLocation op_loc; + // Whether we should include rewritten candidates in the overload set. + bool allow_rewritten_candidates = false; + }; + // The function's name. NameId name_id; @@ -32,7 +51,7 @@ struct CppOverloadSet : public Printable { /// Information about operator rewrites to consider when adding operator /// functions to a candidate set. - clang::OverloadCandidateSet::OperatorRewriteInfo operator_rewrite_info; + OperatorRewriteInfo operator_rewrite_info; auto Print(llvm::raw_ostream& out) const -> void { out << "name: " << name_id << ", parent_scope: " << parent_scope_id; diff --git a/toolchain/sem_ir/diagnostic_loc_converter.cpp b/toolchain/sem_ir/diagnostic_loc_converter.cpp index aab353d9d3ed..fc80f86420d1 100644 --- a/toolchain/sem_ir/diagnostic_loc_converter.cpp +++ b/toolchain/sem_ir/diagnostic_loc_converter.cpp @@ -4,6 +4,7 @@ #include "toolchain/sem_ir/diagnostic_loc_converter.h" +#include "clang/Basic/SourceManager.h" #include "clang/Frontend/DiagnosticRenderer.h" namespace Carbon::SemIR { diff --git a/toolchain/sem_ir/name_scope.h b/toolchain/sem_ir/name_scope.h index a0ceea38957e..f7f17207813d 100644 --- a/toolchain/sem_ir/name_scope.h +++ b/toolchain/sem_ir/name_scope.h @@ -5,7 +5,6 @@ #ifndef CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_ #define CARBON_TOOLCHAIN_SEM_IR_NAME_SCOPE_H_ -#include "clang/AST/DeclBase.h" #include "common/map.h" #include "toolchain/sem_ir/clang_decl.h" #include "toolchain/sem_ir/ids.h" diff --git a/toolchain/sem_ir/type_info.cpp b/toolchain/sem_ir/type_info.cpp index fedceb28a523..064f8ad7468f 100644 --- a/toolchain/sem_ir/type_info.cpp +++ b/toolchain/sem_ir/type_info.cpp @@ -6,6 +6,7 @@ #include +#include "clang/AST/ASTContext.h" #include "common/raw_string_ostream.h" #include "toolchain/sem_ir/file.h"