Jorge Gorbe Moya d2d531e097
[clang][Serialization] Stop including Frontend headers from Serialization (NFC) (#123140)
The Frontend library depends on Serialization. This is an explicit
dependency encoded in the CMake target. However, Serialization currently
has an implicit dependency on Frontend, as it includes one of its
headers. This is not reflected in the CMake build rules, but Bazel is
stricter so, in order to avoid a dependency cycle, it hackily declares
the Frontend headers as source files for Serialization.

Fortunately, the only Frontend header used by Serialization is
clang/Frontend/FrontendDiagnostic.h, which is a legacy header that just
includes clang/Basic/DiagnosticFrontend since
d076608d58d1ec55016eb747a995511e3a3f72aa, back in 2018.

This commit changes Serialization to use the underlying header from
Basic instead. Both Serialization and Frontend depend on Basic, so this
breaks the dependency cycle.
2025-01-16 10:12:04 -08:00

150 lines
5.1 KiB
C++

//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the PCHGenerator, which as a SemaConsumer that generates
// a PCH file.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Serialization/ASTWriter.h"
#include "llvm/Bitstream/BitstreamWriter.h"
using namespace clang;
PCHGenerator::PCHGenerator(
Preprocessor &PP, InMemoryModuleCache &ModuleCache, StringRef OutputFile,
StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors, bool IncludeTimestamps,
bool BuildingImplicitModule, bool ShouldCacheASTInMemory,
bool GeneratingReducedBMI)
: PP(PP), Subject(&PP), OutputFile(OutputFile), isysroot(isysroot.str()),
Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
IncludeTimestamps, BuildingImplicitModule, GeneratingReducedBMI),
AllowASTWithErrors(AllowASTWithErrors),
ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
this->Buffer->IsComplete = false;
}
PCHGenerator::~PCHGenerator() {
}
Module *PCHGenerator::getEmittingModule(ASTContext &) {
Module *M = nullptr;
if (PP.getLangOpts().isCompilingModule()) {
M = PP.getHeaderSearchInfo().lookupModule(PP.getLangOpts().CurrentModule,
SourceLocation(),
/*AllowSearch*/ false);
if (!M)
assert(PP.getDiagnostics().hasErrorOccurred() &&
"emitting module but current module doesn't exist");
}
return M;
}
DiagnosticsEngine &PCHGenerator::getDiagnostics() const {
return PP.getDiagnostics();
}
void PCHGenerator::InitializeSema(Sema &S) {
if (!PP.getHeaderSearchInfo()
.getHeaderSearchOpts()
.ModulesSerializeOnlyPreprocessor)
Subject = &S;
}
void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
// Don't create a PCH if there were fatal failures during module loading.
if (PP.getModuleLoader().HadFatalFailure)
return;
bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
if (hasErrors && !AllowASTWithErrors)
return;
Module *Module = getEmittingModule(Ctx);
// Errors that do not prevent the PCH from being written should not cause the
// overall compilation to fail either.
if (AllowASTWithErrors)
PP.getDiagnostics().getClient()->clear();
Buffer->Signature = Writer.WriteAST(Subject, OutputFile, Module, isysroot,
ShouldCacheASTInMemory);
Buffer->IsComplete = true;
}
ASTMutationListener *PCHGenerator::GetASTMutationListener() {
return &Writer;
}
ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
return &Writer;
}
void PCHGenerator::anchor() {}
CXX20ModulesGenerator::CXX20ModulesGenerator(Preprocessor &PP,
InMemoryModuleCache &ModuleCache,
StringRef OutputFile,
bool GeneratingReducedBMI,
bool AllowASTWithErrors)
: PCHGenerator(
PP, ModuleCache, OutputFile, llvm::StringRef(),
std::make_shared<PCHBuffer>(),
/*Extensions=*/ArrayRef<std::shared_ptr<ModuleFileExtension>>(),
AllowASTWithErrors, /*IncludeTimestamps=*/false,
/*BuildingImplicitModule=*/false, /*ShouldCacheASTInMemory=*/false,
GeneratingReducedBMI) {}
Module *CXX20ModulesGenerator::getEmittingModule(ASTContext &Ctx) {
Module *M = Ctx.getCurrentNamedModule();
assert(M && M->isNamedModuleUnit() &&
"CXX20ModulesGenerator should only be used with C++20 Named modules.");
return M;
}
void CXX20ModulesGenerator::HandleTranslationUnit(ASTContext &Ctx) {
// FIMXE: We'd better to wrap such options to a new class ASTWriterOptions
// since this is not about searching header really.
HeaderSearchOptions &HSOpts =
getPreprocessor().getHeaderSearchInfo().getHeaderSearchOpts();
HSOpts.ModulesSkipDiagnosticOptions = true;
HSOpts.ModulesSkipHeaderSearchPaths = true;
PCHGenerator::HandleTranslationUnit(Ctx);
if (!isComplete())
return;
std::error_code EC;
auto OS = std::make_unique<llvm::raw_fd_ostream>(getOutputFile(), EC);
if (EC) {
getDiagnostics().Report(diag::err_fe_unable_to_open_output)
<< getOutputFile() << EC.message() << "\n";
return;
}
*OS << getBufferPtr()->Data;
OS->flush();
}
void CXX20ModulesGenerator::anchor() {}
void ReducedBMIGenerator::anchor() {}