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