10b57cec5SDimitry Andric //===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the PCHGenerator, which as a SemaConsumer that generates
100b57cec5SDimitry Andric // a PCH file.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h"
160b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
170b57cec5SDimitry Andric #include "clang/Sema/SemaConsumer.h"
180b57cec5SDimitry Andric #include "clang/Serialization/ASTWriter.h"
190b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamWriter.h"
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric
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 BuildingImplicitModule,bool ShouldCacheASTInMemory)230b57cec5SDimitry Andric PCHGenerator::PCHGenerator(
240b57cec5SDimitry Andric const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
250b57cec5SDimitry Andric StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
260b57cec5SDimitry Andric ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
270b57cec5SDimitry Andric bool AllowASTWithErrors, bool IncludeTimestamps,
285f757f3fSDimitry Andric bool BuildingImplicitModule, bool ShouldCacheASTInMemory)
290b57cec5SDimitry Andric : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
300b57cec5SDimitry Andric SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
310b57cec5SDimitry Andric Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
325f757f3fSDimitry Andric IncludeTimestamps, BuildingImplicitModule),
330b57cec5SDimitry Andric AllowASTWithErrors(AllowASTWithErrors),
340b57cec5SDimitry Andric ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
350b57cec5SDimitry Andric this->Buffer->IsComplete = false;
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric
~PCHGenerator()380b57cec5SDimitry Andric PCHGenerator::~PCHGenerator() {
390b57cec5SDimitry Andric }
400b57cec5SDimitry Andric
HandleTranslationUnit(ASTContext & Ctx)410b57cec5SDimitry Andric void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
420b57cec5SDimitry Andric // Don't create a PCH if there were fatal failures during module loading.
430b57cec5SDimitry Andric if (PP.getModuleLoader().HadFatalFailure)
440b57cec5SDimitry Andric return;
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
470b57cec5SDimitry Andric if (hasErrors && !AllowASTWithErrors)
480b57cec5SDimitry Andric return;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric Module *Module = nullptr;
510b57cec5SDimitry Andric if (PP.getLangOpts().isCompilingModule()) {
520b57cec5SDimitry Andric Module = PP.getHeaderSearchInfo().lookupModule(
53349cc55cSDimitry Andric PP.getLangOpts().CurrentModule, SourceLocation(),
54349cc55cSDimitry Andric /*AllowSearch*/ false);
550b57cec5SDimitry Andric if (!Module) {
560b57cec5SDimitry Andric assert(hasErrors && "emitting module but current module doesn't exist");
570b57cec5SDimitry Andric return;
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
615ffd83dbSDimitry Andric // Errors that do not prevent the PCH from being written should not cause the
625ffd83dbSDimitry Andric // overall compilation to fail either.
635ffd83dbSDimitry Andric if (AllowASTWithErrors)
645ffd83dbSDimitry Andric PP.getDiagnostics().getClient()->clear();
655ffd83dbSDimitry Andric
660b57cec5SDimitry Andric // Emit the PCH file to the Buffer.
670b57cec5SDimitry Andric assert(SemaPtr && "No Sema?");
685f757f3fSDimitry Andric Buffer->Signature = Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
690b57cec5SDimitry Andric ShouldCacheASTInMemory);
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric Buffer->IsComplete = true;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
GetASTMutationListener()740b57cec5SDimitry Andric ASTMutationListener *PCHGenerator::GetASTMutationListener() {
750b57cec5SDimitry Andric return &Writer;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric
GetASTDeserializationListener()780b57cec5SDimitry Andric ASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
790b57cec5SDimitry Andric return &Writer;
800b57cec5SDimitry Andric }
81