1e5dd7070Spatrick //===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file defines the PCHGenerator, which as a SemaConsumer that generates
10e5dd7070Spatrick // a PCH file.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick
14e5dd7070Spatrick #include "clang/AST/ASTContext.h"
15e5dd7070Spatrick #include "clang/Lex/HeaderSearch.h"
16e5dd7070Spatrick #include "clang/Lex/Preprocessor.h"
17e5dd7070Spatrick #include "clang/Sema/SemaConsumer.h"
18e5dd7070Spatrick #include "clang/Serialization/ASTWriter.h"
19e5dd7070Spatrick #include "llvm/Bitstream/BitstreamWriter.h"
20e5dd7070Spatrick
21e5dd7070Spatrick using namespace clang;
22e5dd7070Spatrick
PCHGenerator(const Preprocessor & PP,InMemoryModuleCache & ModuleCache,StringRef OutputFile,StringRef isysroot,std::shared_ptr<PCHBuffer> Buffer,ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,bool AllowASTWithErrors,bool IncludeTimestamps,bool ShouldCacheASTInMemory)23e5dd7070Spatrick PCHGenerator::PCHGenerator(
24e5dd7070Spatrick const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
25e5dd7070Spatrick StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
26e5dd7070Spatrick ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
27e5dd7070Spatrick bool AllowASTWithErrors, bool IncludeTimestamps,
28e5dd7070Spatrick bool ShouldCacheASTInMemory)
29e5dd7070Spatrick : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
30e5dd7070Spatrick SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
31e5dd7070Spatrick Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
32e5dd7070Spatrick IncludeTimestamps),
33e5dd7070Spatrick AllowASTWithErrors(AllowASTWithErrors),
34e5dd7070Spatrick ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
35e5dd7070Spatrick this->Buffer->IsComplete = false;
36e5dd7070Spatrick }
37e5dd7070Spatrick
~PCHGenerator()38e5dd7070Spatrick PCHGenerator::~PCHGenerator() {
39e5dd7070Spatrick }
40e5dd7070Spatrick
HandleTranslationUnit(ASTContext & Ctx)41e5dd7070Spatrick void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
42e5dd7070Spatrick // Don't create a PCH if there were fatal failures during module loading.
43e5dd7070Spatrick if (PP.getModuleLoader().HadFatalFailure)
44e5dd7070Spatrick return;
45e5dd7070Spatrick
46e5dd7070Spatrick bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
47e5dd7070Spatrick if (hasErrors && !AllowASTWithErrors)
48e5dd7070Spatrick return;
49e5dd7070Spatrick
50e5dd7070Spatrick Module *Module = nullptr;
51e5dd7070Spatrick if (PP.getLangOpts().isCompilingModule()) {
52e5dd7070Spatrick Module = PP.getHeaderSearchInfo().lookupModule(
53*12c85518Srobert PP.getLangOpts().CurrentModule, SourceLocation(),
54*12c85518Srobert /*AllowSearch*/ false);
55e5dd7070Spatrick if (!Module) {
56e5dd7070Spatrick assert(hasErrors && "emitting module but current module doesn't exist");
57e5dd7070Spatrick return;
58e5dd7070Spatrick }
59e5dd7070Spatrick }
60e5dd7070Spatrick
61ec727ea7Spatrick // Errors that do not prevent the PCH from being written should not cause the
62ec727ea7Spatrick // overall compilation to fail either.
63ec727ea7Spatrick if (AllowASTWithErrors)
64ec727ea7Spatrick PP.getDiagnostics().getClient()->clear();
65ec727ea7Spatrick
66e5dd7070Spatrick // Emit the PCH file to the Buffer.
67e5dd7070Spatrick assert(SemaPtr && "No Sema?");
68e5dd7070Spatrick Buffer->Signature =
69e5dd7070Spatrick Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
70e5dd7070Spatrick // For serialization we are lenient if the errors were
71e5dd7070Spatrick // only warn-as-error kind.
72e5dd7070Spatrick PP.getDiagnostics().hasUncompilableErrorOccurred(),
73e5dd7070Spatrick ShouldCacheASTInMemory);
74e5dd7070Spatrick
75e5dd7070Spatrick Buffer->IsComplete = true;
76e5dd7070Spatrick }
77e5dd7070Spatrick
GetASTMutationListener()78e5dd7070Spatrick ASTMutationListener *PCHGenerator::GetASTMutationListener() {
79e5dd7070Spatrick return &Writer;
80e5dd7070Spatrick }
81e5dd7070Spatrick
GetASTDeserializationListener()82e5dd7070Spatrick ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
83e5dd7070Spatrick return &Writer;
84e5dd7070Spatrick }
85