1ae89987fSChandler Carruth //===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
2135bcc79SSebastian Redl //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6135bcc79SSebastian Redl //
7135bcc79SSebastian Redl //===----------------------------------------------------------------------===//
8135bcc79SSebastian Redl //
9ae89987fSChandler Carruth // This file defines the PCHGenerator, which as a SemaConsumer that generates
10ae89987fSChandler Carruth // a PCH file.
11135bcc79SSebastian Redl //
12135bcc79SSebastian Redl //===----------------------------------------------------------------------===//
13135bcc79SSebastian Redl
143a02247dSChandler Carruth #include "clang/AST/ASTContext.h"
15bd97f353SRichard Smith #include "clang/Lex/HeaderSearch.h"
163a02247dSChandler Carruth #include "clang/Lex/Preprocessor.h"
173a02247dSChandler Carruth #include "clang/Sema/SemaConsumer.h"
189670f847SMehdi Amini #include "clang/Serialization/ASTWriter.h"
19e0308279SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamWriter.h"
20135bcc79SSebastian Redl
21135bcc79SSebastian Redl using namespace clang;
22135bcc79SSebastian Redl
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)236623e1f1SDouglas Gregor PCHGenerator::PCHGenerator(
248bef5cd4SDuncan P. N. Exon Smith const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
258bef5cd4SDuncan P. N. Exon Smith StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
2661137e1aSDavid Blaikie ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
2770d759b4SDuncan P. N. Exon Smith bool AllowASTWithErrors, bool IncludeTimestamps,
2870d759b4SDuncan P. N. Exon Smith bool ShouldCacheASTInMemory)
29bd97f353SRichard Smith : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
30f6021ecdSBenjamin Kramer SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
318bef5cd4SDuncan P. N. Exon Smith Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
32030d7d6dSDuncan P. N. Exon Smith IncludeTimestamps),
3370d759b4SDuncan P. N. Exon Smith AllowASTWithErrors(AllowASTWithErrors),
3470d759b4SDuncan P. N. Exon Smith ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
35f6021ecdSBenjamin Kramer this->Buffer->IsComplete = false;
3677d993d3SDouglas Gregor }
3777d993d3SDouglas Gregor
~PCHGenerator()38637d1e66SAngel Garcia Gomez PCHGenerator::~PCHGenerator() {
39637d1e66SAngel Garcia Gomez }
40135bcc79SSebastian Redl
HandleTranslationUnit(ASTContext & Ctx)41135bcc79SSebastian Redl void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
42f0168de9SArgyrios Kyrtzidis // Don't create a PCH if there were fatal failures during module loading.
43f0168de9SArgyrios Kyrtzidis if (PP.getModuleLoader().HadFatalFailure)
44f0168de9SArgyrios Kyrtzidis return;
45f0168de9SArgyrios Kyrtzidis
46f0168de9SArgyrios Kyrtzidis bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
47f0168de9SArgyrios Kyrtzidis if (hasErrors && !AllowASTWithErrors)
48135bcc79SSebastian Redl return;
49135bcc79SSebastian Redl
50bd97f353SRichard Smith Module *Module = nullptr;
51bbcc9f04SRichard Smith if (PP.getLangOpts().isCompilingModule()) {
52bd97f353SRichard Smith Module = PP.getHeaderSearchInfo().lookupModule(
53*638c673aSJan Svoboda PP.getLangOpts().CurrentModule, SourceLocation(),
54*638c673aSJan Svoboda /*AllowSearch*/ false);
55bbcc9f04SRichard Smith if (!Module) {
56bbcc9f04SRichard Smith assert(hasErrors && "emitting module but current module doesn't exist");
57bbcc9f04SRichard Smith return;
58bbcc9f04SRichard Smith }
59bd97f353SRichard Smith }
60bd97f353SRichard Smith
61cc3fddb4SBen Langmuir // Errors that do not prevent the PCH from being written should not cause the
62cc3fddb4SBen Langmuir // overall compilation to fail either.
63cc3fddb4SBen Langmuir if (AllowASTWithErrors)
64cc3fddb4SBen Langmuir PP.getDiagnostics().getClient()->clear();
65cc3fddb4SBen Langmuir
66bb165fb0SAdrian Prantl // Emit the PCH file to the Buffer.
67135bcc79SSebastian Redl assert(SemaPtr && "No Sema?");
68a5206ce7SAdrian Prantl Buffer->Signature =
6970ec1c7eSArgyrios Kyrtzidis Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
7070ec1c7eSArgyrios Kyrtzidis // For serialization we are lenient if the errors were
7170ec1c7eSArgyrios Kyrtzidis // only warn-as-error kind.
7270d759b4SDuncan P. N. Exon Smith PP.getDiagnostics().hasUncompilableErrorOccurred(),
7370d759b4SDuncan P. N. Exon Smith ShouldCacheASTInMemory);
74135bcc79SSebastian Redl
75bb165fb0SAdrian Prantl Buffer->IsComplete = true;
76135bcc79SSebastian Redl }
77135bcc79SSebastian Redl
GetASTMutationListener()7865ad5691SArgyrios Kyrtzidis ASTMutationListener *PCHGenerator::GetASTMutationListener() {
7965ad5691SArgyrios Kyrtzidis return &Writer;
8065ad5691SArgyrios Kyrtzidis }
8165ad5691SArgyrios Kyrtzidis
GetASTDeserializationListener()823e31c724SSebastian Redl ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
83135bcc79SSebastian Redl return &Writer;
84135bcc79SSebastian Redl }
85