1234353Sdim//===--- GeneratePCH.cpp - Sema Consumer for PCH Generation -----*- C++ -*-===//
2212795Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6212795Sdim//
7212795Sdim//===----------------------------------------------------------------------===//
8212795Sdim//
9234353Sdim//  This file defines the PCHGenerator, which as a SemaConsumer that generates
10234353Sdim//  a PCH file.
11212795Sdim//
12212795Sdim//===----------------------------------------------------------------------===//
13212795Sdim
14212795Sdim#include "clang/AST/ASTContext.h"
15314564Sdim#include "clang/Lex/HeaderSearch.h"
16212795Sdim#include "clang/Lex/Preprocessor.h"
17249423Sdim#include "clang/Sema/SemaConsumer.h"
18314564Sdim#include "clang/Serialization/ASTWriter.h"
19353358Sdim#include "llvm/Bitstream/BitstreamWriter.h"
20212795Sdim
21212795Sdimusing namespace clang;
22212795Sdim
23296417SdimPCHGenerator::PCHGenerator(
24353358Sdim    const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
25353358Sdim    StringRef OutputFile, StringRef isysroot, std::shared_ptr<PCHBuffer> Buffer,
26314564Sdim    ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
27353358Sdim    bool AllowASTWithErrors, bool IncludeTimestamps,
28353358Sdim    bool ShouldCacheASTInMemory)
29314564Sdim    : PP(PP), OutputFile(OutputFile), isysroot(isysroot.str()),
30321369Sdim      SemaPtr(nullptr), Buffer(std::move(Buffer)), Stream(this->Buffer->Data),
31353358Sdim      Writer(Stream, this->Buffer->Data, ModuleCache, Extensions,
32321369Sdim             IncludeTimestamps),
33353358Sdim      AllowASTWithErrors(AllowASTWithErrors),
34353358Sdim      ShouldCacheASTInMemory(ShouldCacheASTInMemory) {
35321369Sdim  this->Buffer->IsComplete = false;
36212795Sdim}
37212795Sdim
38226633SdimPCHGenerator::~PCHGenerator() {
39226633Sdim}
40226633Sdim
41212795Sdimvoid PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) {
42261991Sdim  // Don't create a PCH if there were fatal failures during module loading.
43261991Sdim  if (PP.getModuleLoader().HadFatalFailure)
44212795Sdim    return;
45261991Sdim
46261991Sdim  bool hasErrors = PP.getDiagnostics().hasErrorOccurred();
47261991Sdim  if (hasErrors && !AllowASTWithErrors)
48261991Sdim    return;
49288943Sdim
50314564Sdim  Module *Module = nullptr;
51314564Sdim  if (PP.getLangOpts().isCompilingModule()) {
52314564Sdim    Module = PP.getHeaderSearchInfo().lookupModule(
53314564Sdim        PP.getLangOpts().CurrentModule, /*AllowSearch*/ false);
54314564Sdim    if (!Module) {
55314564Sdim      assert(hasErrors && "emitting module but current module doesn't exist");
56314564Sdim      return;
57314564Sdim    }
58314564Sdim  }
59314564Sdim
60288943Sdim  // Emit the PCH file to the Buffer.
61212795Sdim  assert(SemaPtr && "No Sema?");
62296417Sdim  Buffer->Signature =
63309124Sdim      Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot,
64309124Sdim                      // For serialization we are lenient if the errors were
65309124Sdim                      // only warn-as-error kind.
66353358Sdim                      PP.getDiagnostics().hasUncompilableErrorOccurred(),
67353358Sdim                      ShouldCacheASTInMemory);
68212795Sdim
69288943Sdim  Buffer->IsComplete = true;
70212795Sdim}
71212795Sdim
72218893SdimASTMutationListener *PCHGenerator::GetASTMutationListener() {
73226633Sdim  return &Writer;
74218893Sdim}
75218893Sdim
76212795SdimASTDeserializationListener *PCHGenerator::GetASTDeserializationListener() {
77212795Sdim  return &Writer;
78212795Sdim}
79