//===- ASTWriter.cpp - AST File Writer ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the ASTWriter class, which writes AST files.
//
//===----------------------------------------------------------------------===//

#include "ASTCommon.h"
#include "ASTReaderInternals.h"
#include "MultiOnDiskHashTable.h"
#include "TemplateArgumentHasher.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/AbstractTypeWriter.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclContextInternals.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenACCClause.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileEntry.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OpenCLOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/Version.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/ModuleMap.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "clang/Lex/Token.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/ObjCMethodList.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaCUDA.h"
#include "clang/Sema/SemaObjC.h"
#include "clang/Sema/Weak.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTRecordWriter.h"
#include "clang/Serialization/InMemoryModuleCache.h"
#include "clang/Serialization/ModuleCache.h"
#include "clang/Serialization/ModuleFile.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "clang/Serialization/SerializationDiagnostic.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Bitstream/BitCodes.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/DJB.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/OnDiskHashTable.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SHA1.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/VersionTuple.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <limits>
#include <memory>
#include <optional>
#include <queue>
#include <tuple>
#include <utility>
#include <vector>

using namespace clang;
using namespace clang::serialization;

template <typename T, typename Allocator>
static StringRef bytes(const std::vector<T, Allocator> &v) {
  if (v.empty()) return StringRef();
  return StringRef(reinterpret_cast<const char*>(&v[0]),
                         sizeof(T) * v.size());
}

template <typename T>
static StringRef bytes(const SmallVectorImpl<T> &v) {
  return StringRef(reinterpret_cast<const char*>(v.data()),
                         sizeof(T) * v.size());
}

static std::string bytes(const std::vector<bool> &V) {
  std::string Str;
  Str.reserve(V.size() / 8);
  for (unsigned I = 0, E = V.size(); I < E;) {
    char Byte = 0;
    for (unsigned Bit = 0; Bit < 8 && I < E; ++Bit, ++I)
      Byte |= V[I] << Bit;
    Str += Byte;
  }
  return Str;
}

//===----------------------------------------------------------------------===//
// Type serialization
//===----------------------------------------------------------------------===//

static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) {
  switch (id) {
#define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \
  case Type::CLASS_ID: return TYPE_##CODE_ID;
#include "clang/Serialization/TypeBitCodes.def"
  case Type::LateParsedAttr:
    llvm_unreachable(
        "should be replaced with a concrete type before serialization");
  case Type::Builtin:
    llvm_unreachable("shouldn't be serializing a builtin type this way");
  }
  llvm_unreachable("bad type kind");
}

namespace {

struct AffectingModuleMaps {
  llvm::DenseSet<FileID> DefinitionFileIDs;
  llvm::DenseSet<const FileEntry *> DefinitionFiles;
};

std::optional<AffectingModuleMaps>
GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
  if (!PP.getHeaderSearchInfo()
           .getHeaderSearchOpts()
           .ModulesPruneNonAffectingModuleMaps)
    return std::nullopt;

  const HeaderSearch &HS = PP.getHeaderSearchInfo();
  const SourceManager &SM = PP.getSourceManager();
  const ModuleMap &MM = HS.getModuleMap();

  // Module maps used only by textual headers are special. Their FileID is
  // non-affecting, but their FileEntry is (i.e. must be written as InputFile).
  enum AffectedReason : bool {
    AR_TextualHeader = 0,
    AR_ImportOrTextualHeader = 1,
  };
  auto AssignMostImportant = [](AffectedReason &LHS, AffectedReason RHS) {
    LHS = std::max(LHS, RHS);
  };
  llvm::DenseMap<FileID, AffectedReason> ModuleMaps;
  llvm::DenseMap<const Module *, AffectedReason> ProcessedModules;
  auto CollectModuleMapsForHierarchy = [&](const Module *M,
                                           AffectedReason Reason) {
    M = M->getTopLevelModule();

    // We need to process the header either when it was not present or when we
    // previously flagged module map as textual headers and now we found a
    // proper import.
    if (auto [It, Inserted] = ProcessedModules.insert({M, Reason});
        !Inserted && Reason <= It->second) {
      return;
    } else {
      It->second = Reason;
    }

    std::queue<const Module *> Q;
    Q.push(M);
    while (!Q.empty()) {
      const Module *Mod = Q.front();
      Q.pop();

      // The containing module map is affecting, because it's being pointed
      // into by Module::DefinitionLoc.
      if (auto F = MM.getContainingModuleMapFileID(Mod); F.isValid())
        AssignMostImportant(ModuleMaps[F], Reason);
      // For inferred modules, the module map that allowed inferring is not
      // related to the virtual containing module map file. It did affect the
      // compilation, though.
      if (auto UniqF = MM.getModuleMapFileIDForUniquing(Mod); UniqF.isValid())
        AssignMostImportant(ModuleMaps[UniqF], Reason);

      for (Module *SubM : Mod->submodules())
        Q.push(SubM);
    }
  };

  // Handle all the affecting modules referenced from the root module.

  CollectModuleMapsForHierarchy(RootModule, AR_ImportOrTextualHeader);

  std::queue<const Module *> Q;
  Q.push(RootModule);
  while (!Q.empty()) {
    const Module *CurrentModule = Q.front();
    Q.pop();

    for (const Module *ImportedModule : CurrentModule->Imports)
      CollectModuleMapsForHierarchy(ImportedModule, AR_ImportOrTextualHeader);
    for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses)
      CollectModuleMapsForHierarchy(UndeclaredModule, AR_ImportOrTextualHeader);

    for (Module *M : CurrentModule->submodules())
      Q.push(M);
  }

  // Handle textually-included headers that belong to other modules.
  HS.forEachExistingLocalFileInfo(
      [&](FileEntryRef File, const HeaderFileInfo &HFI) {
        if (!HFI.isCompilingModuleHeader && HFI.isModuleHeader)
          return; // Modular header, handled in the above module-based loop.
        if (!HFI.isCompilingModuleHeader && !HFI.IsLocallyIncluded)
          return; // Non-modular header not included locally is not affecting.

        for (const auto &KH : HS.findResolvedModulesForHeader(File))
          if (const Module *M = KH.getModule())
            CollectModuleMapsForHierarchy(M, AR_TextualHeader);
      });

  // FIXME: This algorithm is not correct for module map hierarchies where
  // module map file defining a (sub)module of a top-level module X includes
  // a module map file that defines a (sub)module of another top-level module Y.
  // Whenever X is affecting and Y is not, "replaying" this PCM file will fail
  // when parsing module map files for X due to not knowing about the `extern`
  // module map for Y.
  //
  // We don't have a good way to fix it here. We could mark all children of
  // affecting module map files as being affecting as well, but that's
  // expensive. SourceManager does not model the edge from parent to child
  // SLocEntries, so instead, we would need to iterate over leaf module map
  // files, walk up their include hierarchy and check whether we arrive at an
  // affecting module map.
  //
  // Instead of complicating and slowing down this function, we should probably
  // just ban module map hierarchies where module map defining a (sub)module X
  // includes a module map defining a module that's not a submodule of X.

  llvm::DenseSet<const FileEntry *> ModuleFileEntries;
  llvm::DenseSet<FileID> ModuleFileIDs;
  for (auto [FID, Reason] : ModuleMaps) {
    if (Reason == AR_ImportOrTextualHeader)
      ModuleFileIDs.insert(FID);
    if (auto *FE = SM.getFileEntryForID(FID))
      ModuleFileEntries.insert(FE);
  }

  AffectingModuleMaps R;
  R.DefinitionFileIDs = std::move(ModuleFileIDs);
  R.DefinitionFiles = std::move(ModuleFileEntries);
  return std::move(R);
}

class ASTTypeWriter {
  ASTWriter &Writer;
  ASTWriter::RecordData Record;
  ASTRecordWriter BasicWriter;

public:
  ASTTypeWriter(ASTContext &Context, ASTWriter &Writer)
      : Writer(Writer), BasicWriter(Context, Writer, Record) {}

  uint64_t write(QualType T) {
    if (T.hasLocalNonFastQualifiers()) {
      Qualifiers Qs = T.getLocalQualifiers();
      BasicWriter.writeQualType(T.getLocalUnqualifiedType());
      BasicWriter.writeQualifiers(Qs);
      return BasicWriter.Emit(TYPE_EXT_QUAL, Writer.getTypeExtQualAbbrev());
    }

    const Type *typePtr = T.getTypePtr();
    serialization::AbstractTypeWriter<ASTRecordWriter> atw(BasicWriter);
    atw.write(typePtr);
    return BasicWriter.Emit(getTypeCodeForTypeClass(typePtr->getTypeClass()),
                            /*abbrev*/ 0);
  }
};

class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
  ASTRecordWriter &Record;

  void addSourceLocation(SourceLocation Loc) { Record.AddSourceLocation(Loc); }
  void addSourceRange(SourceRange Range) { Record.AddSourceRange(Range); }

public:
  TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {}

#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
#include "clang/AST/TypeLocNodes.def"

  void VisitArrayTypeLoc(ArrayTypeLoc TyLoc);
  void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc);
  void VisitTagTypeLoc(TagTypeLoc TL);
};

} // namespace

void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
  // nothing to do
}

void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
  addSourceLocation(TL.getBuiltinLoc());
  if (TL.needsExtraLocalData()) {
    Record.push_back(TL.getWrittenTypeSpec());
    Record.push_back(static_cast<uint64_t>(TL.getWrittenSignSpec()));
    Record.push_back(static_cast<uint64_t>(TL.getWrittenWidthSpec()));
    Record.push_back(TL.hasModeAttr());
  }
}

void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) {
  addSourceLocation(TL.getStarLoc());
}

void TypeLocWriter::VisitDecayedTypeLoc(DecayedTypeLoc TL) {
  // nothing to do
}

void TypeLocWriter::VisitAdjustedTypeLoc(AdjustedTypeLoc TL) {
  // nothing to do
}

void TypeLocWriter::VisitArrayParameterTypeLoc(ArrayParameterTypeLoc TL) {
  // nothing to do
}

void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
  addSourceLocation(TL.getCaretLoc());
}

void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
  addSourceLocation(TL.getAmpLoc());
}

void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
  addSourceLocation(TL.getAmpAmpLoc());
}

void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
  addSourceLocation(TL.getStarLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
}

void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) {
  addSourceLocation(TL.getLBracketLoc());
  addSourceLocation(TL.getRBracketLoc());
  Record.push_back(TL.getSizeExpr() ? 1 : 0);
  if (TL.getSizeExpr())
    Record.AddStmt(TL.getSizeExpr());
}

void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
  VisitArrayTypeLoc(TL);
}

void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
  VisitArrayTypeLoc(TL);
}

void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
  VisitArrayTypeLoc(TL);
}

void TypeLocWriter::VisitDependentSizedArrayTypeLoc(
                                            DependentSizedArrayTypeLoc TL) {
  VisitArrayTypeLoc(TL);
}

void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(
    DependentAddressSpaceTypeLoc TL) {
  addSourceLocation(TL.getAttrNameLoc());
  SourceRange range = TL.getAttrOperandParensRange();
  addSourceLocation(range.getBegin());
  addSourceLocation(range.getEnd());
  Record.AddStmt(TL.getAttrExprOperand());
}

void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
                                        DependentSizedExtVectorTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitDependentVectorTypeLoc(
    DependentVectorTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {
  addSourceLocation(TL.getAttrNameLoc());
  SourceRange range = TL.getAttrOperandParensRange();
  addSourceLocation(range.getBegin());
  addSourceLocation(range.getEnd());
  Record.AddStmt(TL.getAttrRowOperand());
  Record.AddStmt(TL.getAttrColumnOperand());
}

void TypeLocWriter::VisitDependentSizedMatrixTypeLoc(
    DependentSizedMatrixTypeLoc TL) {
  addSourceLocation(TL.getAttrNameLoc());
  SourceRange range = TL.getAttrOperandParensRange();
  addSourceLocation(range.getBegin());
  addSourceLocation(range.getEnd());
  Record.AddStmt(TL.getAttrRowOperand());
  Record.AddStmt(TL.getAttrColumnOperand());
}

void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
  addSourceLocation(TL.getLocalRangeBegin());
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
  addSourceRange(TL.getExceptionSpecRange());
  addSourceLocation(TL.getLocalRangeEnd());
  for (unsigned i = 0, e = TL.getNumParams(); i != e; ++i)
    Record.AddDeclRef(TL.getParam(i));
}

void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
  VisitFunctionTypeLoc(TL);
}

void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
  VisitFunctionTypeLoc(TL);
}

void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitUsingTypeLoc(UsingTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitObjCTypeParamTypeLoc(ObjCTypeParamTypeLoc TL) {
  if (TL.getNumProtocols()) {
    addSourceLocation(TL.getProtocolLAngleLoc());
    addSourceLocation(TL.getProtocolRAngleLoc());
  }
  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
    addSourceLocation(TL.getProtocolLoc(i));
}

void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
  addSourceLocation(TL.getTypeofLoc());
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
}

void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
  addSourceLocation(TL.getTypeofLoc());
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
  Record.AddTypeSourceInfo(TL.getUnmodifiedTInfo());
}

void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
  addSourceLocation(TL.getDecltypeLoc());
  addSourceLocation(TL.getRParenLoc());
}

void TypeLocWriter::VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
  addSourceLocation(TL.getKWLoc());
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
  Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());
}

void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) {
  assert(CR);
  AddNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc());
  AddSourceLocation(CR->getTemplateKWLoc());
  AddDeclarationNameInfo(CR->getConceptNameInfo());
  AddDeclRef(CR->getFoundDecl());
  AddDeclRef(CR->getNamedConcept());
  push_back(CR->getTemplateArgsAsWritten() != nullptr);
  if (CR->getTemplateArgsAsWritten())
    AddASTTemplateArgumentListInfo(CR->getTemplateArgsAsWritten());
}

void TypeLocWriter::VisitPackIndexingTypeLoc(PackIndexingTypeLoc TL) {
  addSourceLocation(TL.getEllipsisLoc());
}

void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
  auto *CR = TL.getConceptReference();
  Record.push_back(TL.isConstrained() && CR);
  if (TL.isConstrained() && CR)
    Record.AddConceptReference(CR);
  Record.push_back(TL.isDecltypeAuto());
  if (TL.isDecltypeAuto())
    addSourceLocation(TL.getRParenLoc());
}

void TypeLocWriter::VisitDeducedTemplateSpecializationTypeLoc(
    DeducedTemplateSpecializationTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getTemplateNameLoc());
}

void TypeLocWriter::VisitTagTypeLoc(TagTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) {
  VisitTagTypeLoc(TL);
}

void TypeLocWriter::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
  VisitTagTypeLoc(TL);
}

void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { VisitTagTypeLoc(TL); }

void TypeLocWriter::VisitAttributedTypeLoc(AttributedTypeLoc TL) {
  Record.AddAttr(TL.getAttr());
}

void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) {
  // Nothing to do
}

void TypeLocWriter::VisitLateParsedAttrTypeLoc(LateParsedAttrTypeLoc TL) {
  llvm_unreachable(
      "should be replaced with a concrete type before serialization");
}

void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) {
  // Nothing to do.
}

void TypeLocWriter::VisitOverflowBehaviorTypeLoc(OverflowBehaviorTypeLoc TL) {
  addSourceLocation(TL.getAttrLoc());
}

void TypeLocWriter::VisitHLSLAttributedResourceTypeLoc(
    HLSLAttributedResourceTypeLoc TL) {
  // Nothing to do.
}

void TypeLocWriter::VisitHLSLInlineSpirvTypeLoc(HLSLInlineSpirvTypeLoc TL) {
  // Nothing to do.
}

void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc(
                                            SubstTemplateTypeParmTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitSubstTemplateTypeParmPackTypeLoc(
                                          SubstTemplateTypeParmPackTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitSubstBuiltinTemplatePackTypeLoc(
    SubstBuiltinTemplatePackTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitTemplateSpecializationTypeLoc(
                                           TemplateSpecializationTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getTemplateKeywordLoc());
  addSourceLocation(TL.getTemplateNameLoc());
  addSourceLocation(TL.getLAngleLoc());
  addSourceLocation(TL.getRAngleLoc());
  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
    Record.AddTemplateArgumentLocInfo(TL.getArgLoc(i));
}

void TypeLocWriter::VisitParenTypeLoc(ParenTypeLoc TL) {
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
}

void TypeLocWriter::VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
  addSourceLocation(TL.getExpansionLoc());
}

void TypeLocWriter::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
  addSourceLocation(TL.getElaboratedKeywordLoc());
  Record.AddNestedNameSpecifierLoc(TL.getQualifierLoc());
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) {
  addSourceLocation(TL.getEllipsisLoc());
}

void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
  addSourceLocation(TL.getNameEndLoc());
}

void TypeLocWriter::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
  Record.push_back(TL.hasBaseTypeAsWritten());
  addSourceLocation(TL.getTypeArgsLAngleLoc());
  addSourceLocation(TL.getTypeArgsRAngleLoc());
  for (unsigned i = 0, e = TL.getNumTypeArgs(); i != e; ++i)
    Record.AddTypeSourceInfo(TL.getTypeArgTInfo(i));
  addSourceLocation(TL.getProtocolLAngleLoc());
  addSourceLocation(TL.getProtocolRAngleLoc());
  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
    addSourceLocation(TL.getProtocolLoc(i));
}

void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
  addSourceLocation(TL.getStarLoc());
}

void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
  addSourceLocation(TL.getKWLoc());
  addSourceLocation(TL.getLParenLoc());
  addSourceLocation(TL.getRParenLoc());
}

void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
  addSourceLocation(TL.getKWLoc());
}
void TypeLocWriter::VisitBitIntTypeLoc(clang::BitIntTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}
void TypeLocWriter::VisitDependentBitIntTypeLoc(
    clang::DependentBitIntTypeLoc TL) {
  addSourceLocation(TL.getNameLoc());
}

void TypeLocWriter::VisitPredefinedSugarTypeLoc(
    clang::PredefinedSugarTypeLoc TL) {
  // Nothing to do.
}

void ASTWriter::WriteTypeAbbrevs() {
  using namespace llvm;

  std::shared_ptr<BitCodeAbbrev> Abv;

  // Abbreviation for TYPE_EXT_QUAL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::TYPE_EXT_QUAL));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // Type
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 3));   // Quals
  TypeExtQualAbbrev = Stream.EmitAbbrev(std::move(Abv));
}

//===----------------------------------------------------------------------===//
// ASTWriter Implementation
//===----------------------------------------------------------------------===//

static void EmitBlockID(unsigned ID, const char *Name,
                        llvm::BitstreamWriter &Stream,
                        ASTWriter::RecordDataImpl &Record) {
  Record.clear();
  Record.push_back(ID);
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);

  // Emit the block name if present.
  if (!Name || Name[0] == 0)
    return;
  Record.clear();
  while (*Name)
    Record.push_back(*Name++);
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record);
}

static void EmitRecordID(unsigned ID, const char *Name,
                         llvm::BitstreamWriter &Stream,
                         ASTWriter::RecordDataImpl &Record) {
  Record.clear();
  Record.push_back(ID);
  while (*Name)
    Record.push_back(*Name++);
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
}

static void AddStmtsExprs(llvm::BitstreamWriter &Stream,
                          ASTWriter::RecordDataImpl &Record) {
#define RECORD(X) EmitRecordID(X, #X, Stream, Record)
  RECORD(STMT_STOP);
  RECORD(STMT_NULL_PTR);
  RECORD(STMT_REF_PTR);
  RECORD(STMT_NULL);
  RECORD(STMT_COMPOUND);
  RECORD(STMT_CASE);
  RECORD(STMT_DEFAULT);
  RECORD(STMT_LABEL);
  RECORD(STMT_ATTRIBUTED);
  RECORD(STMT_IF);
  RECORD(STMT_SWITCH);
  RECORD(STMT_WHILE);
  RECORD(STMT_DO);
  RECORD(STMT_FOR);
  RECORD(STMT_GOTO);
  RECORD(STMT_INDIRECT_GOTO);
  RECORD(STMT_CONTINUE);
  RECORD(STMT_BREAK);
  RECORD(STMT_RETURN);
  RECORD(STMT_DECL);
  RECORD(STMT_GCCASM);
  RECORD(STMT_MSASM);
  RECORD(EXPR_PREDEFINED);
  RECORD(EXPR_DECL_REF);
  RECORD(EXPR_INTEGER_LITERAL);
  RECORD(EXPR_FIXEDPOINT_LITERAL);
  RECORD(EXPR_FLOATING_LITERAL);
  RECORD(EXPR_IMAGINARY_LITERAL);
  RECORD(EXPR_STRING_LITERAL);
  RECORD(EXPR_CHARACTER_LITERAL);
  RECORD(EXPR_PAREN);
  RECORD(EXPR_PAREN_LIST);
  RECORD(EXPR_UNARY_OPERATOR);
  RECORD(EXPR_SIZEOF_ALIGN_OF);
  RECORD(EXPR_ARRAY_SUBSCRIPT);
  RECORD(EXPR_CALL);
  RECORD(EXPR_MEMBER);
  RECORD(EXPR_BINARY_OPERATOR);
  RECORD(EXPR_COMPOUND_ASSIGN_OPERATOR);
  RECORD(EXPR_CONDITIONAL_OPERATOR);
  RECORD(EXPR_IMPLICIT_CAST);
  RECORD(EXPR_CSTYLE_CAST);
  RECORD(EXPR_COMPOUND_LITERAL);
  RECORD(EXPR_EXT_VECTOR_ELEMENT);
  RECORD(EXPR_INIT_LIST);
  RECORD(EXPR_DESIGNATED_INIT);
  RECORD(EXPR_DESIGNATED_INIT_UPDATE);
  RECORD(EXPR_IMPLICIT_VALUE_INIT);
  RECORD(EXPR_NO_INIT);
  RECORD(EXPR_VA_ARG);
  RECORD(EXPR_ADDR_LABEL);
  RECORD(EXPR_STMT);
  RECORD(EXPR_CHOOSE);
  RECORD(EXPR_GNU_NULL);
  RECORD(EXPR_SHUFFLE_VECTOR);
  RECORD(EXPR_BLOCK);
  RECORD(EXPR_GENERIC_SELECTION);
  RECORD(EXPR_OBJC_STRING_LITERAL);
  RECORD(EXPR_OBJC_BOXED_EXPRESSION);
  RECORD(EXPR_OBJC_ARRAY_LITERAL);
  RECORD(EXPR_OBJC_DICTIONARY_LITERAL);
  RECORD(EXPR_OBJC_ENCODE);
  RECORD(EXPR_OBJC_SELECTOR_EXPR);
  RECORD(EXPR_OBJC_PROTOCOL_EXPR);
  RECORD(EXPR_OBJC_IVAR_REF_EXPR);
  RECORD(EXPR_OBJC_PROPERTY_REF_EXPR);
  RECORD(EXPR_OBJC_KVC_REF_EXPR);
  RECORD(EXPR_OBJC_MESSAGE_EXPR);
  RECORD(STMT_OBJC_FOR_COLLECTION);
  RECORD(STMT_OBJC_CATCH);
  RECORD(STMT_OBJC_FINALLY);
  RECORD(STMT_OBJC_AT_TRY);
  RECORD(STMT_OBJC_AT_SYNCHRONIZED);
  RECORD(STMT_OBJC_AT_THROW);
  RECORD(EXPR_OBJC_BOOL_LITERAL);
  RECORD(STMT_CXX_CATCH);
  RECORD(STMT_CXX_TRY);
  RECORD(STMT_CXX_FOR_RANGE);
  RECORD(EXPR_CXX_OPERATOR_CALL);
  RECORD(EXPR_CXX_MEMBER_CALL);
  RECORD(EXPR_CXX_REWRITTEN_BINARY_OPERATOR);
  RECORD(EXPR_CXX_CONSTRUCT);
  RECORD(EXPR_CXX_TEMPORARY_OBJECT);
  RECORD(EXPR_CXX_STATIC_CAST);
  RECORD(EXPR_CXX_DYNAMIC_CAST);
  RECORD(EXPR_CXX_REINTERPRET_CAST);
  RECORD(EXPR_CXX_CONST_CAST);
  RECORD(EXPR_CXX_ADDRSPACE_CAST);
  RECORD(EXPR_CXX_FUNCTIONAL_CAST);
  RECORD(EXPR_USER_DEFINED_LITERAL);
  RECORD(EXPR_CXX_STD_INITIALIZER_LIST);
  RECORD(EXPR_CXX_BOOL_LITERAL);
  RECORD(EXPR_CXX_PAREN_LIST_INIT);
  RECORD(EXPR_CXX_NULL_PTR_LITERAL);
  RECORD(EXPR_CXX_TYPEID_EXPR);
  RECORD(EXPR_CXX_TYPEID_TYPE);
  RECORD(EXPR_CXX_THIS);
  RECORD(EXPR_CXX_THROW);
  RECORD(EXPR_CXX_DEFAULT_ARG);
  RECORD(EXPR_CXX_DEFAULT_INIT);
  RECORD(EXPR_CXX_BIND_TEMPORARY);
  RECORD(EXPR_CXX_SCALAR_VALUE_INIT);
  RECORD(EXPR_CXX_NEW);
  RECORD(EXPR_CXX_DELETE);
  RECORD(EXPR_CXX_PSEUDO_DESTRUCTOR);
  RECORD(EXPR_EXPR_WITH_CLEANUPS);
  RECORD(EXPR_CXX_DEPENDENT_SCOPE_MEMBER);
  RECORD(EXPR_CXX_DEPENDENT_SCOPE_DECL_REF);
  RECORD(EXPR_CXX_UNRESOLVED_CONSTRUCT);
  RECORD(EXPR_CXX_UNRESOLVED_MEMBER);
  RECORD(EXPR_CXX_UNRESOLVED_LOOKUP);
  RECORD(EXPR_CXX_EXPRESSION_TRAIT);
  RECORD(EXPR_CXX_NOEXCEPT);
  RECORD(EXPR_OPAQUE_VALUE);
  RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR);
  RECORD(EXPR_TYPE_TRAIT);
  RECORD(EXPR_ARRAY_TYPE_TRAIT);
  RECORD(EXPR_PACK_EXPANSION);
  RECORD(EXPR_SIZEOF_PACK);
  RECORD(EXPR_PACK_INDEXING);
  RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM);
  RECORD(EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK);
  RECORD(EXPR_FUNCTION_PARM_PACK);
  RECORD(EXPR_MATERIALIZE_TEMPORARY);
  RECORD(EXPR_CUDA_KERNEL_CALL);
  RECORD(EXPR_CXX_UUIDOF_EXPR);
  RECORD(EXPR_CXX_UUIDOF_TYPE);
  RECORD(EXPR_LAMBDA);
#undef RECORD
}

void ASTWriter::WriteBlockInfoBlock() {
  RecordData Record;
  Stream.EnterBlockInfoBlock();

#define BLOCK(X) EmitBlockID(X ## _ID, #X, Stream, Record)
#define RECORD(X) EmitRecordID(X, #X, Stream, Record)

  // Control Block.
  BLOCK(CONTROL_BLOCK);
  RECORD(METADATA);
  RECORD(MODULE_NAME);
  RECORD(MODULE_DIRECTORY);
  RECORD(MODULE_MAP_FILE);
  RECORD(IMPORT);
  RECORD(ORIGINAL_FILE);
  RECORD(ORIGINAL_FILE_ID);
  RECORD(INPUT_FILE_OFFSETS);

  BLOCK(OPTIONS_BLOCK);
  RECORD(LANGUAGE_OPTIONS);
  RECORD(CODEGEN_OPTIONS);
  RECORD(TARGET_OPTIONS);
  RECORD(FILE_SYSTEM_OPTIONS);
  RECORD(HEADER_SEARCH_OPTIONS);
  RECORD(PREPROCESSOR_OPTIONS);

  BLOCK(INPUT_FILES_BLOCK);
  RECORD(INPUT_FILE);
  RECORD(INPUT_FILE_HASH);

  // AST Top-Level Block.
  BLOCK(AST_BLOCK);
  RECORD(SUBMODULE_METADATA);
  RECORD(TYPE_OFFSET);
  RECORD(DECL_OFFSET);
  RECORD(IDENTIFIER_OFFSET);
  RECORD(IDENTIFIER_TABLE);
  RECORD(EAGERLY_DESERIALIZED_DECLS);
  RECORD(MODULAR_CODEGEN_DECLS);
  RECORD(SPECIAL_TYPES);
  RECORD(STATISTICS);
  RECORD(TENTATIVE_DEFINITIONS);
  RECORD(SELECTOR_OFFSETS);
  RECORD(METHOD_POOL);
  RECORD(PP_COUNTER_VALUE);
  RECORD(SOURCE_LOCATION_OFFSETS);
  RECORD(EXT_VECTOR_DECLS);
  RECORD(UNUSED_FILESCOPED_DECLS);
  RECORD(PPD_ENTITIES_OFFSETS);
  RECORD(VTABLE_USES);
  RECORD(PPD_SKIPPED_RANGES);
  RECORD(REFERENCED_SELECTOR_POOL);
  RECORD(TU_UPDATE_LEXICAL);
  RECORD(SEMA_DECL_REFS);
  RECORD(WEAK_UNDECLARED_IDENTIFIERS);
  RECORD(EXTNAME_UNDECLARED_IDENTIFIERS);
  RECORD(PENDING_IMPLICIT_INSTANTIATIONS);
  RECORD(UPDATE_VISIBLE);
  RECORD(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD);
  RECORD(RELATED_DECLS_MAP);
  RECORD(DECL_UPDATE_OFFSETS);
  RECORD(DECL_UPDATES);
  RECORD(CUDA_SPECIAL_DECL_REFS);
  RECORD(HEADER_SEARCH_TABLE);
  RECORD(FP_PRAGMA_OPTIONS);
  RECORD(OPENCL_EXTENSIONS);
  RECORD(OPENCL_EXTENSION_TYPES);
  RECORD(OPENCL_EXTENSION_DECLS);
  RECORD(DELEGATING_CTORS);
  RECORD(KNOWN_NAMESPACES);
  RECORD(MODULE_OFFSET_MAP);
  RECORD(SOURCE_MANAGER_LINE_TABLE);
  RECORD(OBJC_CATEGORIES_MAP);
  RECORD(FILE_SORTED_DECLS);
  RECORD(IMPORTED_MODULES);
  RECORD(OBJC_CATEGORIES);
  RECORD(MACRO_OFFSET);
  RECORD(INTERESTING_IDENTIFIERS);
  RECORD(UNDEFINED_BUT_USED);
  RECORD(LATE_PARSED_TEMPLATE);
  RECORD(OPTIMIZE_PRAGMA_OPTIONS);
  RECORD(MSSTRUCT_PRAGMA_OPTIONS);
  RECORD(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS);
  RECORD(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES);
  RECORD(DELETE_EXPRS_TO_ANALYZE);
  RECORD(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH);
  RECORD(PP_CONDITIONAL_STACK);
  RECORD(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS);
  RECORD(PP_ASSUME_NONNULL_LOC);
  RECORD(PP_UNSAFE_BUFFER_USAGE);
  RECORD(VTABLES_TO_EMIT);
  RECORD(RISCV_VECTOR_INTRINSICS_PRAGMA);

  // SourceManager Block.
  BLOCK(SOURCE_MANAGER_BLOCK);
  RECORD(SM_SLOC_FILE_ENTRY);
  RECORD(SM_SLOC_BUFFER_ENTRY);
  RECORD(SM_SLOC_BUFFER_BLOB);
  RECORD(SM_SLOC_BUFFER_BLOB_COMPRESSED);
  RECORD(SM_SLOC_EXPANSION_ENTRY);

  // Preprocessor Block.
  BLOCK(PREPROCESSOR_BLOCK);
  RECORD(PP_MACRO_DIRECTIVE_HISTORY);
  RECORD(PP_MACRO_FUNCTION_LIKE);
  RECORD(PP_MACRO_OBJECT_LIKE);
  RECORD(PP_MODULE_MACRO);
  RECORD(PP_TOKEN);

  // Submodule Block.
  BLOCK(SUBMODULE_BLOCK);
  RECORD(SUBMODULE_END);
  RECORD(SUBMODULE_DEFINITION);
  RECORD(SUBMODULE_UMBRELLA_HEADER);
  RECORD(SUBMODULE_HEADER);
  RECORD(SUBMODULE_TOPHEADER);
  RECORD(SUBMODULE_UMBRELLA_DIR);
  RECORD(SUBMODULE_IMPORTS);
  RECORD(SUBMODULE_AFFECTING_MODULES);
  RECORD(SUBMODULE_EXPORTS);
  RECORD(SUBMODULE_REQUIRES);
  RECORD(SUBMODULE_EXCLUDED_HEADER);
  RECORD(SUBMODULE_LINK_LIBRARY);
  RECORD(SUBMODULE_CONFIG_MACRO);
  RECORD(SUBMODULE_CONFLICT);
  RECORD(SUBMODULE_PRIVATE_HEADER);
  RECORD(SUBMODULE_TEXTUAL_HEADER);
  RECORD(SUBMODULE_PRIVATE_TEXTUAL_HEADER);
  RECORD(SUBMODULE_INITIALIZERS);
  RECORD(SUBMODULE_EXPORT_AS);
  RECORD(SUBMODULE_CHILD);

  // Comments Block.
  BLOCK(COMMENTS_BLOCK);
  RECORD(COMMENTS_RAW_COMMENT);

  // Decls and Types block.
  BLOCK(DECLTYPES_BLOCK);
  RECORD(TYPE_EXT_QUAL);
  RECORD(TYPE_COMPLEX);
  RECORD(TYPE_POINTER);
  RECORD(TYPE_BLOCK_POINTER);
  RECORD(TYPE_LVALUE_REFERENCE);
  RECORD(TYPE_RVALUE_REFERENCE);
  RECORD(TYPE_MEMBER_POINTER);
  RECORD(TYPE_CONSTANT_ARRAY);
  RECORD(TYPE_INCOMPLETE_ARRAY);
  RECORD(TYPE_VARIABLE_ARRAY);
  RECORD(TYPE_VECTOR);
  RECORD(TYPE_EXT_VECTOR);
  RECORD(TYPE_FUNCTION_NO_PROTO);
  RECORD(TYPE_FUNCTION_PROTO);
  RECORD(TYPE_TYPEDEF);
  RECORD(TYPE_TYPEOF_EXPR);
  RECORD(TYPE_TYPEOF);
  RECORD(TYPE_RECORD);
  RECORD(TYPE_ENUM);
  RECORD(TYPE_OBJC_INTERFACE);
  RECORD(TYPE_OBJC_OBJECT_POINTER);
  RECORD(TYPE_DECLTYPE);
  RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM);
  RECORD(TYPE_UNRESOLVED_USING);
  RECORD(TYPE_INJECTED_CLASS_NAME);
  RECORD(TYPE_OBJC_OBJECT);
  RECORD(TYPE_TEMPLATE_TYPE_PARM);
  RECORD(TYPE_TEMPLATE_SPECIALIZATION);
  RECORD(TYPE_DEPENDENT_NAME);
  RECORD(TYPE_DEPENDENT_SIZED_ARRAY);
  RECORD(TYPE_PAREN);
  RECORD(TYPE_MACRO_QUALIFIED);
  RECORD(TYPE_PACK_EXPANSION);
  RECORD(TYPE_ATTRIBUTED);
  RECORD(TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK);
  RECORD(TYPE_SUBST_BUILTIN_TEMPLATE_PACK);
  RECORD(TYPE_AUTO);
  RECORD(TYPE_UNARY_TRANSFORM);
  RECORD(TYPE_ATOMIC);
  RECORD(TYPE_DECAYED);
  RECORD(TYPE_ADJUSTED);
  RECORD(TYPE_OBJC_TYPE_PARAM);
  RECORD(LOCAL_REDECLARATIONS);
  RECORD(DECL_TYPEDEF);
  RECORD(DECL_TYPEALIAS);
  RECORD(DECL_ENUM);
  RECORD(DECL_RECORD);
  RECORD(DECL_ENUM_CONSTANT);
  RECORD(DECL_FUNCTION);
  RECORD(DECL_OBJC_METHOD);
  RECORD(DECL_OBJC_INTERFACE);
  RECORD(DECL_OBJC_PROTOCOL);
  RECORD(DECL_OBJC_IVAR);
  RECORD(DECL_OBJC_AT_DEFS_FIELD);
  RECORD(DECL_OBJC_CATEGORY);
  RECORD(DECL_OBJC_CATEGORY_IMPL);
  RECORD(DECL_OBJC_IMPLEMENTATION);
  RECORD(DECL_OBJC_COMPATIBLE_ALIAS);
  RECORD(DECL_OBJC_PROPERTY);
  RECORD(DECL_OBJC_PROPERTY_IMPL);
  RECORD(DECL_FIELD);
  RECORD(DECL_MS_PROPERTY);
  RECORD(DECL_VAR);
  RECORD(DECL_IMPLICIT_PARAM);
  RECORD(DECL_PARM_VAR);
  RECORD(DECL_FILE_SCOPE_ASM);
  RECORD(DECL_BLOCK);
  RECORD(DECL_CONTEXT_LEXICAL);
  RECORD(DECL_CONTEXT_VISIBLE);
  RECORD(DECL_CONTEXT_MODULE_LOCAL_VISIBLE);
  RECORD(DECL_NAMESPACE);
  RECORD(DECL_NAMESPACE_ALIAS);
  RECORD(DECL_USING);
  RECORD(DECL_USING_SHADOW);
  RECORD(DECL_USING_DIRECTIVE);
  RECORD(DECL_UNRESOLVED_USING_VALUE);
  RECORD(DECL_UNRESOLVED_USING_TYPENAME);
  RECORD(DECL_LINKAGE_SPEC);
  RECORD(DECL_EXPORT);
  RECORD(DECL_CXX_RECORD);
  RECORD(DECL_CXX_METHOD);
  RECORD(DECL_CXX_CONSTRUCTOR);
  RECORD(DECL_CXX_DESTRUCTOR);
  RECORD(DECL_CXX_CONVERSION);
  RECORD(DECL_ACCESS_SPEC);
  RECORD(DECL_FRIEND);
  RECORD(DECL_FRIEND_TEMPLATE);
  RECORD(DECL_CLASS_TEMPLATE);
  RECORD(DECL_CLASS_TEMPLATE_SPECIALIZATION);
  RECORD(DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION);
  RECORD(DECL_VAR_TEMPLATE);
  RECORD(DECL_VAR_TEMPLATE_SPECIALIZATION);
  RECORD(DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION);
  RECORD(DECL_FUNCTION_TEMPLATE);
  RECORD(DECL_TEMPLATE_TYPE_PARM);
  RECORD(DECL_NON_TYPE_TEMPLATE_PARM);
  RECORD(DECL_TEMPLATE_TEMPLATE_PARM);
  RECORD(DECL_CONCEPT);
  RECORD(DECL_REQUIRES_EXPR_BODY);
  RECORD(DECL_TYPE_ALIAS_TEMPLATE);
  RECORD(DECL_STATIC_ASSERT);
  RECORD(DECL_CXX_BASE_SPECIFIERS);
  RECORD(DECL_CXX_CTOR_INITIALIZERS);
  RECORD(DECL_INDIRECTFIELD);
  RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);
  RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK);
  RECORD(DECL_IMPORT);
  RECORD(DECL_OMP_THREADPRIVATE);
  RECORD(DECL_EMPTY);
  RECORD(DECL_OBJC_TYPE_PARAM);
  RECORD(DECL_OMP_CAPTUREDEXPR);
  RECORD(DECL_PRAGMA_COMMENT);
  RECORD(DECL_PRAGMA_DETECT_MISMATCH);
  RECORD(DECL_OMP_DECLARE_REDUCTION);
  RECORD(DECL_OMP_ALLOCATE);
  RECORD(DECL_HLSL_BUFFER);
  RECORD(DECL_OPENACC_DECLARE);
  RECORD(DECL_OPENACC_ROUTINE);

  // Statements and Exprs can occur in the Decls and Types block.
  AddStmtsExprs(Stream, Record);

  BLOCK(PREPROCESSOR_DETAIL_BLOCK);
  RECORD(PPD_MACRO_EXPANSION);
  RECORD(PPD_MACRO_DEFINITION);
  RECORD(PPD_INCLUSION_DIRECTIVE);

  // Decls and Types block.
  BLOCK(EXTENSION_BLOCK);
  RECORD(EXTENSION_METADATA);

  BLOCK(UNHASHED_CONTROL_BLOCK);
  RECORD(SIGNATURE);
  RECORD(AST_BLOCK_HASH);
  RECORD(DIAGNOSTIC_OPTIONS);
  RECORD(HEADER_SEARCH_PATHS);
  RECORD(DIAG_PRAGMA_MAPPINGS);
  RECORD(HEADER_SEARCH_ENTRY_USAGE);
  RECORD(VFS_USAGE);

#undef RECORD
#undef BLOCK
  Stream.ExitBlock();
}

/// Adjusts the given filename to only write out the portion of the
/// filename that is not part of the system root directory.
///
/// \param Filename the file name to adjust.
///
/// \param BaseDir When non-NULL, the PCH file is a relocatable AST file and
/// the returned filename will be adjusted by this root directory.
///
/// \returns either the original filename (if it needs no adjustment) or the
/// adjusted filename (which points into the @p Filename parameter).
static const char *
adjustFilenameForRelocatableAST(const char *Filename, StringRef BaseDir) {
  assert(Filename && "No file name to adjust?");

  if (BaseDir.empty())
    return Filename;

  // Verify that the filename and the system root have the same prefix.
  unsigned Pos = 0;
  for (; Filename[Pos] && Pos < BaseDir.size(); ++Pos)
    if (Filename[Pos] != BaseDir[Pos])
      return Filename; // Prefixes don't match.

  // We hit the end of the filename before we hit the end of the system root.
  if (!Filename[Pos])
    return Filename;

  // If there's not a path separator at the end of the base directory nor
  // immediately after it, then this isn't within the base directory.
  if (!llvm::sys::path::is_separator(Filename[Pos])) {
    if (!llvm::sys::path::is_separator(BaseDir.back()))
      return Filename;
  } else {
    // If the file name has a '/' at the current position, skip over the '/'.
    // We distinguish relative paths from absolute paths by the
    // absence of '/' at the beginning of relative paths.
    //
    // FIXME: This is wrong. We distinguish them by asking if the path is
    // absolute, which isn't the same thing. And there might be multiple '/'s
    // in a row. Use a better mechanism to indicate whether we have emitted an
    // absolute or relative path.
    ++Pos;
  }

  return Filename + Pos;
}

std::pair<ASTFileSignature, ASTFileSignature>
ASTWriter::createSignature() const {
  StringRef AllBytes(Buffer.data(), Buffer.size());

  llvm::SHA1 Hasher;
  Hasher.update(AllBytes.slice(ASTBlockRange.first, ASTBlockRange.second));
  ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hasher.result());

  // Add the remaining bytes:
  //  1. Before the unhashed control block.
  Hasher.update(AllBytes.slice(0, UnhashedControlBlockRange.first));
  //  2. Between the unhashed control block and the AST block.
  Hasher.update(
      AllBytes.slice(UnhashedControlBlockRange.second, ASTBlockRange.first));
  //  3. After the AST block.
  Hasher.update(AllBytes.substr(ASTBlockRange.second));
  ASTFileSignature Signature = ASTFileSignature::create(Hasher.result());

  return std::make_pair(ASTBlockHash, Signature);
}

ASTFileSignature ASTWriter::createSignatureForNamedModule() const {
  llvm::SHA1 Hasher;
  Hasher.update(StringRef(Buffer.data(), Buffer.size()));

  assert(WritingModule);
  assert(WritingModule->isNamedModule());

  // We need to combine all the export imported modules no matter
  // we used it or not.
  for (auto [ExportImported, _] : WritingModule->Exports)
    Hasher.update(ExportImported->Signature);

  // We combine all the used modules to make sure the signature is precise.
  // Consider the case like:
  //
  // // a.cppm
  // export module a;
  // export inline int a() { ... }
  //
  // // b.cppm
  // export module b;
  // import a;
  // export inline int b() { return a(); }
  //
  // Since both `a()` and `b()` are inline, we need to make sure the BMI of
  // `b.pcm` will change after the implementation of `a()` changes. We can't
  // get that naturally since we won't record the body of `a()` during the
  // writing process. We can't reuse ODRHash here since ODRHash won't calculate
  // the called function recursively. So ODRHash will be problematic if `a()`
  // calls other inline functions.
  //
  // Probably we can solve this by a new hash mechanism. But the safety and
  // efficiency may a problem too. Here we just combine the hash value of the
  // used modules conservatively.
  for (Module *M : TouchedTopLevelModules)
    Hasher.update(M->Signature);

  return ASTFileSignature::create(Hasher.result());
}

static void BackpatchSignatureAt(llvm::BitstreamWriter &Stream,
                                 const ASTFileSignature &S, uint64_t BitNo) {
  for (uint8_t Byte : S) {
    Stream.BackpatchByte(BitNo, Byte);
    BitNo += 8;
  }
}

ASTFileSignature ASTWriter::backpatchSignature() {
  if (isWritingStdCXXNamedModules()) {
    ASTFileSignature Signature = createSignatureForNamedModule();
    BackpatchSignatureAt(Stream, Signature, SignatureOffset);
    return Signature;
  }

  if (!WritingModule ||
      !PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)
    return {};

  // For implicit modules, write the hash of the PCM as its signature.
  ASTFileSignature ASTBlockHash;
  ASTFileSignature Signature;
  std::tie(ASTBlockHash, Signature) = createSignature();

  BackpatchSignatureAt(Stream, ASTBlockHash, ASTBlockHashOffset);
  BackpatchSignatureAt(Stream, Signature, SignatureOffset);

  return Signature;
}

void ASTWriter::writeUnhashedControlBlock(Preprocessor &PP) {
  using namespace llvm;

  // Flush first to prepare the PCM hash (signature).
  Stream.FlushToWord();
  UnhashedControlBlockRange.first = Stream.GetCurrentBitNo() >> 3;

  // Enter the block and prepare to write records.
  RecordData Record;
  Stream.EnterSubblock(UNHASHED_CONTROL_BLOCK_ID, 5);

  // For implicit modules and C++20 named modules, write the hash of the PCM as
  // its signature.
  if (isWritingStdCXXNamedModules() ||
      (WritingModule &&
       PP.getHeaderSearchInfo().getHeaderSearchOpts().ModulesHashContent)) {
    // At this point, we don't know the actual signature of the file or the AST
    // block - we're only able to compute those at the end of the serialization
    // process. Let's store dummy signatures for now, and replace them with the
    // real ones later on.
    // The bitstream VBR-encodes record elements, which makes backpatching them
    // really difficult. Let's store the signatures as blobs instead - they are
    // guaranteed to be word-aligned, and we control their format/encoding.
    auto Dummy = ASTFileSignature::createDummy();
    SmallString<128> Blob{Dummy.begin(), Dummy.end()};

    // We don't need AST Block hash in named modules.
    if (!isWritingStdCXXNamedModules()) {
      auto Abbrev = std::make_shared<BitCodeAbbrev>();
      Abbrev->Add(BitCodeAbbrevOp(AST_BLOCK_HASH));
      Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
      unsigned ASTBlockHashAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

      Record.push_back(AST_BLOCK_HASH);
      Stream.EmitRecordWithBlob(ASTBlockHashAbbrev, Record, Blob);
      ASTBlockHashOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;
      Record.clear();
    }

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(SIGNATURE));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned SignatureAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    Record.push_back(SIGNATURE);
    Stream.EmitRecordWithBlob(SignatureAbbrev, Record, Blob);
    SignatureOffset = Stream.GetCurrentBitNo() - Blob.size() * 8;
    Record.clear();
  }

  const auto &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();

  // Diagnostic options.
  const auto &Diags = PP.getDiagnostics();
  const DiagnosticOptions &DiagOpts = Diags.getDiagnosticOptions();
  if (!HSOpts.ModulesSkipDiagnosticOptions) {
#define DIAGOPT(Name, Bits, Default) Record.push_back(DiagOpts.Name);
#define ENUM_DIAGOPT(Name, Type, Bits, Default)                                \
  Record.push_back(static_cast<unsigned>(DiagOpts.get##Name()));
#include "clang/Basic/DiagnosticOptions.def"
    Record.push_back(DiagOpts.Warnings.size());
    for (unsigned I = 0, N = DiagOpts.Warnings.size(); I != N; ++I)
      AddString(DiagOpts.Warnings[I], Record);
    Record.push_back(DiagOpts.Remarks.size());
    for (unsigned I = 0, N = DiagOpts.Remarks.size(); I != N; ++I)
      AddString(DiagOpts.Remarks[I], Record);
    // Note: we don't serialize the log or serialization file names, because
    // they are generally transient files and will almost always be overridden.
    Stream.EmitRecord(DIAGNOSTIC_OPTIONS, Record);
    Record.clear();
  }

  // Header search paths.
  if (!HSOpts.ModulesSkipHeaderSearchPaths) {
    // Include entries.
    Record.push_back(HSOpts.UserEntries.size());
    for (unsigned I = 0, N = HSOpts.UserEntries.size(); I != N; ++I) {
      const HeaderSearchOptions::Entry &Entry = HSOpts.UserEntries[I];
      AddString(Entry.Path, Record);
      Record.push_back(static_cast<unsigned>(Entry.Group));
      Record.push_back(Entry.IsFramework);
      Record.push_back(Entry.IgnoreSysRoot);
    }

    // System header prefixes.
    Record.push_back(HSOpts.SystemHeaderPrefixes.size());
    for (unsigned I = 0, N = HSOpts.SystemHeaderPrefixes.size(); I != N; ++I) {
      AddString(HSOpts.SystemHeaderPrefixes[I].Prefix, Record);
      Record.push_back(HSOpts.SystemHeaderPrefixes[I].IsSystemHeader);
    }

    // VFS overlay files.
    Record.push_back(HSOpts.VFSOverlayFiles.size());
    for (StringRef VFSOverlayFile : HSOpts.VFSOverlayFiles)
      AddString(VFSOverlayFile, Record);

    Stream.EmitRecord(HEADER_SEARCH_PATHS, Record);
  }

  if (!HSOpts.ModulesSkipPragmaDiagnosticMappings)
    WritePragmaDiagnosticMappings(Diags, /* isModule = */ WritingModule);

  // Header search entry usage.
  {
    auto HSEntryUsage = PP.getHeaderSearchInfo().computeUserEntryUsage();
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_ENTRY_USAGE));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // Bit vector.
    unsigned HSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
    RecordData::value_type Record[] = {HEADER_SEARCH_ENTRY_USAGE,
                                       HSEntryUsage.size()};
    Stream.EmitRecordWithBlob(HSUsageAbbrevCode, Record, bytes(HSEntryUsage));
  }

  // VFS usage.
  {
    auto VFSUsage = PP.getHeaderSearchInfo().collectVFSUsageAndClear();
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(VFS_USAGE));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // Number of bits.
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));      // Bit vector.
    unsigned VFSUsageAbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
    RecordData::value_type Record[] = {VFS_USAGE, VFSUsage.size()};
    Stream.EmitRecordWithBlob(VFSUsageAbbrevCode, Record, bytes(VFSUsage));
  }

  // Leave the options block.
  Stream.ExitBlock();
  UnhashedControlBlockRange.second = Stream.GetCurrentBitNo() >> 3;
}

/// Write the control block.
void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {
  using namespace llvm;

  SourceManager &SourceMgr = PP.getSourceManager();
  FileManager &FileMgr = PP.getFileManager();

  Stream.EnterSubblock(CONTROL_BLOCK_ID, 5);
  RecordData Record;

  // Metadata
  auto MetadataAbbrev = std::make_shared<BitCodeAbbrev>();
  MetadataAbbrev->Add(BitCodeAbbrevOp(METADATA));
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Major
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Minor
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang maj.
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
  // Standard C++ module
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1));
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors
  MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
  unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev));
  assert((!WritingModule || isysroot.empty()) &&
         "writing module as a relocatable PCH?");
  {
    RecordData::value_type Record[] = {METADATA,
                                       VERSION_MAJOR,
                                       VERSION_MINOR,
                                       CLANG_VERSION_MAJOR,
                                       CLANG_VERSION_MINOR,
                                       !isysroot.empty(),
                                       isWritingStdCXXNamedModules(),
                                       IncludeTimestamps,
                                       ASTHasCompilerErrors};
    Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
                              getClangFullRepositoryVersion());
  }

  if (WritingModule) {
    // Module name
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
    unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
    RecordData::value_type Record[] = {MODULE_NAME};
    Stream.EmitRecordWithBlob(AbbrevCode, Record, WritingModule->Name);

    auto BaseDir = [&]() -> std::optional<SmallString<128>> {
      if (PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd) {
        // Use the current working directory as the base path for all inputs.
        auto CWD = FileMgr.getOptionalDirectoryRef(".");
        return CWD->getName();
      }
      if (WritingModule->Directory) {
        return WritingModule->Directory->getName();
      }
      return std::nullopt;
    }();
    if (BaseDir) {
      FileMgr.makeAbsolutePath(*BaseDir, /*Canonicalize=*/true);

      // If the home of the module is the current working directory, then we
      // want to pick up the cwd of the build process loading the module, not
      // our cwd, when we load this module.
      if (!PP.getHeaderSearchInfo().getHeaderSearchOpts().ModuleFileHomeIsCwd &&
          (!PP.getHeaderSearchInfo()
                .getHeaderSearchOpts()
                .ModuleMapFileHomeIsCwd ||
           WritingModule->Directory->getName() != ".")) {
        // Module directory.
        auto Abbrev = std::make_shared<BitCodeAbbrev>();
        Abbrev->Add(BitCodeAbbrevOp(MODULE_DIRECTORY));
        Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Directory
        unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

        RecordData::value_type Record[] = {MODULE_DIRECTORY};
        Stream.EmitRecordWithBlob(AbbrevCode, Record, *BaseDir);
      }

      // Write out all other paths relative to the base directory if possible.
      BaseDirectory.assign(BaseDir->begin(), BaseDir->end());
    }
  } else if (!isysroot.empty()) {
    // Write out paths relative to the sysroot if possible.
    SmallString<128> CleanedSysroot(isysroot);
    PP.getFileManager().makeAbsolutePath(CleanedSysroot, /*Canonicalize=*/true);
    BaseDirectory.assign(CleanedSysroot.begin(), CleanedSysroot.end());
  }

  // Module map file
  if (WritingModule && WritingModule->Kind == Module::ModuleMapModule) {
    Record.clear();

    auto &Map = PP.getHeaderSearchInfo().getModuleMap();
    AddPath(WritingModule->PresumedModuleMapFile.empty()
                ? Map.getModuleMapFileForUniquing(WritingModule)
                      ->getNameAsRequested()
                : StringRef(WritingModule->PresumedModuleMapFile),
            Record);

    // Additional module map files.
    if (auto *AdditionalModMaps =
            Map.getAdditionalModuleMapFiles(WritingModule)) {
      Record.push_back(AdditionalModMaps->size());
      SmallVector<FileEntryRef, 1> ModMaps(AdditionalModMaps->begin(),
                                           AdditionalModMaps->end());
      llvm::sort(ModMaps, [](FileEntryRef A, FileEntryRef B) {
        return A.getName() < B.getName();
      });
      for (FileEntryRef F : ModMaps)
        AddPath(F.getName(), Record);
    } else {
      Record.push_back(0);
    }

    Stream.EmitRecord(MODULE_MAP_FILE, Record);
  }

  // Imports
  if (Chain) {
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(IMPORT));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ImportLoc
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Module name len
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Standard C++ mod
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File size
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File timestamp
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File name raw kind
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File name len
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Strings
    unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

    SmallString<128> Blob;

    for (ModuleFile &M : Chain->getModuleManager()) {
      // Skip modules that weren't directly imported.
      if (!M.isDirectlyImported())
        continue;

      Record.clear();
      Blob.clear();

      Record.push_back(IMPORT);
      Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding
      AddSourceLocation(M.ImportLoc, Record);
      AddStringBlob(M.ModuleName, Record, Blob);
      Record.push_back(M.StandardCXXModule);

      // We don't want to hard code the information about imported modules
      // in the C++20 named modules.
      if (M.StandardCXXModule) {
        Record.push_back(0);
        Record.push_back(0);
        Record.push_back(0);
        Record.push_back(0);
      } else {
        // If we have calculated signature, there is no need to store
        // the size or timestamp.
        Record.push_back(M.Signature ? 0 : M.Size);
        Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.ModTime));

        Record.push_back(M.FileName.getRawKind());

        llvm::append_range(Blob, M.Signature);

        AddPathBlob(M.FileName, Record, Blob);
      }

      Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob);
    }
  }

  // Write the options block.
  Stream.EnterSubblock(OPTIONS_BLOCK_ID, 4);

  // Language options.
  Record.clear();
  const LangOptions &LangOpts = PP.getLangOpts();
  Record.push_back(static_cast<unsigned>(LangOpts.LangStd));
  const uint64_t LanguageOptionValues[] = {
#define LANGOPT(Name, Bits, Default, Compatibility, Description) LangOpts.Name,
#define ENUM_LANGOPT(Name, Type, Bits, Default, Compatibility, Description)    \
  static_cast<unsigned>(LangOpts.get##Name()),
#include "clang/Basic/LangOptions.def"
#define SANITIZER(NAME, ID) LangOpts.Sanitize.has(SanitizerKind::ID),
#include "clang/Basic/Sanitizers.def"
  };
  llvm::append_range(Record, LanguageOptionValues);

  Record.push_back(LangOpts.ModuleFeatures.size());
  for (StringRef Feature : LangOpts.ModuleFeatures)
    AddString(Feature, Record);

  Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind());
  AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record);

  AddString(LangOpts.CurrentModule, Record);

  // Comment options.
  Record.push_back(LangOpts.CommentOpts.BlockCommandNames.size());
  for (const auto &I : LangOpts.CommentOpts.BlockCommandNames) {
    AddString(I, Record);
  }
  Record.push_back(LangOpts.CommentOpts.ParseAllComments);

  // OpenMP offloading options.
  Record.push_back(LangOpts.OMPTargetTriples.size());
  for (auto &T : LangOpts.OMPTargetTriples)
    AddString(T.getTriple(), Record);

  AddString(LangOpts.OMPHostIRFile, Record);

  Stream.EmitRecord(LANGUAGE_OPTIONS, Record);

  // Codegen options.
  // FIXME: Replace with C++20 `using enum CodeGenOptions::CompatibilityKind`.
  using CK = CodeGenOptions::CompatibilityKind;
  Record.clear();
  const CodeGenOptions &CGOpts = getCodeGenOpts();
#define CODEGENOPT(Name, Bits, Default, Compatibility)                         \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    Record.push_back(static_cast<unsigned>(CGOpts.Name));
#define ENUM_CODEGENOPT(Name, Type, Bits, Default, Compatibility)              \
  if constexpr (CK::Compatibility != CK::Benign)                               \
    Record.push_back(static_cast<unsigned>(CGOpts.get##Name()));
#define DEBUGOPT(Name, Bits, Default, Compatibility)
#define VALUE_DEBUGOPT(Name, Bits, Default, Compatibility)
#define ENUM_DEBUGOPT(Name, Type, Bits, Default, Compatibility)
#include "clang/Basic/CodeGenOptions.def"
  Stream.EmitRecord(CODEGEN_OPTIONS, Record);

  // Target options.
  Record.clear();
  const TargetInfo &Target = PP.getTargetInfo();
  const TargetOptions &TargetOpts = Target.getTargetOpts();
  AddString(TargetOpts.Triple, Record);
  AddString(TargetOpts.CPU, Record);
  AddString(TargetOpts.TuneCPU, Record);
  AddString(TargetOpts.ABI, Record);
  Record.push_back(TargetOpts.FeaturesAsWritten.size());
  for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size(); I != N; ++I) {
    AddString(TargetOpts.FeaturesAsWritten[I], Record);
  }
  Record.push_back(TargetOpts.Features.size());
  for (unsigned I = 0, N = TargetOpts.Features.size(); I != N; ++I) {
    AddString(TargetOpts.Features[I], Record);
  }
  Stream.EmitRecord(TARGET_OPTIONS, Record);

  // File system options.
  Record.clear();
  const FileSystemOptions &FSOpts = FileMgr.getFileSystemOpts();
  AddString(FSOpts.WorkingDir, Record);
  Stream.EmitRecord(FILE_SYSTEM_OPTIONS, Record);

  // Header search options.
  Record.clear();
  const HeaderSearchOptions &HSOpts =
      PP.getHeaderSearchInfo().getHeaderSearchOpts();

  StringRef HSOpts_ModuleCachePath =
      PP.getHeaderSearchInfo().getNormalizedModuleCachePath();

  AddString(HSOpts.Sysroot, Record);
  AddString(HSOpts.ResourceDir, Record);
  AddString(HSOpts_ModuleCachePath, Record);
  AddString(HSOpts.ModuleUserBuildPath, Record);
  Record.push_back(HSOpts.DisableModuleHash);
  Record.push_back(HSOpts.ImplicitModuleMaps);
  Record.push_back(HSOpts.ModuleMapFileHomeIsCwd);
  Record.push_back(HSOpts.EnablePrebuiltImplicitModules);
  Record.push_back(HSOpts.UseBuiltinIncludes);
  Record.push_back(HSOpts.UseStandardSystemIncludes);
  Record.push_back(HSOpts.UseStandardCXXIncludes);
  Record.push_back(HSOpts.UseLibcxx);
  AddString(PP.getHeaderSearchInfo().getContextHash(), Record);
  Stream.EmitRecord(HEADER_SEARCH_OPTIONS, Record);

  // Preprocessor options.
  Record.clear();
  const PreprocessorOptions &PPOpts = PP.getPreprocessorOpts();

  // If we're building an implicit module with a context hash, the importer is
  // guaranteed to have the same macros defined on the command line. Skip
  // writing them.
  bool SkipMacros = BuildingImplicitModule && !HSOpts.DisableModuleHash;
  bool WriteMacros = !SkipMacros;
  Record.push_back(WriteMacros);
  if (WriteMacros) {
    // Macro definitions.
    Record.push_back(PPOpts.Macros.size());
    for (unsigned I = 0, N = PPOpts.Macros.size(); I != N; ++I) {
      AddString(PPOpts.Macros[I].first, Record);
      Record.push_back(PPOpts.Macros[I].second);
    }
  }

  // Includes
  Record.push_back(PPOpts.Includes.size());
  for (unsigned I = 0, N = PPOpts.Includes.size(); I != N; ++I)
    AddString(PPOpts.Includes[I], Record);

  // Macro includes
  Record.push_back(PPOpts.MacroIncludes.size());
  for (unsigned I = 0, N = PPOpts.MacroIncludes.size(); I != N; ++I)
    AddString(PPOpts.MacroIncludes[I], Record);

  Record.push_back(PPOpts.UsePredefines);
  // Detailed record is important since it is used for the module cache hash.
  Record.push_back(PPOpts.DetailedRecord);

  // FIXME: Using `AddString` to record `ImplicitPCHInclude` does not handle
  // relocatable files. We probably should call
  // `AddPath(PPOpts.ImplicitPCHInclude, Record)` to properly support chained
  // relocatable PCHs.
  AddString(PPOpts.ImplicitPCHInclude, Record);
  Record.push_back(static_cast<unsigned>(PPOpts.ObjCXXARCStandardLibrary));
  Stream.EmitRecord(PREPROCESSOR_OPTIONS, Record);

  // Leave the options block.
  Stream.ExitBlock();

  // Original file name and file ID
  if (auto MainFile =
          SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID())) {
    auto FileAbbrev = std::make_shared<BitCodeAbbrev>();
    FileAbbrev->Add(BitCodeAbbrevOp(ORIGINAL_FILE));
    FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File ID
    FileAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
    unsigned FileAbbrevCode = Stream.EmitAbbrev(std::move(FileAbbrev));

    Record.clear();
    Record.push_back(ORIGINAL_FILE);
    AddFileID(SourceMgr.getMainFileID(), Record);
    EmitRecordWithPath(FileAbbrevCode, Record, MainFile->getName());
  }

  Record.clear();
  AddFileID(SourceMgr.getMainFileID(), Record);
  Stream.EmitRecord(ORIGINAL_FILE_ID, Record);

  WriteInputFiles(SourceMgr);
  Stream.ExitBlock();
}

namespace  {

/// An input file.
struct InputFileEntry {
  FileEntryRef File;
  bool IsSystemFile;
  bool IsTransient;
  bool BufferOverridden;
  bool IsTopLevel;
  bool IsModuleMap;
  uint32_t ContentHash[2];

  InputFileEntry(FileEntryRef File) : File(File) {}

  void trySetContentHash(
      Preprocessor &PP,
      llvm::function_ref<std::optional<llvm::MemoryBufferRef>()> GetMemBuff) {
    ContentHash[0] = 0;
    ContentHash[1] = 0;

    if (!PP.getHeaderSearchInfo()
             .getHeaderSearchOpts()
             .ValidateASTInputFilesContent)
      return;

    auto MemBuff = GetMemBuff();
    if (!MemBuff) {
      PP.Diag(SourceLocation(), diag::err_module_unable_to_hash_content)
          << File.getName();
      return;
    }

    uint64_t Hash = xxh3_64bits(MemBuff->getBuffer());
    ContentHash[0] = uint32_t(Hash);
    ContentHash[1] = uint32_t(Hash >> 32);
  }
};

} // namespace

SourceLocation ASTWriter::getAffectingIncludeLoc(const SourceManager &SourceMgr,
                                                 const SrcMgr::FileInfo &File) {
  SourceLocation IncludeLoc = File.getIncludeLoc();
  if (IncludeLoc.isValid()) {
    FileID IncludeFID = SourceMgr.getFileID(IncludeLoc);
    assert(IncludeFID.isValid() && "IncludeLoc in invalid file");
    if (!IsSLocAffecting[IncludeFID.ID])
      IncludeLoc = SourceLocation();
  }
  return IncludeLoc;
}

void ASTWriter::WriteInputFiles(SourceManager &SourceMgr) {
  using namespace llvm;

  Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4);

  // Create input-file abbreviation.
  auto IFAbbrev = std::make_shared<BitCodeAbbrev>();
  IFAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE));
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 12)); // Size
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // Modification time
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Overridden
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Transient
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Top-level
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Module map
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // Name as req. len
  IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name as req. + name
  unsigned IFAbbrevCode = Stream.EmitAbbrev(std::move(IFAbbrev));

  // Create input file hash abbreviation.
  auto IFHAbbrev = std::make_shared<BitCodeAbbrev>();
  IFHAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_HASH));
  IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  IFHAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  unsigned IFHAbbrevCode = Stream.EmitAbbrev(std::move(IFHAbbrev));

  uint64_t InputFilesOffsetBase = Stream.GetCurrentBitNo();

  // Get all ContentCache objects for files.
  std::vector<InputFileEntry> UserFiles;
  std::vector<InputFileEntry> SystemFiles;
  for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) {
    // Get this source location entry.
    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);
    assert(&SourceMgr.getSLocEntry(FileID::get(I)) == SLoc);

    // We only care about file entries that were not overridden.
    if (!SLoc->isFile())
      continue;
    const SrcMgr::FileInfo &File = SLoc->getFile();
    const SrcMgr::ContentCache *Cache = &File.getContentCache();
    if (!Cache->OrigEntry)
      continue;

    // Do not emit input files that do not affect current module.
    if (!IsSLocFileEntryAffecting[I])
      continue;

    InputFileEntry Entry(*Cache->OrigEntry);
    Entry.IsSystemFile = isSystem(File.getFileCharacteristic());
    Entry.IsTransient = Cache->IsTransient;
    Entry.BufferOverridden = Cache->BufferOverridden;

    FileID IncludeFileID = SourceMgr.getFileID(File.getIncludeLoc());
    Entry.IsTopLevel = IncludeFileID.isInvalid() || IncludeFileID.ID < 0 ||
                       !IsSLocFileEntryAffecting[IncludeFileID.ID];
    Entry.IsModuleMap = isModuleMap(File.getFileCharacteristic());

    Entry.trySetContentHash(*PP, [&] { return Cache->getBufferIfLoaded(); });

    if (Entry.IsSystemFile)
      SystemFiles.push_back(Entry);
    else
      UserFiles.push_back(Entry);
  }

  // FIXME: Make providing input files not in the SourceManager more flexible.
  // The SDKSettings.json file is necessary for correct evaluation of
  // availability annotations.
  StringRef Sysroot = PP->getHeaderSearchInfo().getHeaderSearchOpts().Sysroot;
  if (!Sysroot.empty()) {
    SmallString<128> SDKSettingsJSON = Sysroot;
    llvm::sys::path::append(SDKSettingsJSON, "SDKSettings.json");
    FileManager &FM = PP->getFileManager();
    if (auto FE = FM.getOptionalFileRef(SDKSettingsJSON)) {
      InputFileEntry Entry(*FE);
      Entry.IsSystemFile = true;
      Entry.IsTransient = false;
      Entry.BufferOverridden = false;
      Entry.IsTopLevel = true;
      Entry.IsModuleMap = false;
      std::unique_ptr<MemoryBuffer> MB;
      Entry.trySetContentHash(*PP, [&]() -> std::optional<MemoryBufferRef> {
        if (auto MBOrErr = FM.getBufferForFile(Entry.File)) {
          MB = std::move(*MBOrErr);
          return MB->getMemBufferRef();
        }
        return std::nullopt;
      });
      SystemFiles.push_back(Entry);
    }
  }

  // User files go at the front, system files at the back.
  auto SortedFiles = llvm::concat<InputFileEntry>(std::move(UserFiles),
                                                  std::move(SystemFiles));

  unsigned UserFilesNum = 0;
  // Write out all of the input files.
  std::vector<uint64_t> InputFileOffsets;
  for (const auto &Entry : SortedFiles) {
    uint32_t &InputFileID = InputFileIDs[Entry.File];
    if (InputFileID != 0)
      continue; // already recorded this file.

    // Record this entry's offset.
    InputFileOffsets.push_back(Stream.GetCurrentBitNo() - InputFilesOffsetBase);

    InputFileID = InputFileOffsets.size();

    if (!Entry.IsSystemFile)
      ++UserFilesNum;

    // Emit size/modification time for this file.
    // And whether this file was overridden.
    {
      SmallString<128> NameAsRequested = Entry.File.getNameAsRequested();
      SmallString<128> Name = Entry.File.getName();

      PreparePathForOutput(NameAsRequested);
      PreparePathForOutput(Name);

      if (Name == NameAsRequested)
        Name.clear();

      RecordData::value_type Record[] = {
          INPUT_FILE,
          InputFileOffsets.size(),
          (uint64_t)Entry.File.getSize(),
          (uint64_t)getTimestampForOutput(Entry.File.getModificationTime()),
          Entry.BufferOverridden,
          Entry.IsTransient,
          Entry.IsTopLevel,
          Entry.IsModuleMap,
          NameAsRequested.size()};

      Stream.EmitRecordWithBlob(IFAbbrevCode, Record,
                                (NameAsRequested + Name).str());
    }

    // Emit content hash for this file.
    {
      RecordData::value_type Record[] = {INPUT_FILE_HASH, Entry.ContentHash[0],
                                         Entry.ContentHash[1]};
      Stream.EmitRecordWithAbbrev(IFHAbbrevCode, Record);
    }
  }

  Stream.ExitBlock();

  // Create input file offsets abbreviation.
  auto OffsetsAbbrev = std::make_shared<BitCodeAbbrev>();
  OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS));
  OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files
  OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system
                                                                //   input files
  OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // Array
  unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(std::move(OffsetsAbbrev));

  // Write input file offsets.
  RecordData::value_type Record[] = {INPUT_FILE_OFFSETS,
                                     InputFileOffsets.size(), UserFilesNum};
  Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, bytes(InputFileOffsets));
}

//===----------------------------------------------------------------------===//
// Source Manager Serialization
//===----------------------------------------------------------------------===//

/// Create an abbreviation for the SLocEntry that refers to a
/// file.
static unsigned CreateSLocFileAbbrev(llvm::BitstreamWriter &Stream) {
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_FILE_ENTRY));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
  // FileEntry fields.
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Input File ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumCreatedFIDs
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 24)); // FirstDeclIndex
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // NumDecls
  return Stream.EmitAbbrev(std::move(Abbrev));
}

/// Create an abbreviation for the SLocEntry that refers to a
/// buffer.
static unsigned CreateSLocBufferAbbrev(llvm::BitstreamWriter &Stream) {
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_BUFFER_ENTRY));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Include location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Characteristic
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Line directives
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Buffer name blob
  return Stream.EmitAbbrev(std::move(Abbrev));
}

/// Create an abbreviation for the SLocEntry that refers to a
/// buffer's blob.
static unsigned CreateSLocBufferBlobAbbrev(llvm::BitstreamWriter &Stream,
                                           bool Compressed) {
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(Compressed ? SM_SLOC_BUFFER_BLOB_COMPRESSED
                                         : SM_SLOC_BUFFER_BLOB));
  if (Compressed)
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Uncompressed size
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Blob
  return Stream.EmitAbbrev(std::move(Abbrev));
}

/// Create an abbreviation for the SLocEntry that refers to a macro
/// expansion.
static unsigned CreateSLocExpansionAbbrev(llvm::BitstreamWriter &Stream) {
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SM_SLOC_EXPANSION_ENTRY));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Offset
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Spelling location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Start location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // End location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is token range
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Token length
  return Stream.EmitAbbrev(std::move(Abbrev));
}

/// Emit key length and data length as ULEB-encoded data, and return them as a
/// pair.
static std::pair<unsigned, unsigned>
emitULEBKeyDataLength(unsigned KeyLen, unsigned DataLen, raw_ostream &Out) {
  llvm::encodeULEB128(KeyLen, Out);
  llvm::encodeULEB128(DataLen, Out);
  return std::make_pair(KeyLen, DataLen);
}

namespace {

  // Trait used for the on-disk hash table of header search information.
  class HeaderFileInfoTrait {
    ASTWriter &Writer;

  public:
    HeaderFileInfoTrait(ASTWriter &Writer) : Writer(Writer) {}

    struct key_type {
      StringRef Filename;
      off_t Size;
      time_t ModTime;
    };
    using key_type_ref = const key_type &;

    using UnresolvedModule =
        llvm::PointerIntPair<Module *, 2, ModuleMap::ModuleHeaderRole>;

    struct data_type {
      data_type(const HeaderFileInfo &HFI, bool AlreadyIncluded,
                ArrayRef<ModuleMap::KnownHeader> KnownHeaders,
                UnresolvedModule Unresolved)
          : HFI(HFI), AlreadyIncluded(AlreadyIncluded),
            KnownHeaders(KnownHeaders), Unresolved(Unresolved) {}

      HeaderFileInfo HFI;
      bool AlreadyIncluded;
      SmallVector<ModuleMap::KnownHeader, 1> KnownHeaders;
      UnresolvedModule Unresolved;
    };
    using data_type_ref = const data_type &;

    using hash_value_type = unsigned;
    using offset_type = unsigned;

    hash_value_type ComputeHash(key_type_ref key) {
      // The hash is based only on size/time of the file, so that the reader can
      // match even when symlinking or excess path elements ("foo/../", "../")
      // change the form of the name. However, complete path is still the key.
      uint8_t buf[sizeof(key.Size) + sizeof(key.ModTime)];
      memcpy(buf, &key.Size, sizeof(key.Size));
      memcpy(buf + sizeof(key.Size), &key.ModTime, sizeof(key.ModTime));
      return llvm::xxh3_64bits(buf);
    }

    std::pair<unsigned, unsigned>
    EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
      unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
      unsigned DataLen = 1 + sizeof(IdentifierID);
      for (auto ModInfo : Data.KnownHeaders)
        if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
          DataLen += 4;
      if (Data.Unresolved.getPointer())
        DataLen += 4;
      return emitULEBKeyDataLength(KeyLen, DataLen, Out);
    }

    void EmitKey(raw_ostream& Out, key_type_ref key, unsigned KeyLen) {
      using namespace llvm::support;

      endian::Writer LE(Out, llvm::endianness::little);
      LE.write<uint64_t>(key.Size);
      KeyLen -= 8;
      LE.write<uint64_t>(key.ModTime);
      KeyLen -= 8;
      Out.write(key.Filename.data(), KeyLen);
    }

    void EmitData(raw_ostream &Out, key_type_ref key,
                  data_type_ref Data, unsigned DataLen) {
      using namespace llvm::support;

      endian::Writer LE(Out, llvm::endianness::little);
      uint64_t Start = Out.tell(); (void)Start;

      unsigned char Flags = (Data.AlreadyIncluded << 6)
                          | (Data.HFI.isImport << 5)
                          | (Writer.isWritingStdCXXNamedModules() ? 0 :
                             Data.HFI.isPragmaOnce << 4)
                          | (Data.HFI.DirInfo << 1);
      LE.write<uint8_t>(Flags);

      if (Data.HFI.LazyControllingMacro.isID())
        LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID());
      else
        LE.write<IdentifierID>(
            Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr()));

      auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {
        if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {
          uint32_t Value = (ModID << 3) | (unsigned)Role;
          assert((Value >> 3) == ModID && "overflow in header module info");
          LE.write<uint32_t>(Value);
        }
      };

      for (auto ModInfo : Data.KnownHeaders)
        EmitModule(ModInfo.getModule(), ModInfo.getRole());
      if (Data.Unresolved.getPointer())
        EmitModule(Data.Unresolved.getPointer(), Data.Unresolved.getInt());

      assert(Out.tell() - Start == DataLen && "Wrong data length");
    }
  };

} // namespace

/// Write the header search block for the list of files that
///
/// \param HS The header search structure to save.
void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
  HeaderFileInfoTrait GeneratorTrait(*this);
  llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;
  SmallVector<const char *, 4> SavedStrings;
  unsigned NumHeaderSearchEntries = 0;

  // Find all unresolved headers for the current module. We generally will
  // have resolved them before we get here, but not necessarily: we might be
  // compiling a preprocessed module, where there is no requirement for the
  // original files to exist any more.
  const HeaderFileInfo Empty; // So we can take a reference.
  if (WritingModule) {
    llvm::SmallVector<Module *, 16> Worklist(1, WritingModule);
    while (!Worklist.empty()) {
      Module *M = Worklist.pop_back_val();
      // We don't care about headers in unimportable submodules.
      if (M->isUnimportable())
        continue;

      // Map to disk files where possible, to pick up any missing stat
      // information. This also means we don't need to check the unresolved
      // headers list when emitting resolved headers in the first loop below.
      // FIXME: It'd be preferable to avoid doing this if we were given
      // sufficient stat information in the module map.
      HS.getModuleMap().resolveHeaderDirectives(M, /*File=*/std::nullopt);

      // If the file didn't exist, we can still create a module if we were given
      // enough information in the module map.
      for (const auto &U : M->MissingHeaders) {
        // Check that we were given enough information to build a module
        // without this file existing on disk.
        if (!U.Size || (!U.ModTime && IncludeTimestamps)) {
          PP->Diag(U.FileNameLoc, diag::err_module_no_size_mtime_for_header)
              << WritingModule->getFullModuleName() << U.Size.has_value()
              << U.FileName;
          continue;
        }

        // Form the effective relative pathname for the file.
        SmallString<128> Filename(M->Directory->getName());
        llvm::sys::path::append(Filename, U.FileName);
        PreparePathForOutput(Filename);

        StringRef FilenameDup = strdup(Filename.c_str());
        SavedStrings.push_back(FilenameDup.data());

        HeaderFileInfoTrait::key_type Key = {
            FilenameDup, *U.Size, IncludeTimestamps ? *U.ModTime : 0};
        HeaderFileInfoTrait::data_type Data = {
            Empty, false, {}, {M, ModuleMap::headerKindToRole(U.Kind)}};
        // FIXME: Deal with cases where there are multiple unresolved header
        // directives in different submodules for the same header.
        Generator.insert(Key, Data, GeneratorTrait);
        ++NumHeaderSearchEntries;
      }
      auto SubmodulesRange = M->submodules();
      Worklist.append(SubmodulesRange.begin(), SubmodulesRange.end());
    }
  }

  HS.forEachExistingLocalFileInfo(
      [&](FileEntryRef File, const HeaderFileInfo &HFI) {
        if (!HFI.isCompilingModuleHeader && HFI.isModuleHeader)
          return; // Header file info is tracked by the owning module file.
        if (!HFI.isCompilingModuleHeader && !HFI.IsLocallyIncluded)
          return; // Header file info is tracked by the including module file.

        // Massage the file path into an appropriate form.
        StringRef Filename = File.getName();
        SmallString<128> FilenameTmp(Filename);
        if (PreparePathForOutput(FilenameTmp)) {
          // If we performed any translation on the file name at all, we need to
          // save this string, since the generator will refer to it later.
          Filename = StringRef(strdup(FilenameTmp.c_str()));
          SavedStrings.push_back(Filename.data());
        }

        bool Included = HFI.IsLocallyIncluded || PP->alreadyIncluded(File);

        HeaderFileInfoTrait::key_type Key = {
            Filename, File.getSize(),
            getTimestampForOutput(File.getModificationTime())};
        HeaderFileInfoTrait::data_type Data = {
            HFI,
            Included,
            HS.getModuleMap().findResolvedModulesForHeader(File),
            {}};
        Generator.insert(Key, Data, GeneratorTrait);
        ++NumHeaderSearchEntries;
      });

  // Create the on-disk hash table in a buffer.
  SmallString<4096> TableData;
  uint32_t BucketOffset;
  {
    using namespace llvm::support;

    llvm::raw_svector_ostream Out(TableData);
    // Make sure that no bucket is at offset 0
    endian::write<uint32_t>(Out, 0, llvm::endianness::little);
    BucketOffset = Generator.Emit(Out, GeneratorTrait);
  }

  // Create a blob abbreviation
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(HEADER_SEARCH_TABLE));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  unsigned TableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  // Write the header search table
  RecordData::value_type Record[] = {HEADER_SEARCH_TABLE, BucketOffset,
                                     NumHeaderSearchEntries, TableData.size()};
  Stream.EmitRecordWithBlob(TableAbbrev, Record, TableData);

  // Free all of the strings we had to duplicate.
  for (unsigned I = 0, N = SavedStrings.size(); I != N; ++I)
    free(const_cast<char *>(SavedStrings[I]));
}

static void emitBlob(llvm::BitstreamWriter &Stream, StringRef Blob,
                     unsigned SLocBufferBlobCompressedAbbrv,
                     unsigned SLocBufferBlobAbbrv) {
  using RecordDataType = ASTWriter::RecordData::value_type;

  // Compress the buffer if possible. We expect that almost all PCM
  // consumers will not want its contents.
  SmallVector<uint8_t, 0> CompressedBuffer;
  if (llvm::compression::zstd::isAvailable()) {
    llvm::compression::zstd::compress(
        llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer, 9);
    RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};
    Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,
                              llvm::toStringRef(CompressedBuffer));
    return;
  }
  if (llvm::compression::zlib::isAvailable()) {
    llvm::compression::zlib::compress(
        llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer);
    RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};
    Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,
                              llvm::toStringRef(CompressedBuffer));
    return;
  }

  RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB};
  Stream.EmitRecordWithBlob(SLocBufferBlobAbbrv, Record, Blob);
}

/// Writes the block containing the serialized form of the
/// source manager.
///
/// TODO: We should probably use an on-disk hash table (stored in a
/// blob), indexed based on the file name, so that we only create
/// entries for files that we actually need. In the common case (no
/// errors), we probably won't have to create file entries for any of
/// the files in the AST.
void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) {
  RecordData Record;

  // Enter the source manager block.
  Stream.EnterSubblock(SOURCE_MANAGER_BLOCK_ID, 4);
  const uint64_t SourceManagerBlockOffset = Stream.GetCurrentBitNo();

  // Abbreviations for the various kinds of source-location entries.
  unsigned SLocFileAbbrv = CreateSLocFileAbbrev(Stream);
  unsigned SLocBufferAbbrv = CreateSLocBufferAbbrev(Stream);
  unsigned SLocBufferBlobAbbrv = CreateSLocBufferBlobAbbrev(Stream, false);
  unsigned SLocBufferBlobCompressedAbbrv =
      CreateSLocBufferBlobAbbrev(Stream, true);
  unsigned SLocExpansionAbbrv = CreateSLocExpansionAbbrev(Stream);

  // Write out the source location entry table. We skip the first
  // entry, which is always the same dummy entry.
  std::vector<uint32_t> SLocEntryOffsets;
  uint64_t SLocEntryOffsetsBase = Stream.GetCurrentBitNo();
  SLocEntryOffsets.reserve(SourceMgr.local_sloc_entry_size() - 1);
  for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size();
       I != N; ++I) {
    // Get this source location entry.
    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I);
    FileID FID = FileID::get(I);
    assert(&SourceMgr.getSLocEntry(FID) == SLoc);

    // Record the offset of this source-location entry.
    uint64_t Offset = Stream.GetCurrentBitNo() - SLocEntryOffsetsBase;
    assert((Offset >> 32) == 0 && "SLocEntry offset too large");

    // Figure out which record code to use.
    unsigned Code;
    if (SLoc->isFile()) {
      const SrcMgr::ContentCache *Cache = &SLoc->getFile().getContentCache();
      if (Cache->OrigEntry) {
        Code = SM_SLOC_FILE_ENTRY;
      } else
        Code = SM_SLOC_BUFFER_ENTRY;
    } else
      Code = SM_SLOC_EXPANSION_ENTRY;
    Record.clear();
    Record.push_back(Code);

    if (SLoc->isFile()) {
      const SrcMgr::FileInfo &File = SLoc->getFile();
      const SrcMgr::ContentCache *Content = &File.getContentCache();
      // Do not emit files that were not listed as inputs.
      if (!IsSLocAffecting[I])
        continue;
      SLocEntryOffsets.push_back(Offset);
      // Starting offset of this entry within this module, so skip the dummy.
      Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);
      AddSourceLocation(getAffectingIncludeLoc(SourceMgr, File), Record);
      Record.push_back(File.getFileCharacteristic()); // FIXME: stable encoding
      Record.push_back(File.hasLineDirectives());

      bool EmitBlob = false;
      if (Content->OrigEntry) {
        assert(Content->OrigEntry == Content->ContentsEntry &&
               "Writing to AST an overridden file is not supported");

        // The source location entry is a file. Emit input file ID.
        assert(InputFileIDs[*Content->OrigEntry] != 0 && "Missed file entry");
        Record.push_back(InputFileIDs[*Content->OrigEntry]);

        Record.push_back(getAdjustedNumCreatedFIDs(FID));

        FileDeclIDsTy::iterator FDI = FileDeclIDs.find(FID);
        if (FDI != FileDeclIDs.end()) {
          Record.push_back(FDI->second->FirstDeclIndex);
          Record.push_back(FDI->second->DeclIDs.size());
        } else {
          Record.push_back(0);
          Record.push_back(0);
        }

        Stream.EmitRecordWithAbbrev(SLocFileAbbrv, Record);

        if (Content->BufferOverridden || Content->IsTransient)
          EmitBlob = true;
      } else {
        // The source location entry is a buffer. The blob associated
        // with this entry contains the contents of the buffer.

        // We add one to the size so that we capture the trailing NULL
        // that is required by llvm::MemoryBuffer::getMemBuffer (on
        // the reader side).
        std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(
            SourceMgr.getDiagnostics(), SourceMgr.getFileManager());
        StringRef Name = Buffer ? Buffer->getBufferIdentifier() : "";
        Stream.EmitRecordWithBlob(SLocBufferAbbrv, Record,
                                  StringRef(Name.data(), Name.size() + 1));
        EmitBlob = true;
      }

      if (EmitBlob) {
        // Include the implicit terminating null character in the on-disk buffer
        // if we're writing it uncompressed.
        std::optional<llvm::MemoryBufferRef> Buffer = Content->getBufferOrNone(
            SourceMgr.getDiagnostics(), SourceMgr.getFileManager());
        if (!Buffer)
          Buffer = llvm::MemoryBufferRef("<<<INVALID BUFFER>>>", "");
        StringRef Blob(Buffer->getBufferStart(), Buffer->getBufferSize() + 1);
        emitBlob(Stream, Blob, SLocBufferBlobCompressedAbbrv,
                 SLocBufferBlobAbbrv);
      }
    } else {
      // The source location entry is a macro expansion.
      const SrcMgr::ExpansionInfo &Expansion = SLoc->getExpansion();
      SLocEntryOffsets.push_back(Offset);
      // Starting offset of this entry within this module, so skip the dummy.
      Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2);
      AddSourceLocation(Expansion.getSpellingLoc(), Record);
      AddSourceLocation(Expansion.getExpansionLocStart(), Record);
      AddSourceLocation(Expansion.isMacroArgExpansion()
                            ? SourceLocation()
                            : Expansion.getExpansionLocEnd(),
                        Record);
      Record.push_back(Expansion.isExpansionTokenRange());

      // Compute the token length for this macro expansion.
      SourceLocation::UIntTy NextOffset = SourceMgr.getNextLocalOffset();
      if (I + 1 != N)
        NextOffset = SourceMgr.getLocalSLocEntry(I + 1).getOffset();
      Record.push_back(getAdjustedOffset(NextOffset - SLoc->getOffset()) - 1);
      Stream.EmitRecordWithAbbrev(SLocExpansionAbbrv, Record);
    }
  }

  Stream.ExitBlock();

  if (SLocEntryOffsets.empty())
    return;

  // Write the source-location offsets table into the AST block. This
  // table is used for lazily loading source-location information.
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SOURCE_LOCATION_OFFSETS));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // # of slocs
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 16)); // total size
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32)); // base offset
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // offsets
  unsigned SLocOffsetsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
  {
    RecordData::value_type Record[] = {
        SOURCE_LOCATION_OFFSETS, SLocEntryOffsets.size(),
        getAdjustedOffset(SourceMgr.getNextLocalOffset()) - 1 /* skip dummy */,
        SLocEntryOffsetsBase - SourceManagerBlockOffset};
    Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record,
                              bytes(SLocEntryOffsets));
  }

  // Write the line table. It depends on remapping working, so it must come
  // after the source location offsets.
  if (SourceMgr.hasLineTable()) {
    LineTableInfo &LineTable = SourceMgr.getLineTable();

    Record.clear();

    // Emit the needed file names.
    llvm::DenseMap<int, int> FilenameMap;
    FilenameMap[-1] = -1; // For unspecified filenames.
    for (const auto &L : LineTable) {
      if (L.first.ID < 0)
        continue;
      for (auto &LE : L.second) {
        if (FilenameMap.insert(std::make_pair(LE.FilenameID,
                                              FilenameMap.size() - 1)).second)
          AddPath(LineTable.getFilename(LE.FilenameID), Record);
      }
    }
    Record.push_back(0);

    // Emit the line entries
    for (const auto &L : LineTable) {
      // Only emit entries for local files.
      if (L.first.ID < 0)
        continue;

      AddFileID(L.first, Record);

      // Emit the line entries
      Record.push_back(L.second.size());
      for (const auto &LE : L.second) {
        Record.push_back(LE.FileOffset);
        Record.push_back(LE.LineNo);
        Record.push_back(FilenameMap[LE.FilenameID]);
        Record.push_back((unsigned)LE.FileKind);
        Record.push_back(LE.IncludeOffset);
      }
    }

    Stream.EmitRecord(SOURCE_MANAGER_LINE_TABLE, Record);
  }
}

//===----------------------------------------------------------------------===//
// Preprocessor Serialization
//===----------------------------------------------------------------------===//

static bool shouldIgnoreMacro(MacroDirective *MD, bool IsModule,
                              const Preprocessor &PP) {
  if (MacroInfo *MI = MD->getMacroInfo())
    if (MI->isBuiltinMacro())
      return true;

  if (IsModule) {
    SourceLocation Loc = MD->getLocation();
    if (Loc.isInvalid())
      return true;
    if (PP.getSourceManager().getFileID(Loc) == PP.getPredefinesFileID())
      return true;
  }

  return false;
}

/// Writes the block containing the serialized form of the
/// preprocessor.
void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
  uint64_t MacroOffsetsBase = Stream.GetCurrentBitNo();

  PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
  if (PPRec)
    WritePreprocessorDetail(*PPRec, MacroOffsetsBase);

  RecordData Record;
  RecordData ModuleMacroRecord;

  // If the preprocessor __COUNTER__ value has been bumped, remember it.
  if (PP.getCounterValue() != 0) {
    RecordData::value_type Record[] = {PP.getCounterValue()};
    Stream.EmitRecord(PP_COUNTER_VALUE, Record);
  }

  // If we have a recorded #pragma assume_nonnull, remember it so it can be
  // replayed when the preamble terminates into the main file.
  SourceLocation AssumeNonNullLoc =
      PP.getPreambleRecordedPragmaAssumeNonNullLoc();
  if (AssumeNonNullLoc.isValid()) {
    assert(PP.isRecordingPreamble());
    AddSourceLocation(AssumeNonNullLoc, Record);
    Stream.EmitRecord(PP_ASSUME_NONNULL_LOC, Record);
    Record.clear();
  }

  if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
    assert(!IsModule);
    auto SkipInfo = PP.getPreambleSkipInfo();
    if (SkipInfo) {
      Record.push_back(true);
      AddSourceLocation(SkipInfo->HashTokenLoc, Record);
      AddSourceLocation(SkipInfo->IfTokenLoc, Record);
      Record.push_back(SkipInfo->FoundNonSkipPortion);
      Record.push_back(SkipInfo->FoundElse);
      AddSourceLocation(SkipInfo->ElseLoc, Record);
    } else {
      Record.push_back(false);
    }
    for (const auto &Cond : PP.getPreambleConditionalStack()) {
      AddSourceLocation(Cond.IfLoc, Record);
      Record.push_back(Cond.WasSkipping);
      Record.push_back(Cond.FoundNonSkip);
      Record.push_back(Cond.FoundElse);
    }
    Stream.EmitRecord(PP_CONDITIONAL_STACK, Record);
    Record.clear();
  }

  // Write the safe buffer opt-out region map in PP
  for (SourceLocation &S : PP.serializeSafeBufferOptOutMap())
    AddSourceLocation(S, Record);
  Stream.EmitRecord(PP_UNSAFE_BUFFER_USAGE, Record);
  Record.clear();

  // Enter the preprocessor block.
  Stream.EnterSubblock(PREPROCESSOR_BLOCK_ID, 3);

  // If the AST file contains __DATE__ or __TIME__ emit a warning about this.
  // FIXME: Include a location for the use, and say which one was used.
  if (PP.SawDateOrTime())
    PP.Diag(SourceLocation(), diag::warn_module_uses_date_time) << IsModule;

  // Loop over all the macro directives that are live at the end of the file,
  // emitting each to the PP section.

  // Construct the list of identifiers with macro directives that need to be
  // serialized.
  SmallVector<const IdentifierInfo *, 128> MacroIdentifiers;
  // It is meaningless to emit macros for named modules. It only wastes times
  // and spaces.
  if (!isWritingStdCXXNamedModules())
    for (auto &Id : PP.getIdentifierTable())
      if (Id.second->hadMacroDefinition() &&
          (!Id.second->isFromAST() ||
          Id.second->hasChangedSinceDeserialization()))
        MacroIdentifiers.push_back(Id.second);
  // Sort the set of macro definitions that need to be serialized by the
  // name of the macro, to provide a stable ordering.
  llvm::sort(MacroIdentifiers, llvm::deref<std::less<>>());

  // Emit the macro directives as a list and associate the offset with the
  // identifier they belong to.
  for (const IdentifierInfo *Name : MacroIdentifiers) {
    MacroDirective *MD = PP.getLocalMacroDirectiveHistory(Name);
    uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
    assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");

    // Write out any exported module macros.
    bool EmittedModuleMacros = false;
    // C+=20 Header Units are compiled module interfaces, but they preserve
    // macros that are live (i.e. have a defined value) at the end of the
    // compilation.  So when writing a header unit, we preserve only the final
    // value of each macro (and discard any that are undefined).  Header units
    // do not have sub-modules (although they might import other header units).
    // PCH files, conversely, retain the history of each macro's define/undef
    // and of leaf macros in sub modules.
    if (IsModule && WritingModule->isHeaderUnit()) {
      // This is for the main TU when it is a C++20 header unit.
      // We preserve the final state of defined macros, and we do not emit ones
      // that are undefined.
      if (!MD || shouldIgnoreMacro(MD, IsModule, PP) ||
          MD->getKind() == MacroDirective::MD_Undefine)
        continue;
      AddSourceLocation(MD->getLocation(), Record);
      Record.push_back(MD->getKind());
      if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
        Record.push_back(getMacroRef(DefMD->getInfo(), Name));
      } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
        Record.push_back(VisMD->isPublic());
      }
      ModuleMacroRecord.push_back(getSubmoduleID(WritingModule));
      AddMacroRef(MD->getMacroInfo(), Name, ModuleMacroRecord);
      Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);
      ModuleMacroRecord.clear();
      EmittedModuleMacros = true;
    } else {
      // Emit the macro directives in reverse source order.
      for (; MD; MD = MD->getPrevious()) {
        // Once we hit an ignored macro, we're done: the rest of the chain
        // will all be ignored macros.
        if (shouldIgnoreMacro(MD, IsModule, PP))
          break;
        AddSourceLocation(MD->getLocation(), Record);
        Record.push_back(MD->getKind());
        if (auto *DefMD = dyn_cast<DefMacroDirective>(MD)) {
          Record.push_back(getMacroRef(DefMD->getInfo(), Name));
        } else if (auto *VisMD = dyn_cast<VisibilityMacroDirective>(MD)) {
          Record.push_back(VisMD->isPublic());
        }
      }

      // We write out exported module macros for PCH as well.
      auto Leafs = PP.getLeafModuleMacros(Name);
      SmallVector<ModuleMacro *, 8> Worklist(Leafs);
      llvm::DenseMap<ModuleMacro *, unsigned> Visits;
      while (!Worklist.empty()) {
        auto *Macro = Worklist.pop_back_val();

        // Emit a record indicating this submodule exports this macro.
        ModuleMacroRecord.push_back(getSubmoduleID(Macro->getOwningModule()));
        AddMacroRef(Macro->getMacroInfo(), Name, ModuleMacroRecord);
        for (auto *M : Macro->overrides())
          ModuleMacroRecord.push_back(getSubmoduleID(M->getOwningModule()));

        Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);
        ModuleMacroRecord.clear();

        // Enqueue overridden macros once we've visited all their ancestors.
        for (auto *M : Macro->overrides())
          if (++Visits[M] == M->getNumOverridingMacros())
            Worklist.push_back(M);

        EmittedModuleMacros = true;
      }
    }
    if (Record.empty() && !EmittedModuleMacros)
      continue;

    IdentMacroDirectivesOffsetMap[Name] = StartOffset;
    Stream.EmitRecord(PP_MACRO_DIRECTIVE_HISTORY, Record);
    Record.clear();
  }

  /// Offsets of each of the macros into the bitstream, indexed by
  /// the local macro ID
  ///
  /// For each identifier that is associated with a macro, this map
  /// provides the offset into the bitstream where that macro is
  /// defined.
  std::vector<uint32_t> MacroOffsets;

  for (unsigned I = 0, N = MacroInfosToEmit.size(); I != N; ++I) {
    const IdentifierInfo *Name = MacroInfosToEmit[I].Name;
    MacroInfo *MI = MacroInfosToEmit[I].MI;
    MacroID ID = MacroInfosToEmit[I].ID;

    if (ID < FirstMacroID) {
      assert(0 && "Loaded MacroInfo entered MacroInfosToEmit ?");
      continue;
    }

    // Record the local offset of this macro.
    unsigned Index = ID - FirstMacroID;
    if (Index >= MacroOffsets.size())
      MacroOffsets.resize(Index + 1);

    uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
    assert((Offset >> 32) == 0 && "Macro offset too large");
    MacroOffsets[Index] = Offset;

    AddIdentifierRef(Name, Record);
    AddSourceLocation(MI->getDefinitionLoc(), Record);
    AddSourceLocation(MI->getDefinitionEndLoc(), Record);
    Record.push_back(MI->isUsed());
    Record.push_back(MI->isUsedForHeaderGuard());
    Record.push_back(MI->getNumTokens());
    unsigned Code;
    if (MI->isObjectLike()) {
      Code = PP_MACRO_OBJECT_LIKE;
    } else {
      Code = PP_MACRO_FUNCTION_LIKE;

      Record.push_back(MI->isC99Varargs());
      Record.push_back(MI->isGNUVarargs());
      Record.push_back(MI->hasCommaPasting());
      Record.push_back(MI->getNumParams());
      for (const IdentifierInfo *Param : MI->params())
        AddIdentifierRef(Param, Record);
    }

    // If we have a detailed preprocessing record, record the macro definition
    // ID that corresponds to this macro.
    if (PPRec)
      Record.push_back(MacroDefinitions[PPRec->findMacroDefinition(MI)]);

    Stream.EmitRecord(Code, Record);
    Record.clear();

    // Emit the tokens array.
    for (unsigned TokNo = 0, e = MI->getNumTokens(); TokNo != e; ++TokNo) {
      // Note that we know that the preprocessor does not have any annotation
      // tokens in it because they are created by the parser, and thus can't
      // be in a macro definition.
      const Token &Tok = MI->getReplacementToken(TokNo);
      AddToken(Tok, Record);
      Stream.EmitRecord(PP_TOKEN, Record);
      Record.clear();
    }
    ++NumMacros;
  }

  Stream.ExitBlock();

  // Write the offsets table for macro IDs.
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(MACRO_OFFSET));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of macros
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 32));   // base offset
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));

  unsigned MacroOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
  {
    RecordData::value_type Record[] = {MACRO_OFFSET, MacroOffsets.size(),
                                       MacroOffsetsBase - ASTBlockStartOffset};
    Stream.EmitRecordWithBlob(MacroOffsetAbbrev, Record, bytes(MacroOffsets));
  }
}

void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec,
                                        uint64_t MacroOffsetsBase) {
  if (PPRec.local_begin() == PPRec.local_end())
    return;

  SmallVector<PPEntityOffset, 64> PreprocessedEntityOffsets;

  // Enter the preprocessor block.
  Stream.EnterSubblock(PREPROCESSOR_DETAIL_BLOCK_ID, 3);

  // If the preprocessor has a preprocessing record, emit it.
  unsigned NumPreprocessingRecords = 0;
  using namespace llvm;

  // Set up the abbreviation for
  unsigned InclusionAbbrev = 0;
  {
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(PPD_INCLUSION_DIRECTIVE));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // filename length
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // in quotes
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // kind
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // imported module
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    InclusionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
  }

  unsigned FirstPreprocessorEntityID = NUM_PREDEF_PP_ENTITY_IDS;
  unsigned NextPreprocessorEntityID = FirstPreprocessorEntityID;
  RecordData Record;
  for (PreprocessingRecord::iterator E = PPRec.local_begin(),
                                  EEnd = PPRec.local_end();
       E != EEnd;
       (void)++E, ++NumPreprocessingRecords, ++NextPreprocessorEntityID) {
    Record.clear();

    uint64_t Offset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
    assert((Offset >> 32) == 0 && "Preprocessed entity offset too large");
    SourceRange R = getAdjustedRange((*E)->getSourceRange());
    PreprocessedEntityOffsets.emplace_back(
        getRawSourceLocationEncoding(R.getBegin()),
        getRawSourceLocationEncoding(R.getEnd()), Offset);

    if (auto *MD = dyn_cast<MacroDefinitionRecord>(*E)) {
      // Record this macro definition's ID.
      MacroDefinitions[MD] = NextPreprocessorEntityID;

      AddIdentifierRef(MD->getName(), Record);
      Stream.EmitRecord(PPD_MACRO_DEFINITION, Record);
      continue;
    }

    if (auto *ME = dyn_cast<MacroExpansion>(*E)) {
      Record.push_back(ME->isBuiltinMacro());
      if (ME->isBuiltinMacro())
        AddIdentifierRef(ME->getName(), Record);
      else
        Record.push_back(MacroDefinitions[ME->getDefinition()]);
      Stream.EmitRecord(PPD_MACRO_EXPANSION, Record);
      continue;
    }

    if (auto *ID = dyn_cast<InclusionDirective>(*E)) {
      Record.push_back(PPD_INCLUSION_DIRECTIVE);
      Record.push_back(ID->getFileName().size());
      Record.push_back(ID->wasInQuotes());
      Record.push_back(static_cast<unsigned>(ID->getKind()));
      Record.push_back(ID->importedModule());
      SmallString<64> Buffer;
      Buffer += ID->getFileName();
      // Check that the FileEntry is not null because it was not resolved and
      // we create a PCH even with compiler errors.
      if (ID->getFile())
        Buffer += ID->getFile()->getName();
      Stream.EmitRecordWithBlob(InclusionAbbrev, Record, Buffer);
      continue;
    }

    llvm_unreachable("Unhandled PreprocessedEntity in ASTWriter");
  }
  Stream.ExitBlock();

  // Write the offsets table for the preprocessing record.
  if (NumPreprocessingRecords > 0) {
    assert(PreprocessedEntityOffsets.size() == NumPreprocessingRecords);

    // Write the offsets table for identifier IDs.
    using namespace llvm;

    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(PPD_ENTITIES_OFFSETS));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned PPEOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    RecordData::value_type Record[] = {PPD_ENTITIES_OFFSETS};
    Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
                              bytes(PreprocessedEntityOffsets));
  }

  // Write the skipped region table for the preprocessing record.
  ArrayRef<SourceRange> SkippedRanges = PPRec.getSkippedRanges();
  if (SkippedRanges.size() > 0) {
    std::vector<PPSkippedRange> SerializedSkippedRanges;
    SerializedSkippedRanges.reserve(SkippedRanges.size());
    for (auto const& Range : SkippedRanges)
      SerializedSkippedRanges.emplace_back(
          getRawSourceLocationEncoding(Range.getBegin()),
          getRawSourceLocationEncoding(Range.getEnd()));

    using namespace llvm;
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    Record.clear();
    Record.push_back(PPD_SKIPPED_RANGES);
    Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,
                              bytes(SerializedSkippedRanges));
  }
}

unsigned ASTWriter::getLocalOrImportedSubmoduleID(const Module *Mod) {
  if (!Mod)
    return 0;

  auto Known = SubmoduleIDs.find(Mod);
  if (Known != SubmoduleIDs.end())
    return Known->second;

  auto *Top = Mod->getTopLevelModule();
  if (Top != WritingModule &&
      (getLangOpts().CompilingPCH ||
       !Top->fullModuleNameIs(StringRef(getLangOpts().CurrentModule))))
    return 0;

  return SubmoduleIDs[Mod] = NextSubmoduleID++;
}

unsigned ASTWriter::getSubmoduleID(Module *Mod) {
  unsigned ID = getLocalOrImportedSubmoduleID(Mod);
  // FIXME: This can easily happen, if we have a reference to a submodule that
  // did not result in us loading a module file for that submodule. For
  // instance, a cross-top-level-module 'conflict' declaration will hit this.
  // assert((ID || !Mod) &&
  //        "asked for module ID for non-local, non-imported module");
  return ID;
}

void ASTWriter::WriteSubmodules(Module *WritingModule, ASTContext *Context) {
  // Enter the submodule description block.
  Stream.EnterSubblock(SUBMODULE_BLOCK_ID, /*bits for abbreviations*/5);

  // Write the abbreviations needed for the submodules block.
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Kind
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // Definition location
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Inferred allowed by
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExternC
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferSubmodules...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModuleMapIsPriv...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // NamedModuleHasN...
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned UmbrellaAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned HeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TOPHEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned TopHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_UMBRELLA_DIR));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned UmbrellaDirAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_REQUIRES));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // State
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));     // Feature
  unsigned RequiresAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_TEXTUAL_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned TextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned PrivateHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_PRIVATE_TEXTUAL_HEADER));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
  unsigned PrivateTextualHeaderAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_LINK_LIBRARY));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));     // Name
  unsigned LinkLibraryAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFIG_MACRO));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));    // Macro name
  unsigned ConfigMacroAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CONFLICT));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));  // Other module
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));    // Message
  unsigned ConflictAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXPORT_AS));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));    // Macro name
  unsigned ExportAsAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_CHILD));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Child submodule ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // Child name
  unsigned ChildAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  SmallVector<uint64_t> SubmoduleOffsets;
  uint64_t SubmoduleOffsetBase = Stream.GetCurrentBitNo();

  unsigned TopLevelID = getSubmoduleID(WritingModule);

  // Write all of the submodules.
  std::queue<Module *> Q;
  Q.push(WritingModule);
  while (!Q.empty()) {
    Module *Mod = Q.front();
    Q.pop();
    unsigned ID = getSubmoduleID(Mod);
    if (ID < FirstSubmoduleID) {
      assert(0 && "Loaded submodule entered WritingModule ?");
      continue;
    }

    // Record the local offset of this submodule.
    unsigned Index = ID - FirstSubmoduleID;
    if (Index >= SubmoduleOffsets.size())
      SubmoduleOffsets.resize(Index + 1);

    uint64_t Offset = Stream.GetCurrentBitNo() - SubmoduleOffsetBase;
    assert((Offset >> 32) == 0 && "Submodule offset too large");
    SubmoduleOffsets[Index] = Offset;

    uint64_t ParentID = 0;
    if (Mod->Parent) {
      assert(SubmoduleIDs[Mod->Parent] && "Submodule parent not written?");
      ParentID = SubmoduleIDs[Mod->Parent];
    }

    SourceLocationEncoding::RawLocEncoding DefinitionLoc =
        getRawSourceLocationEncoding(getAdjustedLocation(Mod->DefinitionLoc));

    ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
    FileID UnadjustedInferredFID;
    if (Mod->IsInferred)
      UnadjustedInferredFID = ModMap.getModuleMapFileIDForUniquing(Mod);
    int InferredFID = getAdjustedFileID(UnadjustedInferredFID).getOpaqueValue();

    // Emit the definition of the block.
    {
      RecordData::value_type Record[] = {SUBMODULE_DEFINITION,
                                         ID,
                                         ParentID,
                                         (RecordData::value_type)Mod->Kind,
                                         DefinitionLoc,
                                         (RecordData::value_type)InferredFID,
                                         Mod->IsFramework,
                                         Mod->IsExplicit,
                                         Mod->IsSystem,
                                         Mod->IsExternC,
                                         Mod->InferSubmodules,
                                         Mod->InferExplicitSubmodules,
                                         Mod->InferExportWildcard,
                                         Mod->ConfigMacrosExhaustive,
                                         Mod->ModuleMapIsPrivate,
                                         Mod->NamedModuleHasInit};
      Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
    }

    // Emit the requirements.
    for (const auto &R : Mod->Requirements) {
      RecordData::value_type Record[] = {SUBMODULE_REQUIRES, R.RequiredState};
      Stream.EmitRecordWithBlob(RequiresAbbrev, Record, R.FeatureName);
    }

    // Emit the umbrella header, if there is one.
    if (std::optional<Module::Header> UmbrellaHeader =
            Mod->getUmbrellaHeaderAsWritten()) {
      RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_HEADER};
      Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,
                                UmbrellaHeader->NameAsWritten);
    } else if (std::optional<Module::DirectoryName> UmbrellaDir =
                   Mod->getUmbrellaDirAsWritten()) {
      RecordData::value_type Record[] = {SUBMODULE_UMBRELLA_DIR};
      Stream.EmitRecordWithBlob(UmbrellaDirAbbrev, Record,
                                UmbrellaDir->NameAsWritten);
    }

    // Emit the headers.
    struct {
      unsigned RecordKind;
      unsigned Abbrev;
      Module::HeaderKind HeaderKind;
    } HeaderLists[] = {
      {SUBMODULE_HEADER, HeaderAbbrev, Module::HK_Normal},
      {SUBMODULE_TEXTUAL_HEADER, TextualHeaderAbbrev, Module::HK_Textual},
      {SUBMODULE_PRIVATE_HEADER, PrivateHeaderAbbrev, Module::HK_Private},
      {SUBMODULE_PRIVATE_TEXTUAL_HEADER, PrivateTextualHeaderAbbrev,
        Module::HK_PrivateTextual},
      {SUBMODULE_EXCLUDED_HEADER, ExcludedHeaderAbbrev, Module::HK_Excluded}
    };
    for (const auto &HL : HeaderLists) {
      RecordData::value_type Record[] = {HL.RecordKind};
      for (const auto &H : Mod->getHeaders(HL.HeaderKind))
        Stream.EmitRecordWithBlob(HL.Abbrev, Record, H.NameAsWritten);
    }

    // Emit the top headers.
    {
      RecordData::value_type Record[] = {SUBMODULE_TOPHEADER};
      for (FileEntryRef H : Mod->getTopHeaders(PP->getFileManager())) {
        SmallString<128> HeaderName(H.getName());
        PreparePathForOutput(HeaderName);
        Stream.EmitRecordWithBlob(TopHeaderAbbrev, Record, HeaderName);
      }
    }

    // Emit the imports.
    if (!Mod->Imports.empty()) {
      RecordData Record;
      for (Module *I : Mod->Imports)
        Record.push_back(getSubmoduleID(I));
      Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
    }

    // Emit the modules affecting compilation that were not imported.
    if (!Mod->AffectingClangModules.empty()) {
      RecordData Record;
      for (Module *I : Mod->AffectingClangModules)
        Record.push_back(getSubmoduleID(I));
      Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record);
    }

    // Emit the exports.
    if (!Mod->Exports.empty()) {
      RecordData Record;
      for (const auto &E : Mod->Exports) {
        // FIXME: This may fail; we don't require that all exported modules
        // are local or imported.
        Record.push_back(getSubmoduleID(E.first));
        Record.push_back(E.second);
      }
      Stream.EmitRecord(SUBMODULE_EXPORTS, Record);
    }

    //FIXME: How do we emit the 'use'd modules?  They may not be submodules.
    // Might be unnecessary as use declarations are only used to build the
    // module itself.

    // TODO: Consider serializing undeclared uses of modules.

    // Emit the link libraries.
    for (const auto &LL : Mod->LinkLibraries) {
      RecordData::value_type Record[] = {SUBMODULE_LINK_LIBRARY,
                                         LL.IsFramework};
      Stream.EmitRecordWithBlob(LinkLibraryAbbrev, Record, LL.Library);
    }

    // Emit the conflicts.
    for (const auto &C : Mod->Conflicts) {
      // FIXME: This may fail; we don't require that all conflicting modules
      // are local or imported.
      RecordData::value_type Record[] = {SUBMODULE_CONFLICT,
                                         getSubmoduleID(C.Other)};
      Stream.EmitRecordWithBlob(ConflictAbbrev, Record, C.Message);
    }

    // Emit the configuration macros.
    for (const auto &CM : Mod->ConfigMacros) {
      RecordData::value_type Record[] = {SUBMODULE_CONFIG_MACRO};
      Stream.EmitRecordWithBlob(ConfigMacroAbbrev, Record, CM);
    }

    // Emit the reachable initializers.
    // The initializer may only be unreachable in reduced BMI.
    if (Context && !GeneratingReducedBMI) {
      RecordData Inits;
      for (Decl *D : Context->getModuleInitializers(Mod))
        if (wasDeclEmitted(D))
          AddDeclRef(D, Inits);
      if (!Inits.empty())
        Stream.EmitRecord(SUBMODULE_INITIALIZERS, Inits);
    }

    // Emit the name of the re-exported module, if any.
    if (!Mod->ExportAsModule.empty()) {
      RecordData::value_type Record[] = {SUBMODULE_EXPORT_AS};
      Stream.EmitRecordWithBlob(ExportAsAbbrev, Record, Mod->ExportAsModule);
    }

    // Emit one SUBMODULE_CHILD record per direct child so the reader can
    // populate PendingSubmodules and demand-load children by name.
    for (Module *Child : Mod->submodules()) {
      RecordData::value_type Record[] = {SUBMODULE_CHILD,
                                         getSubmoduleID(Child)};
      Stream.EmitRecordWithBlob(ChildAbbrev, Record, Child->Name);
    }

    // Emit the sentinel signifying the end of this submodule.
    {
      RecordData Record;
      Stream.EmitRecord(SUBMODULE_END, Record);
    }

    // Queue up the submodules of this module.
    for (Module *M : Mod->submodules())
      Q.push(M);
  }

  Stream.ExitBlock();

  assert((NextSubmoduleID - FirstSubmoduleID == SubmoduleOffsets.size()) &&
         "Wrong # of submodules; found a reference to a non-local, "
         "non-imported submodule?");

  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_METADATA));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Submodule count
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Base submodule ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Top-level submod ID
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // Submodule offsets
  unsigned SubmoduleMetadataAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

  RecordData::value_type Record[] = {
      SUBMODULE_METADATA, SubmoduleOffsets.size(),
      FirstSubmoduleID - NUM_PREDEF_SUBMODULE_IDS, TopLevelID};
  Stream.EmitRecordWithBlob(SubmoduleMetadataAbbrev, Record,
                            bytes(SubmoduleOffsets));
}

void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
                                              bool isModule) {
  llvm::SmallDenseMap<const DiagnosticsEngine::DiagState *, unsigned, 64>
      DiagStateIDMap;
  unsigned CurrID = 0;
  RecordData Record;

  auto EncodeDiagStateFlags =
      [](const DiagnosticsEngine::DiagState *DS) -> unsigned {
    unsigned Result = (unsigned)DS->ExtBehavior;
    for (unsigned Val :
         {(unsigned)DS->IgnoreAllWarnings, (unsigned)DS->EnableAllWarnings,
          (unsigned)DS->WarningsAsErrors, (unsigned)DS->ErrorsAsFatal,
          (unsigned)DS->SuppressSystemWarnings})
      Result = (Result << 1) | Val;
    return Result;
  };

  unsigned Flags = EncodeDiagStateFlags(Diag.DiagStatesByLoc.FirstDiagState);
  Record.push_back(Flags);

  auto AddDiagState = [&](const DiagnosticsEngine::DiagState *State,
                          bool IncludeNonPragmaStates) {
    // Ensure that the diagnostic state wasn't modified since it was created.
    // We will not correctly round-trip this information otherwise.
    assert(Flags == EncodeDiagStateFlags(State) &&
           "diag state flags vary in single AST file");

    // If we ever serialize non-pragma mappings outside the initial state, the
    // code below will need to consider more than getDefaultMapping.
    assert(!IncludeNonPragmaStates ||
           State == Diag.DiagStatesByLoc.FirstDiagState);

    unsigned &DiagStateID = DiagStateIDMap[State];
    Record.push_back(DiagStateID);

    if (DiagStateID == 0) {
      DiagStateID = ++CurrID;
      SmallVector<std::pair<unsigned, DiagnosticMapping>> Mappings;

      // Add a placeholder for the number of mappings.
      auto SizeIdx = Record.size();
      Record.emplace_back();
      for (const auto &I : *State) {
        // Maybe skip non-pragmas.
        if (!I.second.isPragma() && !IncludeNonPragmaStates)
          continue;
        // Skip default mappings. We have a mapping for every diagnostic ever
        // emitted, regardless of whether it was customized.
        if (!I.second.isPragma() &&
            I.second == Diag.getDiagnosticIDs()->getDefaultMapping(I.first))
          continue;
        Mappings.push_back(I);
      }

      // Sort by diag::kind for deterministic output.
      llvm::sort(Mappings, llvm::less_first());

      for (const auto &I : Mappings) {
        Record.push_back(I.first);
        Record.push_back(I.second.serialize());
      }
      // Update the placeholder.
      Record[SizeIdx] = (Record.size() - SizeIdx) / 2;
    }
  };

  AddDiagState(Diag.DiagStatesByLoc.FirstDiagState, isModule);

  // Reserve a spot for the number of locations with state transitions.
  auto NumLocationsIdx = Record.size();
  Record.emplace_back();

  // Emit the state transitions.
  unsigned NumLocations = 0;
  for (auto &FileIDAndFile : Diag.DiagStatesByLoc.Files) {
    if (!FileIDAndFile.first.isValid() ||
        !FileIDAndFile.second.HasLocalTransitions)
      continue;
    ++NumLocations;

    AddFileID(FileIDAndFile.first, Record);

    Record.push_back(FileIDAndFile.second.StateTransitions.size());
    for (auto &StatePoint : FileIDAndFile.second.StateTransitions) {
      Record.push_back(StatePoint.Offset);
      AddDiagState(StatePoint.State, false);
    }
  }

  // Backpatch the number of locations.
  Record[NumLocationsIdx] = NumLocations;

  // Emit CurDiagStateLoc.  Do it last in order to match source order.
  //
  // This also protects against a hypothetical corner case with simulating
  // -Werror settings for implicit modules in the ASTReader, where reading
  // CurDiagState out of context could change whether warning pragmas are
  // treated as errors.
  AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record);
  AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false);

  // Emit the push stack so that unmatched pushes from a preamble can be
  // restored when the main file is parsed.  Each entry is a DiagState that
  // was active at the time of a `#pragma diagnostic push`.
  Record.push_back(Diag.DiagStateOnPushStack.size());
  for (const auto *State : Diag.DiagStateOnPushStack)
    AddDiagState(State, false);

  Stream.EmitRecord(DIAG_PRAGMA_MAPPINGS, Record);
}

//===----------------------------------------------------------------------===//
// Type Serialization
//===----------------------------------------------------------------------===//

/// Write the representation of a type to the AST stream.
void ASTWriter::WriteType(ASTContext &Context, QualType T) {
  TypeIdx &IdxRef = TypeIdxs[T];
  if (IdxRef.getValue() == 0) // we haven't seen this type before.
    IdxRef = TypeIdx(0, NextTypeID++);
  TypeIdx Idx = IdxRef;

  assert(Idx.getModuleFileIndex() == 0 && "Re-writing a type from a prior AST");
  assert(Idx.getValue() >= FirstTypeID && "Writing predefined type");

  // Emit the type's representation.
  uint64_t Offset =
      ASTTypeWriter(Context, *this).write(T) - DeclTypesBlockStartOffset;

  // Record the offset for this type.
  uint64_t Index = Idx.getValue() - FirstTypeID;
  if (TypeOffsets.size() == Index)
    TypeOffsets.emplace_back(Offset);
  else if (TypeOffsets.size() < Index) {
    TypeOffsets.resize(Index + 1);
    TypeOffsets[Index].set(Offset);
  } else {
    llvm_unreachable("Types emitted in wrong order");
  }
}

//===----------------------------------------------------------------------===//
// Declaration Serialization
//===----------------------------------------------------------------------===//

static bool IsInternalDeclFromFileContext(const Decl *D) {
  auto *ND = dyn_cast<NamedDecl>(D);
  if (!ND)
    return false;

  if (!D->getDeclContext()->getRedeclContext()->isFileContext())
    return false;

  return ND->getFormalLinkage() == Linkage::Internal;
}

/// Write the block containing all of the declaration IDs
/// lexically declared within the given DeclContext.
///
/// \returns the offset of the DECL_CONTEXT_LEXICAL block within the
/// bitstream, or 0 if no block was written.
uint64_t ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
                                                 const DeclContext *DC) {
  if (DC->decls_empty())
    return 0;

  // In reduced BMI, we don't care the declarations in functions.
  if (GeneratingReducedBMI && DC->isFunctionOrMethod())
    return 0;

  uint64_t Offset = Stream.GetCurrentBitNo();
  SmallVector<DeclID, 128> KindDeclPairs;
  for (const auto *D : DC->decls()) {
    if (DoneWritingDeclsAndTypes && !wasDeclEmitted(D))
      continue;

    // We don't need to write decls with internal linkage into reduced BMI.
    // If such decls gets emitted due to it get used from inline functions,
    // the program illegal. However, there are too many use of static inline
    // functions in the global module fragment and it will be breaking change
    // to forbid that. So we have to allow to emit such declarations from GMF.
    if (GeneratingReducedBMI && !D->isFromExplicitGlobalModule() &&
        IsInternalDeclFromFileContext(D))
      continue;

    KindDeclPairs.push_back(D->getKind());
    KindDeclPairs.push_back(GetDeclRef(D).getRawValue());
  }

  ++NumLexicalDeclContexts;
  RecordData::value_type Record[] = {DECL_CONTEXT_LEXICAL};
  Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record,
                            bytes(KindDeclPairs));
  return Offset;
}

void ASTWriter::WriteTypeDeclOffsets() {
  using namespace llvm;

  // Write the type offsets array
  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(TYPE_OFFSET));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
  unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
  {
    RecordData::value_type Record[] = {TYPE_OFFSET, TypeOffsets.size()};
    Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, bytes(TypeOffsets));
  }

  // Write the declaration offsets array
  Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(DECL_OFFSET));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
  unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
  {
    RecordData::value_type Record[] = {DECL_OFFSET, DeclOffsets.size()};
    Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, bytes(DeclOffsets));
  }
}

void ASTWriter::WriteFileDeclIDsMap() {
  using namespace llvm;

  SmallVector<std::pair<FileID, DeclIDInFileInfo *>, 64> SortedFileDeclIDs;
  SortedFileDeclIDs.reserve(FileDeclIDs.size());
  for (const auto &P : FileDeclIDs)
    SortedFileDeclIDs.push_back(std::make_pair(P.first, P.second.get()));
  llvm::sort(SortedFileDeclIDs, llvm::less_first());

  // Join the vectors of DeclIDs from all files.
  SmallVector<DeclID, 256> FileGroupedDeclIDs;
  for (auto &FileDeclEntry : SortedFileDeclIDs) {
    DeclIDInFileInfo &Info = *FileDeclEntry.second;
    Info.FirstDeclIndex = FileGroupedDeclIDs.size();
    llvm::stable_sort(Info.DeclIDs);
    for (auto &LocDeclEntry : Info.DeclIDs)
      FileGroupedDeclIDs.push_back(LocDeclEntry.second.getRawValue());
  }

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(FILE_SORTED_DECLS));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));
  RecordData::value_type Record[] = {FILE_SORTED_DECLS,
                                     FileGroupedDeclIDs.size()};
  Stream.EmitRecordWithBlob(AbbrevCode, Record, bytes(FileGroupedDeclIDs));
}

void ASTWriter::WriteComments(ASTContext &Context) {
  Stream.EnterSubblock(COMMENTS_BLOCK_ID, 3);
  llvm::scope_exit _([this] { Stream.ExitBlock(); });
  if (!PP->getPreprocessorOpts().WriteCommentListToPCH)
    return;

  RecordData Record;
  for (const auto &FO : Context.Comments.OrderedComments) {
    for (const auto &OC : FO.second) {
      const RawComment *I = OC.second;
      Record.clear();
      AddSourceRange(I->getSourceRange(), Record);
      Record.push_back(I->getKind());
      Record.push_back(I->isTrailingComment());
      Record.push_back(I->isAlmostTrailingComment());
      Stream.EmitRecord(COMMENTS_RAW_COMMENT, Record);
    }
  }
}

//===----------------------------------------------------------------------===//
// Global Method Pool and Selector Serialization
//===----------------------------------------------------------------------===//

namespace {

// Trait used for the on-disk hash table used in the method pool.
class ASTMethodPoolTrait {
  ASTWriter &Writer;

public:
  using key_type = Selector;
  using key_type_ref = key_type;

  struct data_type {
    SelectorID ID;
    ObjCMethodList Instance, Factory;
  };
  using data_type_ref = const data_type &;

  using hash_value_type = unsigned;
  using offset_type = unsigned;

  explicit ASTMethodPoolTrait(ASTWriter &Writer) : Writer(Writer) {}

  static hash_value_type ComputeHash(Selector Sel) {
    return serialization::ComputeHash(Sel);
  }

  std::pair<unsigned, unsigned>
    EmitKeyDataLength(raw_ostream& Out, Selector Sel,
                      data_type_ref Methods) {
    unsigned KeyLen =
        2 + (Sel.getNumArgs() ? Sel.getNumArgs() * sizeof(IdentifierID)
                              : sizeof(IdentifierID));
    unsigned DataLen = 4 + 2 + 2; // 2 bytes for each of the method counts
    for (const ObjCMethodList *Method = &Methods.Instance; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        DataLen += sizeof(DeclID);
    for (const ObjCMethodList *Method = &Methods.Factory; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        DataLen += sizeof(DeclID);
    return emitULEBKeyDataLength(KeyLen, DataLen, Out);
  }

  void EmitKey(raw_ostream& Out, Selector Sel, unsigned) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    uint64_t Start = Out.tell();
    assert((Start >> 32) == 0 && "Selector key offset too large");
    Writer.SetSelectorOffset(Sel, Start);
    unsigned N = Sel.getNumArgs();
    LE.write<uint16_t>(N);
    if (N == 0)
      N = 1;
    for (unsigned I = 0; I != N; ++I)
      LE.write<IdentifierID>(
          Writer.getIdentifierRef(Sel.getIdentifierInfoForSlot(I)));
  }

  void EmitData(raw_ostream& Out, key_type_ref,
                data_type_ref Methods, unsigned DataLen) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    uint64_t Start = Out.tell(); (void)Start;
    LE.write<uint32_t>(Methods.ID);
    unsigned NumInstanceMethods = 0;
    for (const ObjCMethodList *Method = &Methods.Instance; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        ++NumInstanceMethods;

    unsigned NumFactoryMethods = 0;
    for (const ObjCMethodList *Method = &Methods.Factory; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        ++NumFactoryMethods;

    unsigned InstanceBits = Methods.Instance.getBits();
    assert(InstanceBits < 4);
    unsigned InstanceHasMoreThanOneDeclBit =
        Methods.Instance.hasMoreThanOneDecl();
    unsigned FullInstanceBits = (NumInstanceMethods << 3) |
                                (InstanceHasMoreThanOneDeclBit << 2) |
                                InstanceBits;
    unsigned FactoryBits = Methods.Factory.getBits();
    assert(FactoryBits < 4);
    unsigned FactoryHasMoreThanOneDeclBit =
        Methods.Factory.hasMoreThanOneDecl();
    unsigned FullFactoryBits = (NumFactoryMethods << 3) |
                               (FactoryHasMoreThanOneDeclBit << 2) |
                               FactoryBits;
    LE.write<uint16_t>(FullInstanceBits);
    LE.write<uint16_t>(FullFactoryBits);
    for (const ObjCMethodList *Method = &Methods.Instance; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));
    for (const ObjCMethodList *Method = &Methods.Factory; Method;
         Method = Method->getNext())
      if (ShouldWriteMethodListNode(Method))
        LE.write<DeclID>((DeclID)Writer.getDeclID(Method->getMethod()));

    assert(Out.tell() - Start == DataLen && "Data length is wrong");
  }

private:
  static bool ShouldWriteMethodListNode(const ObjCMethodList *Node) {
    return (Node->getMethod() && !Node->getMethod()->isFromASTFile());
  }
};

} // namespace

/// Write ObjC data: selectors and the method pool.
///
/// The method pool contains both instance and factory methods, stored
/// in an on-disk hash table indexed by the selector. The hash table also
/// contains an empty entry for every other selector known to Sema.
void ASTWriter::WriteSelectors(Sema &SemaRef) {
  using namespace llvm;

  // Do we have to do anything at all?
  if (SemaRef.ObjC().MethodPool.empty() && SelectorIDs.empty())
    return;
  unsigned NumTableEntries = 0;
  // Create and write out the blob that contains selectors and the method pool.
  {
    llvm::OnDiskChainedHashTableGenerator<ASTMethodPoolTrait> Generator;
    ASTMethodPoolTrait Trait(*this);

    // Create the on-disk hash table representation. We walk through every
    // selector we've seen and look it up in the method pool.
    SelectorOffsets.resize(NextSelectorID - FirstSelectorID);
    for (auto &SelectorAndID : SelectorIDs) {
      Selector S = SelectorAndID.first;
      SelectorID ID = SelectorAndID.second;
      SemaObjC::GlobalMethodPool::iterator F =
          SemaRef.ObjC().MethodPool.find(S);
      ASTMethodPoolTrait::data_type Data = {
        ID,
        ObjCMethodList(),
        ObjCMethodList()
      };
      if (F != SemaRef.ObjC().MethodPool.end()) {
        Data.Instance = F->second.first;
        Data.Factory = F->second.second;
      }
      // Only write this selector if it's not in an existing AST or something
      // changed.
      if (Chain && ID < FirstSelectorID) {
        // Selector already exists. Did it change?
        bool changed = false;
        for (ObjCMethodList *M = &Data.Instance; M && M->getMethod();
             M = M->getNext()) {
          if (!M->getMethod()->isFromASTFile()) {
            changed = true;
            Data.Instance = *M;
            break;
          }
        }
        for (ObjCMethodList *M = &Data.Factory; M && M->getMethod();
             M = M->getNext()) {
          if (!M->getMethod()->isFromASTFile()) {
            changed = true;
            Data.Factory = *M;
            break;
          }
        }
        if (!changed)
          continue;
      } else if (Data.Instance.getMethod() || Data.Factory.getMethod()) {
        // A new method pool entry.
        ++NumTableEntries;
      }
      Generator.insert(S, Data, Trait);
    }

    // Create the on-disk hash table in a buffer.
    SmallString<4096> MethodPool;
    uint32_t BucketOffset;
    {
      using namespace llvm::support;

      ASTMethodPoolTrait Trait(*this);
      llvm::raw_svector_ostream Out(MethodPool);
      // Make sure that no bucket is at offset 0
      endian::write<uint32_t>(Out, 0, llvm::endianness::little);
      BucketOffset = Generator.Emit(Out, Trait);
    }

    // Create a blob abbreviation
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(METHOD_POOL));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned MethodPoolAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    // Write the method pool
    {
      RecordData::value_type Record[] = {METHOD_POOL, BucketOffset,
                                         NumTableEntries};
      Stream.EmitRecordWithBlob(MethodPoolAbbrev, Record, MethodPool);
    }

    // Create a blob abbreviation for the selector table offsets.
    Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(SELECTOR_OFFSETS));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // size
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // first ID
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned SelectorOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    // Write the selector offsets table.
    {
      RecordData::value_type Record[] = {
          SELECTOR_OFFSETS, SelectorOffsets.size(),
          FirstSelectorID - NUM_PREDEF_SELECTOR_IDS};
      Stream.EmitRecordWithBlob(SelectorOffsetAbbrev, Record,
                                bytes(SelectorOffsets));
    }
  }
}

/// Write the selectors referenced in @selector expression into AST file.
void ASTWriter::WriteReferencedSelectorsPool(Sema &SemaRef) {
  using namespace llvm;

  if (SemaRef.ObjC().ReferencedSelectors.empty())
    return;

  RecordData Record;
  ASTRecordWriter Writer(SemaRef.Context, *this, Record);

  // Note: this writes out all references even for a dependent AST. But it is
  // very tricky to fix, and given that @selector shouldn't really appear in
  // headers, probably not worth it. It's not a correctness issue.
  for (auto &SelectorAndLocation : SemaRef.ObjC().ReferencedSelectors) {
    Selector Sel = SelectorAndLocation.first;
    SourceLocation Loc = SelectorAndLocation.second;
    Writer.AddSelectorRef(Sel);
    Writer.AddSourceLocation(Loc);
  }
  Writer.Emit(REFERENCED_SELECTOR_POOL);
}

//===----------------------------------------------------------------------===//
// Identifier Table Serialization
//===----------------------------------------------------------------------===//

/// Determine the declaration that should be put into the name lookup table to
/// represent the given declaration in this module. This is usually D itself,
/// but if D was imported and merged into a local declaration, we want the most
/// recent local declaration instead. The chosen declaration will be the most
/// recent declaration in any module that imports this one.
static NamedDecl *getDeclForLocalLookup(const LangOptions &LangOpts,
                                        NamedDecl *D) {
  if (!LangOpts.Modules || !D->isFromASTFile())
    return D;

  if (Decl *Redecl = D->getPreviousDecl()) {
    // For Redeclarable decls, a prior declaration might be local.
    for (; Redecl; Redecl = Redecl->getPreviousDecl()) {
      // If we find a local decl, we're done.
      if (!Redecl->isFromASTFile()) {
        // Exception: in very rare cases (for injected-class-names), not all
        // redeclarations are in the same semantic context. Skip ones in a
        // different context. They don't go in this lookup table at all.
        if (!Redecl->getDeclContext()->getRedeclContext()->Equals(
                D->getDeclContext()->getRedeclContext()))
          continue;
        return cast<NamedDecl>(Redecl);
      }

      // If we find a decl from a (chained-)PCH stop since we won't find a
      // local one.
      if (Redecl->getOwningModuleID() == 0)
        break;
    }
  } else if (Decl *First = D->getCanonicalDecl()) {
    // For Mergeable decls, the first decl might be local.
    if (!First->isFromASTFile())
      return cast<NamedDecl>(First);
  }

  // All declarations are imported. Our most recent declaration will also be
  // the most recent one in anyone who imports us.
  return D;
}

namespace {

bool IsInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset,
                             bool IsModule, bool IsCPlusPlus) {
  bool NeedDecls = !IsModule || !IsCPlusPlus;

  bool IsInteresting =
      II->getNotableIdentifierID() != tok::NotableIdentifierKind::not_notable ||
      II->getBuiltinID() != Builtin::ID::NotBuiltin ||
      II->getObjCKeywordID() != tok::ObjCKeywordKind::objc_not_keyword;
  if (MacroOffset ||
      (II->hasMacroDefinition() &&
       II->hasFETokenInfoChangedSinceDeserialization()) ||
      II->isPoisoned() || (!IsModule && IsInteresting) ||
      II->hasRevertedTokenIDToIdentifier() ||
      (NeedDecls && II->getFETokenInfo()))
    return true;

  return false;
}

bool IsInterestingNonMacroIdentifier(const IdentifierInfo *II,
                                     ASTWriter &Writer) {
  bool IsModule = Writer.isWritingModule();
  bool IsCPlusPlus = Writer.getLangOpts().CPlusPlus;
  return IsInterestingIdentifier(II, /*MacroOffset=*/0, IsModule, IsCPlusPlus);
}

class ASTIdentifierTableTrait {
  ASTWriter &Writer;
  Preprocessor &PP;
  IdentifierResolver *IdResolver;
  bool IsModule;
  bool NeedDecls;
  ASTWriter::RecordData *InterestingIdentifierOffsets;

  /// Determines whether this is an "interesting" identifier that needs a
  /// full IdentifierInfo structure written into the hash table. Notably, this
  /// doesn't check whether the name has macros defined; use PublicMacroIterator
  /// to check that.
  bool isInterestingIdentifier(const IdentifierInfo *II, uint64_t MacroOffset) {
    return IsInterestingIdentifier(II, MacroOffset, IsModule,
                                   Writer.getLangOpts().CPlusPlus);
  }

public:
  using key_type = const IdentifierInfo *;
  using key_type_ref = key_type;

  using data_type = IdentifierID;
  using data_type_ref = data_type;

  using hash_value_type = unsigned;
  using offset_type = unsigned;

  ASTIdentifierTableTrait(ASTWriter &Writer, Preprocessor &PP,
                          IdentifierResolver *IdResolver, bool IsModule,
                          ASTWriter::RecordData *InterestingIdentifierOffsets)
      : Writer(Writer), PP(PP), IdResolver(IdResolver), IsModule(IsModule),
        NeedDecls(!IsModule || !Writer.getLangOpts().CPlusPlus),
        InterestingIdentifierOffsets(InterestingIdentifierOffsets) {}

  bool needDecls() const { return NeedDecls; }

  static hash_value_type ComputeHash(const IdentifierInfo* II) {
    return llvm::djbHash(II->getName());
  }

  bool isInterestingIdentifier(const IdentifierInfo *II) {
    auto MacroOffset = Writer.getMacroDirectivesOffset(II);
    return isInterestingIdentifier(II, MacroOffset);
  }

  std::pair<unsigned, unsigned>
  EmitKeyDataLength(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID) {
    // Record the location of the identifier data. This is used when generating
    // the mapping from persistent IDs to strings.
    Writer.SetIdentifierOffset(II, Out.tell());

    auto MacroOffset = Writer.getMacroDirectivesOffset(II);

    // Emit the offset of the key/data length information to the interesting
    // identifiers table if necessary.
    if (InterestingIdentifierOffsets &&
        isInterestingIdentifier(II, MacroOffset))
      InterestingIdentifierOffsets->push_back(Out.tell());

    unsigned KeyLen = II->getLength() + 1;
    unsigned DataLen = sizeof(IdentifierID); // bytes for the persistent ID << 1
    if (isInterestingIdentifier(II, MacroOffset)) {
      DataLen += 2; // 2 bytes for builtin ID
      DataLen += 2; // 2 bytes for flags
      if (MacroOffset || (II->hasMacroDefinition() &&
                          II->hasFETokenInfoChangedSinceDeserialization()))
        DataLen += 4; // MacroDirectives offset.

      if (NeedDecls && IdResolver)
        DataLen += std::distance(IdResolver->begin(II), IdResolver->end()) *
                   sizeof(DeclID);
    }
    return emitULEBKeyDataLength(KeyLen, DataLen, Out);
  }

  void EmitKey(raw_ostream &Out, const IdentifierInfo *II, unsigned KeyLen) {
    Out.write(II->getNameStart(), KeyLen);
  }

  void EmitData(raw_ostream &Out, const IdentifierInfo *II, IdentifierID ID,
                unsigned) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);

    auto MacroOffset = Writer.getMacroDirectivesOffset(II);
    if (!isInterestingIdentifier(II, MacroOffset)) {
      LE.write<IdentifierID>(ID << 1);
      return;
    }

    LE.write<IdentifierID>((ID << 1) | 0x01);
    uint32_t Bits = (uint32_t)II->getObjCOrBuiltinID();
    assert((Bits & 0xffff) == Bits && "ObjCOrBuiltinID too big for ASTReader.");
    LE.write<uint16_t>(Bits);
    Bits = 0;
    bool HasMacroDefinition =
        (MacroOffset != 0) || (II->hasMacroDefinition() &&
                               II->hasFETokenInfoChangedSinceDeserialization());
    Bits = (Bits << 1) | unsigned(HasMacroDefinition);
    Bits = (Bits << 1) | unsigned(II->isExtensionToken());
    Bits = (Bits << 1) | unsigned(II->isPoisoned());
    Bits = (Bits << 1) | unsigned(II->hasRevertedTokenIDToIdentifier());
    Bits = (Bits << 1) | unsigned(II->isCPlusPlusOperatorKeyword());
    LE.write<uint16_t>(Bits);

    if (HasMacroDefinition)
      LE.write<uint32_t>(MacroOffset);

    if (NeedDecls && IdResolver) {
      // Emit the declaration IDs in reverse order, because the
      // IdentifierResolver provides the declarations as they would be
      // visible (e.g., the function "stat" would come before the struct
      // "stat"), but the ASTReader adds declarations to the end of the list
      // (so we need to see the struct "stat" before the function "stat").
      // Only emit declarations that aren't from a chained PCH, though.
      SmallVector<NamedDecl *, 16> Decls(IdResolver->decls(II));
      for (NamedDecl *D : llvm::reverse(Decls))
        LE.write<DeclID>((DeclID)Writer.getDeclID(
            getDeclForLocalLookup(PP.getLangOpts(), D)));
    }
  }
};

} // namespace

/// If the \param IdentifierID ID is a local Identifier ID. If the higher
/// bits of ID is 0, it implies that the ID doesn't come from AST files.
static bool isLocalIdentifierID(IdentifierID ID) { return !(ID >> 32); }

/// Write the identifier table into the AST file.
///
/// The identifier table consists of a blob containing string data
/// (the actual identifiers themselves) and a separate "offsets" index
/// that maps identifier IDs to locations within the blob.
void ASTWriter::WriteIdentifierTable(Preprocessor &PP,
                                     IdentifierResolver *IdResolver,
                                     bool IsModule) {
  using namespace llvm;

  RecordData InterestingIdents;

  // Create and write out the blob that contains the identifier
  // strings.
  {
    llvm::OnDiskChainedHashTableGenerator<ASTIdentifierTableTrait> Generator;
    ASTIdentifierTableTrait Trait(*this, PP, IdResolver, IsModule,
                                  IsModule ? &InterestingIdents : nullptr);

    // Create the on-disk hash table representation. We only store offsets
    // for identifiers that appear here for the first time.
    IdentifierOffsets.resize(NextIdentID - FirstIdentID);
    for (auto IdentIDPair : IdentifierIDs) {
      const IdentifierInfo *II = IdentIDPair.first;
      IdentifierID ID = IdentIDPair.second;
      assert(II && "NULL identifier in identifier table");

      // Write out identifiers if either the ID is local or the identifier has
      // changed since it was loaded.
      if (isLocalIdentifierID(ID) || II->hasChangedSinceDeserialization() ||
          (Trait.needDecls() &&
           II->hasFETokenInfoChangedSinceDeserialization()))
        Generator.insert(II, ID, Trait);
    }

    // Create the on-disk hash table in a buffer.
    SmallString<4096> IdentifierTable;
    uint32_t BucketOffset;
    {
      using namespace llvm::support;

      llvm::raw_svector_ostream Out(IdentifierTable);
      // Make sure that no bucket is at offset 0
      endian::write<uint32_t>(Out, 0, llvm::endianness::little);
      BucketOffset = Generator.Emit(Out, Trait);
    }

    // Create a blob abbreviation
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_TABLE));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

    // Write the identifier table
    RecordData::value_type Record[] = {IDENTIFIER_TABLE, BucketOffset};
    Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable);
  }

  // Write the offsets table for identifier IDs.
  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_OFFSET));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of identifiers
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  unsigned IdentifierOffsetAbbrev = Stream.EmitAbbrev(std::move(Abbrev));

#ifndef NDEBUG
  for (unsigned I = 0, N = IdentifierOffsets.size(); I != N; ++I)
    assert(IdentifierOffsets[I] && "Missing identifier offset?");
#endif

  RecordData::value_type Record[] = {IDENTIFIER_OFFSET,
                                     IdentifierOffsets.size()};
  Stream.EmitRecordWithBlob(IdentifierOffsetAbbrev, Record,
                            bytes(IdentifierOffsets));

  // In C++, write the list of interesting identifiers (those that are
  // defined as macros, poisoned, or similar unusual things).
  if (!InterestingIdents.empty())
    Stream.EmitRecord(INTERESTING_IDENTIFIERS, InterestingIdents);
}

void ASTWriter::handleVTable(CXXRecordDecl *RD) {
  if (!RD->isInNamedModule())
    return;

  PendingEmittingVTables.push_back(RD);
}

void ASTWriter::addTouchedModuleFile(serialization::ModuleFile *MF) {
  TouchedModuleFiles.insert(MF);
}

//===----------------------------------------------------------------------===//
// DeclContext's Name Lookup Table Serialization
//===----------------------------------------------------------------------===//

namespace {

class ASTDeclContextNameLookupTraitBase {
protected:
  ASTWriter &Writer;
  using DeclIDsTy = llvm::SmallVector<LocalDeclID, 64>;
  DeclIDsTy DeclIDs;

public:
  /// A start and end index into DeclIDs, representing a sequence of decls.
  using data_type = std::pair<unsigned, unsigned>;
  using data_type_ref = const data_type &;

  using hash_value_type = unsigned;
  using offset_type = unsigned;

  explicit ASTDeclContextNameLookupTraitBase(ASTWriter &Writer)
      : Writer(Writer) {}

  data_type getData(const DeclIDsTy &LocalIDs) {
    unsigned Start = DeclIDs.size();
    for (auto ID : LocalIDs)
      DeclIDs.push_back(ID);
    return std::make_pair(Start, DeclIDs.size());
  }

  data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) {
    unsigned Start = DeclIDs.size();
    DeclIDs.insert(
        DeclIDs.end(),
        DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.begin()),
        DeclIDIterator<GlobalDeclID, LocalDeclID>(FromReader.end()));
    return std::make_pair(Start, DeclIDs.size());
  }

  void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {
    assert(Writer.hasChain() &&
           "have reference to loaded module file but no chain?");

    using namespace llvm::support;
    Writer.addTouchedModuleFile(F);
    endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F),
                            llvm::endianness::little);
  }

  std::pair<unsigned, unsigned> EmitKeyDataLengthBase(raw_ostream &Out,
                                                      DeclarationNameKey Name,
                                                      data_type_ref Lookup) {
    unsigned KeyLen = 1;
    switch (Name.getKind()) {
    case DeclarationName::Identifier:
    case DeclarationName::CXXLiteralOperatorName:
    case DeclarationName::CXXDeductionGuideName:
      KeyLen += sizeof(IdentifierID);
      break;
    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
      KeyLen += 4;
      break;
    case DeclarationName::CXXOperatorName:
      KeyLen += 1;
      break;
    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
    case DeclarationName::CXXUsingDirective:
      break;
    }

    // length of DeclIDs.
    unsigned DataLen = sizeof(DeclID) * (Lookup.second - Lookup.first);

    return {KeyLen, DataLen};
  }

  void EmitKeyBase(raw_ostream &Out, DeclarationNameKey Name) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    LE.write<uint8_t>(Name.getKind());
    switch (Name.getKind()) {
    case DeclarationName::Identifier:
    case DeclarationName::CXXLiteralOperatorName:
    case DeclarationName::CXXDeductionGuideName:
      LE.write<IdentifierID>(Writer.getIdentifierRef(Name.getIdentifier()));
      return;
    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
      LE.write<uint32_t>(Writer.getSelectorRef(Name.getSelector()));
      return;
    case DeclarationName::CXXOperatorName:
      assert(Name.getOperatorKind() < NUM_OVERLOADED_OPERATORS &&
             "Invalid operator?");
      LE.write<uint8_t>(Name.getOperatorKind());
      return;
    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
    case DeclarationName::CXXUsingDirective:
      return;
    }

    llvm_unreachable("Invalid name kind?");
  }

  void EmitDataBase(raw_ostream &Out, data_type Lookup, unsigned DataLen) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    uint64_t Start = Out.tell(); (void)Start;
    for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I)
      LE.write<DeclID>((DeclID)DeclIDs[I]);
    assert(Out.tell() - Start == DataLen && "Data length is wrong");
  }
};

class ModuleLevelNameLookupTrait : public ASTDeclContextNameLookupTraitBase {
public:
  using primary_module_hash_type = unsigned;

  using key_type = std::pair<DeclarationNameKey, primary_module_hash_type>;
  using key_type_ref = key_type;

  explicit ModuleLevelNameLookupTrait(ASTWriter &Writer)
      : ASTDeclContextNameLookupTraitBase(Writer) {}

  static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }

  hash_value_type ComputeHash(key_type Key) {
    llvm::FoldingSetNodeID ID;
    ID.AddInteger(Key.first.getHash());
    ID.AddInteger(Key.second);
    return ID.computeStableHash();
  }

  std::pair<unsigned, unsigned>
  EmitKeyDataLength(raw_ostream &Out, key_type Key, data_type_ref Lookup) {
    auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Key.first, Lookup);
    KeyLen += sizeof(Key.second);
    return emitULEBKeyDataLength(KeyLen, DataLen, Out);
  }

  void EmitKey(raw_ostream &Out, key_type Key, unsigned) {
    EmitKeyBase(Out, Key.first);
    llvm::support::endian::Writer LE(Out, llvm::endianness::little);
    LE.write<primary_module_hash_type>(Key.second);
  }

  void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,
                unsigned DataLen) {
    EmitDataBase(Out, Lookup, DataLen);
  }
};

class ASTDeclContextNameTrivialLookupTrait
    : public ASTDeclContextNameLookupTraitBase {
public:
  using key_type = DeclarationNameKey;
  using key_type_ref = key_type;

public:
  using ASTDeclContextNameLookupTraitBase::ASTDeclContextNameLookupTraitBase;

  using ASTDeclContextNameLookupTraitBase::getData;

  static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }

  hash_value_type ComputeHash(key_type Name) { return Name.getHash(); }

  std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,
                                                  DeclarationNameKey Name,
                                                  data_type_ref Lookup) {
    auto [KeyLen, DataLen] = EmitKeyDataLengthBase(Out, Name, Lookup);
    return emitULEBKeyDataLength(KeyLen, DataLen, Out);
  }

  void EmitKey(raw_ostream &Out, DeclarationNameKey Name, unsigned) {
    return EmitKeyBase(Out, Name);
  }

  void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,
                unsigned DataLen) {
    EmitDataBase(Out, Lookup, DataLen);
  }
};

static bool isModuleLocalDecl(NamedDecl *D) {
  // For decls not in a file context, they should have the same visibility
  // with their parent.
  if (auto *Parent = dyn_cast<NamedDecl>(D->getNonTransparentDeclContext());
      Parent && !D->getNonTransparentDeclContext()->isFileContext())
    return isModuleLocalDecl(Parent);

  // Deduction Guide are special here. Since their logical parent context are
  // not their actual parent.
  if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
    if (auto *CDGD = dyn_cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()))
      return isModuleLocalDecl(CDGD->getDeducedTemplate());

  if (D->getFormalLinkage() != Linkage::Module)
    return false;

  // It is hard for the serializer to judge if the in-class friend declaration
  // is visible or not, so we just transfer the task to Sema. It should be a
  // safe decision since Sema is able to handle the lookup rules for in-class
  // friend declarations good enough already.
  if (D->getFriendObjectKind() &&
      isa<CXXRecordDecl>(D->getLexicalDeclContext()))
    return false;

  return true;
}

static bool isTULocalInNamedModules(NamedDecl *D) {
  Module *NamedModule = D->getTopLevelOwningNamedModule();
  if (!NamedModule)
    return false;

  // For none-top level decls, we choose to move it to the general visible
  // lookup table. Since the consumer may get its parent somehow and performs
  // a lookup in it (considering looking up the operator function in lambda).
  // The difference between module local lookup table and TU local lookup table
  // is, the consumers still have a chance to lookup in the module local lookup
  // table but **now** the consumers won't read the TU local lookup table if
  // the consumer is not the original TU.
  //
  // FIXME: It seems to be an optimization chance (and also a more correct
  // semantics) to remain the TULocal lookup table and performing similar lookup
  // with the module local lookup table except that we only allow the lookups
  // with the same module unit.
  if (!D->getNonTransparentDeclContext()->isFileContext())
    return false;

  return D->getLinkageInternal() == Linkage::Internal;
}

class ASTDeclContextNameLookupTrait
    : public ASTDeclContextNameTrivialLookupTrait {
public:
  using TULocalDeclsMapTy = llvm::DenseMap<key_type, DeclIDsTy>;

  using ModuleLevelDeclsMapTy =
      llvm::DenseMap<ModuleLevelNameLookupTrait::key_type, DeclIDsTy>;

private:
  enum class LookupVisibility {
    GenerallyVisibile,
    // The decls can only be found by other TU in the same module.
    // Note a clang::Module models a module unit instead of logical module
    // in C++20.
    ModuleLocalVisible,
    // The decls can only be found by the TU itself that defines it.
    TULocal,
  };

  LookupVisibility getLookupVisibility(NamedDecl *D) const {
    // Only named modules have other lookup visibility.
    if (!Writer.isWritingStdCXXNamedModules())
      return LookupVisibility::GenerallyVisibile;

    if (isModuleLocalDecl(D))
      return LookupVisibility::ModuleLocalVisible;
    if (isTULocalInNamedModules(D))
      return LookupVisibility::TULocal;

    // A trick to handle enum constants. The enum constants is special since
    // they can be found directly without their parent context. This makes it
    // tricky to decide if an EnumConstantDecl is visible or not by their own
    // visibilities. E.g., for a class member, we can assume it is visible if
    // the user get its parent somehow. But for an enum constant, the users may
    // access if without its parent context. Although we can fix the problem in
    // Sema lookup process, it might be too complex, we just make a trick here.
    // Note that we only removes enum constant from the lookup table from its
    // parent of parent. We DON'T remove the enum constant from its parent. So
    // we don't need to care about merging problems here.
    if (auto *ECD = dyn_cast<EnumConstantDecl>(D);
        ECD && DC.isFileContext() && ECD->getTopLevelOwningNamedModule()) {
      if (llvm::all_of(
              DC.noload_lookup(
                  cast<EnumDecl>(ECD->getDeclContext())->getDeclName()),
              [](auto *Found) {
                return Found->isInvisibleOutsideTheOwningModule();
              }))
        return ECD->isFromExplicitGlobalModule() ||
                       ECD->isInAnonymousNamespace()
                   ? LookupVisibility::TULocal
                   : LookupVisibility::ModuleLocalVisible;
    }

    return LookupVisibility::GenerallyVisibile;
  }

  DeclContext &DC;
  ModuleLevelDeclsMapTy ModuleLocalDeclsMap;
  TULocalDeclsMapTy TULocalDeclsMap;

public:
  using ASTDeclContextNameTrivialLookupTrait::
      ASTDeclContextNameTrivialLookupTrait;

  ASTDeclContextNameLookupTrait(ASTWriter &Writer, DeclContext &DC)
      : ASTDeclContextNameTrivialLookupTrait(Writer), DC(DC) {}

  template <typename Coll> data_type getData(const Coll &Decls) {
    unsigned Start = DeclIDs.size();
    auto AddDecl = [this](NamedDecl *D) {
      NamedDecl *DeclForLocalLookup =
          getDeclForLocalLookup(Writer.getLangOpts(), D);

      if (Writer.getDoneWritingDeclsAndTypes() &&
          !Writer.wasDeclEmitted(DeclForLocalLookup))
        return;

      // Try to avoid writing internal decls to reduced BMI.
      // See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
      if (Writer.isGeneratingReducedBMI() &&
          !DeclForLocalLookup->isFromExplicitGlobalModule() &&
          IsInternalDeclFromFileContext(DeclForLocalLookup))
        return;

      auto ID = Writer.GetDeclRef(DeclForLocalLookup);

      switch (getLookupVisibility(DeclForLocalLookup)) {
      case LookupVisibility::ModuleLocalVisible:
        if (UnsignedOrNone PrimaryModuleHash =
                getPrimaryModuleHash(D->getOwningModule())) {
          auto Key = std::make_pair(D->getDeclName(), *PrimaryModuleHash);
          auto Iter = ModuleLocalDeclsMap.find(Key);
          if (Iter == ModuleLocalDeclsMap.end())
            ModuleLocalDeclsMap.insert({Key, DeclIDsTy{ID}});
          else
            Iter->second.push_back(ID);
          return;
        }
        break;
      case LookupVisibility::TULocal: {
        auto Iter = TULocalDeclsMap.find(D->getDeclName());
        if (Iter == TULocalDeclsMap.end())
          TULocalDeclsMap.insert({D->getDeclName(), DeclIDsTy{ID}});
        else
          Iter->second.push_back(ID);
        return;
      }
      case LookupVisibility::GenerallyVisibile:
        // Generally visible decls go into the general lookup table.
        break;
      }

      DeclIDs.push_back(ID);
    };
    ASTReader *Chain = Writer.getChain();
    for (NamedDecl *D : Decls) {
      if (Chain && isa<NamespaceDecl>(D) && D->isFromASTFile() &&
          D == Chain->getKeyDeclaration(D)) {
        // In ASTReader, we stored only the key declaration of a namespace decl
        // for this TU. If we have an external namespace decl, this is that
        // key declaration and we need to re-expand it to write out the first
        // decl from each module.
        //
        // See comment 'ASTReader::FindExternalVisibleDeclsByName' for details.
        auto Firsts =
            Writer.CollectFirstDeclFromEachModule(D, /*IncludeLocal=*/false);
        for (const auto &[_, First] : Firsts)
          AddDecl(cast<NamedDecl>(const_cast<Decl *>(First)));
      } else {
        AddDecl(D);
      }
    }
    return std::make_pair(Start, DeclIDs.size());
  }

  const ModuleLevelDeclsMapTy &getModuleLocalDecls() {
    return ModuleLocalDeclsMap;
  }

  const TULocalDeclsMapTy &getTULocalDecls() { return TULocalDeclsMap; }
};

} // namespace

namespace {
class LazySpecializationInfoLookupTrait {
  ASTWriter &Writer;
  llvm::SmallVector<serialization::reader::LazySpecializationInfo, 64> Specs;

public:
  using key_type = unsigned;
  using key_type_ref = key_type;

  /// A start and end index into Specs, representing a sequence of decls.
  using data_type = std::pair<unsigned, unsigned>;
  using data_type_ref = const data_type &;

  using hash_value_type = unsigned;
  using offset_type = unsigned;

  explicit LazySpecializationInfoLookupTrait(ASTWriter &Writer)
      : Writer(Writer) {}

  template <typename Col, typename Col2>
  data_type getData(Col &&C, Col2 &ExistingInfo) {
    unsigned Start = Specs.size();
    for (auto *D : C) {
      NamedDecl *ND = getDeclForLocalLookup(Writer.getLangOpts(),
                                            const_cast<NamedDecl *>(D));
      Specs.push_back(GlobalDeclID(Writer.GetDeclRef(ND).getRawValue()));
    }
    for (const serialization::reader::LazySpecializationInfo &Info :
         ExistingInfo)
      Specs.push_back(Info);
    return std::make_pair(Start, Specs.size());
  }

  data_type ImportData(
      const reader::LazySpecializationInfoLookupTrait::data_type &FromReader) {
    unsigned Start = Specs.size();
    for (auto ID : FromReader)
      Specs.push_back(ID);
    return std::make_pair(Start, Specs.size());
  }

  static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; }

  hash_value_type ComputeHash(key_type Name) { return Name; }

  void EmitFileRef(raw_ostream &Out, ModuleFile *F) const {
    assert(Writer.hasChain() &&
           "have reference to loaded module file but no chain?");

    using namespace llvm::support;
    Writer.addTouchedModuleFile(F);
    endian::write<uint32_t>(Out, Writer.getChain()->getModuleFileID(F),
                            llvm::endianness::little);
  }

  std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &Out,
                                                  key_type HashValue,
                                                  data_type_ref Lookup) {
    // 4 bytes for each slot.
    unsigned KeyLen = 4;
    unsigned DataLen = sizeof(serialization::reader::LazySpecializationInfo) *
                       (Lookup.second - Lookup.first);

    return emitULEBKeyDataLength(KeyLen, DataLen, Out);
  }

  void EmitKey(raw_ostream &Out, key_type HashValue, unsigned) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    LE.write<uint32_t>(HashValue);
  }

  void EmitData(raw_ostream &Out, key_type_ref, data_type Lookup,
                unsigned DataLen) {
    using namespace llvm::support;

    endian::Writer LE(Out, llvm::endianness::little);
    uint64_t Start = Out.tell();
    (void)Start;
    for (unsigned I = Lookup.first, N = Lookup.second; I != N; ++I) {
      LE.write<DeclID>(Specs[I].getRawValue());
    }
    assert(Out.tell() - Start == DataLen && "Data length is wrong");
  }
};

unsigned CalculateODRHashForSpecs(const Decl *Spec) {
  ArrayRef<TemplateArgument> Args;
  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Spec))
    Args = CTSD->getTemplateArgs().asArray();
  else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Spec))
    Args = VTSD->getTemplateArgs().asArray();
  else if (auto *FD = dyn_cast<FunctionDecl>(Spec))
    Args = FD->getTemplateSpecializationArgs()->asArray();
  else
    llvm_unreachable("New Specialization Kind?");

  return StableHashForTemplateArguments(Args);
}
} // namespace

void ASTWriter::GenerateSpecializationInfoLookupTable(
    const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
    llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial) {
  assert(D->isFirstDecl());

  // Create the on-disk hash table representation.
  MultiOnDiskHashTableGenerator<reader::LazySpecializationInfoLookupTrait,
                                LazySpecializationInfoLookupTrait>
      Generator;
  LazySpecializationInfoLookupTrait Trait(*this);

  llvm::MapVector<unsigned, llvm::SmallVector<const NamedDecl *, 4>>
      SpecializationMaps;

  for (auto *Specialization : Specializations) {
    unsigned HashedValue = CalculateODRHashForSpecs(Specialization);

    auto Iter = SpecializationMaps.find(HashedValue);
    if (Iter == SpecializationMaps.end())
      Iter = SpecializationMaps
                 .try_emplace(HashedValue,
                              llvm::SmallVector<const NamedDecl *, 4>())
                 .first;

    Iter->second.push_back(cast<NamedDecl>(Specialization));
  }

  auto *Lookups =
      Chain ? Chain->getLoadedSpecializationsLookupTables(D, IsPartial)
            : nullptr;

  for (auto &[HashValue, Specs] : SpecializationMaps) {
    SmallVector<serialization::reader::LazySpecializationInfo, 16>
        ExisitingSpecs;
    // We have to merge the lookup table manually here. We can't depend on the
    // merge mechanism offered by
    // clang::serialization::MultiOnDiskHashTableGenerator since that generator
    // assumes the we'll get the same value with the same key.
    // And also underlying llvm::OnDiskChainedHashTableGenerator assumes that we
    // won't insert the values with the same key twice. So we have to merge the
    // lookup table here manually.
    if (Lookups)
      ExisitingSpecs = Lookups->Table.find(HashValue);

    Generator.insert(HashValue, Trait.getData(Specs, ExisitingSpecs), Trait);
  }

  // Reduced BMI may not emit everything in the lookup table,
  // If Reduced BMI **partially** emits some decls,
  // then the generator may not emit the corresponding entry for the
  // corresponding name is already there. See
  // MultiOnDiskHashTableGenerator::insert and
  // MultiOnDiskHashTableGenerator::emit for details.
  // So we won't emit the lookup table if we're generating reduced BMI.
  auto *ToEmitMaybeMergedLookupTable =
      (!isGeneratingReducedBMI() && Lookups) ? &Lookups->Table : nullptr;
  Generator.emit(LookupTable, Trait, ToEmitMaybeMergedLookupTable);
}

uint64_t ASTWriter::WriteSpecializationInfoLookupTable(
    const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
    bool IsPartial) {

  llvm::SmallString<4096> LookupTable;
  GenerateSpecializationInfoLookupTable(D, Specializations, LookupTable,
                                        IsPartial);

  uint64_t Offset = Stream.GetCurrentBitNo();
  RecordData::value_type Record[] = {static_cast<RecordData::value_type>(
      IsPartial ? DECL_PARTIAL_SPECIALIZATIONS : DECL_SPECIALIZATIONS)};
  Stream.EmitRecordWithBlob(IsPartial ? DeclPartialSpecializationsAbbrev
                                      : DeclSpecializationsAbbrev,
                            Record, LookupTable);

  return Offset;
}

/// Returns true if all of the lookup result are either external, not emitted or
/// predefined. In such cases, the lookup result is not interesting and we don't
/// need to record the result in the current being written module. Return false
/// otherwise.
static bool isLookupResultNotInteresting(ASTWriter &Writer,
                                         StoredDeclsList &Result) {
  for (auto *D : Result.getLookupResult()) {
    auto *LocalD = getDeclForLocalLookup(Writer.getLangOpts(), D);
    if (LocalD->isFromASTFile())
      continue;

    // We can only be sure whether the local declaration is reachable
    // after we done writing the declarations and types.
    if (Writer.getDoneWritingDeclsAndTypes() && !Writer.wasDeclEmitted(LocalD))
      continue;

    // We don't need to emit the predefined decls.
    if (Writer.isDeclPredefined(LocalD))
      continue;

    return false;
  }

  return true;
}

void ASTWriter::GenerateNameLookupTable(
    ASTContext &Context, const DeclContext *ConstDC,
    llvm::SmallVectorImpl<char> &LookupTable,
    llvm::SmallVectorImpl<char> &ModuleLocalLookupTable,
    llvm::SmallVectorImpl<char> &TULookupTable) {
  assert(!ConstDC->hasLazyLocalLexicalLookups() &&
         !ConstDC->hasLazyExternalLexicalLookups() &&
         "must call buildLookups first");

  // FIXME: We need to build the lookups table, which is logically const.
  auto *DC = const_cast<DeclContext*>(ConstDC);
  assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table");

  // Create the on-disk hash table representation.
  MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,
                                ASTDeclContextNameLookupTrait>
      Generator;
  ASTDeclContextNameLookupTrait Trait(*this, *DC);

  // The first step is to collect the declaration names which we need to
  // serialize into the name lookup table, and to collect them in a stable
  // order.
  SmallVector<DeclarationName, 16> Names;

  // We also track whether we're writing out the DeclarationNameKey for
  // constructors or conversion functions.
  bool IncludeConstructorNames = false;
  bool IncludeConversionNames = false;

  for (auto &[Name, Result] : *DC->buildLookup()) {
    // If there are no local declarations in our lookup result, we
    // don't need to write an entry for the name at all. If we can't
    // write out a lookup set without performing more deserialization,
    // just skip this entry.
    //
    // Also in reduced BMI, we'd like to avoid writing unreachable
    // declarations in GMF, so we need to avoid writing declarations
    // that entirely external or unreachable.
    if (GeneratingReducedBMI && isLookupResultNotInteresting(*this, Result))
      continue;
    // We also skip empty results. If any of the results could be external and
    // the currently available results are empty, then all of the results are
    // external and we skip it above. So the only way we get here with an empty
    // results is when no results could have been external *and* we have
    // external results.
    //
    // FIXME: While we might want to start emitting on-disk entries for negative
    // lookups into a decl context as an optimization, today we *have* to skip
    // them because there are names with empty lookup results in decl contexts
    // which we can't emit in any stable ordering: we lookup constructors and
    // conversion functions in the enclosing namespace scope creating empty
    // results for them. This in almost certainly a bug in Clang's name lookup,
    // but that is likely to be hard or impossible to fix and so we tolerate it
    // here by omitting lookups with empty results.
    if (Result.getLookupResult().empty())
      continue;

    switch (Name.getNameKind()) {
    default:
      Names.push_back(Name);
      break;

    case DeclarationName::CXXConstructorName:
      IncludeConstructorNames = true;
      break;

    case DeclarationName::CXXConversionFunctionName:
      IncludeConversionNames = true;
      break;
    }
  }

  // Sort the names into a stable order.
  llvm::sort(Names);

  if (IncludeConstructorNames || IncludeConversionNames) {
    // We need to establish an ordering of constructor and conversion function
    // names, and they don't have an intrinsic ordering. We also need to write
    // out all constructor and conversion function results if we write out any
    // of them, because they're all tracked under the same lookup key.
    llvm::SmallPtrSet<DeclarationName, 8> AddedNames;
    for (Decl *ChildD : cast<CXXRecordDecl>(DC)->decls()) {
      if (auto *ChildND = dyn_cast<NamedDecl>(ChildD)) {
        auto Name = ChildND->getDeclName();
        switch (Name.getNameKind()) {
        default:
          continue;

        case DeclarationName::CXXConstructorName:
          if (!IncludeConstructorNames)
            continue;
          break;

        case DeclarationName::CXXConversionFunctionName:
          if (!IncludeConversionNames)
            continue;
          break;
        }
        if (AddedNames.insert(Name).second)
          Names.push_back(Name);
      }
    }
  }
  // Next we need to do a lookup with each name into this decl context to fully
  // populate any results from external sources. We don't actually use the
  // results of these lookups because we only want to use the results after all
  // results have been loaded and the pointers into them will be stable.
  for (auto &Name : Names)
    DC->lookup(Name);

  // Now we need to insert the results for each name into the hash table. For
  // constructor names and conversion function names, we actually need to merge
  // all of the results for them into one list of results each and insert
  // those.
  SmallVector<NamedDecl *, 8> ConstructorDecls;
  SmallVector<NamedDecl *, 8> ConversionDecls;

  // Now loop over the names, either inserting them or appending for the two
  // special cases.
  for (auto &Name : Names) {
    DeclContext::lookup_result Result = DC->noload_lookup(Name);

    switch (Name.getNameKind()) {
    default:
      Generator.insert(Name, Trait.getData(Result), Trait);
      break;

    case DeclarationName::CXXConstructorName:
      ConstructorDecls.append(Result.begin(), Result.end());
      break;

    case DeclarationName::CXXConversionFunctionName:
      ConversionDecls.append(Result.begin(), Result.end());
      break;
    }
  }

  // Handle our two special cases if we ended up having any. We arbitrarily use
  // the first declaration's name here because the name itself isn't part of
  // the key, only the kind of name is used.
  if (!ConstructorDecls.empty())
    Generator.insert(ConstructorDecls.front()->getDeclName(),
                     Trait.getData(ConstructorDecls), Trait);
  if (!ConversionDecls.empty())
    Generator.insert(ConversionDecls.front()->getDeclName(),
                     Trait.getData(ConversionDecls), Trait);

  // Create the on-disk hash table. Also emit the existing imported and
  // merged table if there is one.
  auto *Lookups = Chain ? Chain->getLoadedLookupTables(DC) : nullptr;
  // Reduced BMI may not emit everything in the lookup table,
  // If Reduced BMI **partially** emits some decls,
  // then the generator may not emit the corresponding entry for the
  // corresponding name is already there. See
  // MultiOnDiskHashTableGenerator::insert and
  // MultiOnDiskHashTableGenerator::emit for details.
  // So we won't emit the lookup table if we're generating reduced BMI.
  auto *ToEmitMaybeMergedLookupTable =
      (!isGeneratingReducedBMI() && Lookups) ? &Lookups->Table : nullptr;
  Generator.emit(LookupTable, Trait, ToEmitMaybeMergedLookupTable);

  const auto &ModuleLocalDecls = Trait.getModuleLocalDecls();
  if (!ModuleLocalDecls.empty()) {
    MultiOnDiskHashTableGenerator<reader::ModuleLocalNameLookupTrait,
                                  ModuleLevelNameLookupTrait>
        ModuleLocalLookupGenerator;
    ModuleLevelNameLookupTrait ModuleLocalTrait(*this);

    for (const auto &ModuleLocalIter : ModuleLocalDecls) {
      const auto &Key = ModuleLocalIter.first;
      const auto &IDs = ModuleLocalIter.second;
      ModuleLocalLookupGenerator.insert(Key, ModuleLocalTrait.getData(IDs),
                                        ModuleLocalTrait);
    }

    // See the above comment. We won't emit the merged table if we're generating
    // reduced BMI.
    auto *ModuleLocalLookups =
        (isGeneratingReducedBMI() && Chain &&
         Chain->getModuleLocalLookupTables(DC))
            ? &Chain->getModuleLocalLookupTables(DC)->Table
            : nullptr;
    ModuleLocalLookupGenerator.emit(ModuleLocalLookupTable, ModuleLocalTrait,
                                    ModuleLocalLookups);
  }

  const auto &TULocalDecls = Trait.getTULocalDecls();
  if (!TULocalDecls.empty() && !isGeneratingReducedBMI()) {
    MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait,
                                  ASTDeclContextNameTrivialLookupTrait>
        TULookupGenerator;
    ASTDeclContextNameTrivialLookupTrait TULocalTrait(*this);

    for (const auto &TULocalIter : TULocalDecls) {
      const auto &Key = TULocalIter.first;
      const auto &IDs = TULocalIter.second;
      TULookupGenerator.insert(Key, TULocalTrait.getData(IDs), TULocalTrait);
    }

    // See the above comment. We won't emit the merged table if we're generating
    // reduced BMI.
    auto *TULocalLookups =
        (isGeneratingReducedBMI() && Chain && Chain->getTULocalLookupTables(DC))
            ? &Chain->getTULocalLookupTables(DC)->Table
            : nullptr;
    TULookupGenerator.emit(TULookupTable, TULocalTrait, TULocalLookups);
  }
}

/// Write the block containing all of the declaration IDs
/// visible from the given DeclContext.
///
/// \returns the offset of the DECL_CONTEXT_VISIBLE block within the
/// bitstream, or 0 if no block was written.
void ASTWriter::WriteDeclContextVisibleBlock(
    ASTContext &Context, DeclContext *DC, VisibleLookupBlockOffsets &Offsets) {
  assert(!Offsets);

  // If we imported a key declaration of this namespace, write the visible
  // lookup results as an update record for it rather than including them
  // on this declaration. We will only look at key declarations on reload.
  if (isa<NamespaceDecl>(DC) && Chain &&
      Chain->getKeyDeclaration(cast<Decl>(DC))->isFromASTFile()) {
    // Only do this once, for the first local declaration of the namespace.
    for (auto *Prev = cast<NamespaceDecl>(DC)->getPreviousDecl(); Prev;
         Prev = Prev->getPreviousDecl())
      if (!Prev->isFromASTFile())
        return;

    // Note that we need to emit an update record for the primary context.
    UpdatedDeclContexts.insert(DC->getPrimaryContext());

    // Make sure all visible decls are written. They will be recorded later. We
    // do this using a side data structure so we can sort the names into
    // a deterministic order.
    StoredDeclsMap *Map = DC->getPrimaryContext()->buildLookup();
    SmallVector<std::pair<DeclarationName, DeclContext::lookup_result>, 16>
        LookupResults;
    if (Map) {
      LookupResults.reserve(Map->size());
      for (auto &Entry : *Map)
        LookupResults.push_back(
            std::make_pair(Entry.first, Entry.second.getLookupResult()));
    }

    llvm::sort(LookupResults, llvm::less_first());
    for (auto &NameAndResult : LookupResults) {
      DeclarationName Name = NameAndResult.first;
      DeclContext::lookup_result Result = NameAndResult.second;
      if (Name.getNameKind() == DeclarationName::CXXConstructorName ||
          Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
        // We have to work around a name lookup bug here where negative lookup
        // results for these names get cached in namespace lookup tables (these
        // names should never be looked up in a namespace).
        assert(Result.empty() && "Cannot have a constructor or conversion "
                                 "function name in a namespace!");
        continue;
      }

      for (NamedDecl *ND : Result) {
        if (ND->isFromASTFile())
          continue;

        if (DoneWritingDeclsAndTypes && !wasDeclEmitted(ND))
          continue;

        // We don't need to force emitting internal decls into reduced BMI.
        // See comments in ASTWriter::WriteDeclContextLexicalBlock for details.
        if (GeneratingReducedBMI && !ND->isFromExplicitGlobalModule() &&
            IsInternalDeclFromFileContext(ND))
          continue;

        GetDeclRef(ND);
      }
    }

    return;
  }

  if (DC->getPrimaryContext() != DC)
    return;

  // Skip contexts which don't support name lookup.
  if (!DC->isLookupContext())
    return;

  // If not in C++, we perform name lookup for the translation unit via the
  // IdentifierInfo chains, don't bother to build a visible-declarations table.
  if (DC->isTranslationUnit() && !Context.getLangOpts().CPlusPlus)
    return;

  // Serialize the contents of the mapping used for lookup. Note that,
  // although we have two very different code paths, the serialized
  // representation is the same for both cases: a declaration name,
  // followed by a size, followed by references to the visible
  // declarations that have that name.
  StoredDeclsMap *Map = DC->buildLookup();
  if (!Map || Map->empty())
    return;

  Offsets.VisibleOffset = Stream.GetCurrentBitNo();
  // Create the on-disk hash table in a buffer.
  SmallString<4096> LookupTable;
  SmallString<4096> ModuleLocalLookupTable;
  SmallString<4096> TULookupTable;
  GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable,
                          TULookupTable);

  // Write the lookup table
  RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE};
  Stream.EmitRecordWithBlob(DeclContextVisibleLookupAbbrev, Record,
                            LookupTable);
  ++NumVisibleDeclContexts;

  if (!ModuleLocalLookupTable.empty()) {
    Offsets.ModuleLocalOffset = Stream.GetCurrentBitNo();
    assert(Offsets.ModuleLocalOffset > Offsets.VisibleOffset);
    // Write the lookup table
    RecordData::value_type ModuleLocalRecord[] = {
        DECL_CONTEXT_MODULE_LOCAL_VISIBLE};
    Stream.EmitRecordWithBlob(DeclModuleLocalVisibleLookupAbbrev,
                              ModuleLocalRecord, ModuleLocalLookupTable);
    ++NumModuleLocalDeclContexts;
  }

  if (!TULookupTable.empty()) {
    Offsets.TULocalOffset = Stream.GetCurrentBitNo();
    // Write the lookup table
    RecordData::value_type TULocalDeclsRecord[] = {
        DECL_CONTEXT_TU_LOCAL_VISIBLE};
    Stream.EmitRecordWithBlob(DeclTULocalLookupAbbrev, TULocalDeclsRecord,
                              TULookupTable);
    ++NumTULocalDeclContexts;
  }
}

/// Write an UPDATE_VISIBLE block for the given context.
///
/// UPDATE_VISIBLE blocks contain the declarations that are added to an existing
/// DeclContext in a dependent AST file. As such, they only exist for the TU
/// (in C++), for namespaces, and for classes with forward-declared unscoped
/// enumeration members (in C++11).
void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context,
                                              const DeclContext *DC) {
  StoredDeclsMap *Map = DC->getLookupPtr();
  if (!Map || Map->empty())
    return;

  // Create the on-disk hash table in a buffer.
  SmallString<4096> LookupTable;
  SmallString<4096> ModuleLocalLookupTable;
  SmallString<4096> TULookupTable;
  GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable,
                          TULookupTable);

  // If we're updating a namespace, select a key declaration as the key for the
  // update record; those are the only ones that will be checked on reload.
  if (isa<NamespaceDecl>(DC))
    DC = cast<DeclContext>(Chain->getKeyDeclaration(cast<Decl>(DC)));

  // Write the lookup table
  RecordData::value_type Record[] = {UPDATE_VISIBLE,
                                     getDeclID(cast<Decl>(DC)).getRawValue()};
  Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable);

  if (!ModuleLocalLookupTable.empty()) {
    // Write the module local lookup table
    RecordData::value_type ModuleLocalRecord[] = {
        UPDATE_MODULE_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()};
    Stream.EmitRecordWithBlob(ModuleLocalUpdateVisibleAbbrev, ModuleLocalRecord,
                              ModuleLocalLookupTable);
  }

  if (!TULookupTable.empty()) {
    RecordData::value_type GMFRecord[] = {
        UPDATE_TU_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()};
    Stream.EmitRecordWithBlob(TULocalUpdateVisibleAbbrev, GMFRecord,
                              TULookupTable);
  }
}

/// Write an FP_PRAGMA_OPTIONS block for the given FPOptions.
void ASTWriter::WriteFPPragmaOptions(const FPOptionsOverride &Opts) {
  RecordData::value_type Record[] = {Opts.getAsOpaqueInt()};
  Stream.EmitRecord(FP_PRAGMA_OPTIONS, Record);
}

/// Write an OPENCL_EXTENSIONS block for the given OpenCLOptions.
void ASTWriter::WriteOpenCLExtensions(Sema &SemaRef) {
  if (!SemaRef.Context.getLangOpts().OpenCL)
    return;

  const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
  RecordData Record;
  for (const auto &I:Opts.OptMap) {
    AddString(I.getKey(), Record);
    auto V = I.getValue();
    Record.push_back(V.Supported ? 1 : 0);
    Record.push_back(V.Enabled ? 1 : 0);
    Record.push_back(V.WithPragma ? 1 : 0);
    Record.push_back(V.Avail);
    Record.push_back(V.Core);
    Record.push_back(V.Opt);
  }
  Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
}
void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
  if (SemaRef.CUDA().ForceHostDeviceDepth > 0) {
    RecordData::value_type Record[] = {SemaRef.CUDA().ForceHostDeviceDepth};
    Stream.EmitRecord(CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH, Record);
  }
}

void ASTWriter::WriteObjCCategories() {
  if (ObjCClassesWithCategories.empty())
    return;

  SmallVector<ObjCCategoriesInfo, 2> CategoriesMap;
  RecordData Categories;

  for (unsigned I = 0, N = ObjCClassesWithCategories.size(); I != N; ++I) {
    unsigned Size = 0;
    unsigned StartIndex = Categories.size();

    ObjCInterfaceDecl *Class = ObjCClassesWithCategories[I];

    // Allocate space for the size.
    Categories.push_back(0);

    // Add the categories.
    for (ObjCInterfaceDecl::known_categories_iterator
           Cat = Class->known_categories_begin(),
           CatEnd = Class->known_categories_end();
         Cat != CatEnd; ++Cat, ++Size) {
      assert(getDeclID(*Cat).isValid() && "Bogus category");
      AddDeclRef(*Cat, Categories);
    }

    // Update the size.
    Categories[StartIndex] = Size;

    // Record this interface -> category map.
    ObjCCategoriesInfo CatInfo = { getDeclID(Class), StartIndex };
    CategoriesMap.push_back(CatInfo);
  }

  // Sort the categories map by the definition ID, since the reader will be
  // performing binary searches on this information.
  llvm::array_pod_sort(CategoriesMap.begin(), CategoriesMap.end());

  // Emit the categories map.
  using namespace llvm;

  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(OBJC_CATEGORIES_MAP));
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of entries
  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  unsigned AbbrevID = Stream.EmitAbbrev(std::move(Abbrev));

  RecordData::value_type Record[] = {OBJC_CATEGORIES_MAP, CategoriesMap.size()};
  Stream.EmitRecordWithBlob(AbbrevID, Record,
                            reinterpret_cast<char *>(CategoriesMap.data()),
                            CategoriesMap.size() * sizeof(ObjCCategoriesInfo));

  // Emit the category lists.
  Stream.EmitRecord(OBJC_CATEGORIES, Categories);
}

void ASTWriter::WriteLateParsedTemplates(Sema &SemaRef) {
  Sema::LateParsedTemplateMapT &LPTMap = SemaRef.LateParsedTemplateMap;

  if (LPTMap.empty())
    return;

  RecordData Record;
  for (auto &LPTMapEntry : LPTMap) {
    const FunctionDecl *FD = LPTMapEntry.first;
    LateParsedTemplate &LPT = *LPTMapEntry.second;
    AddDeclRef(FD, Record);
    AddDeclRef(LPT.D, Record);
    Record.push_back(LPT.FPO.getAsOpaqueInt());
    Record.push_back(LPT.Toks.size());

    for (const auto &Tok : LPT.Toks) {
      AddToken(Tok, Record);
    }
  }
  Stream.EmitRecord(LATE_PARSED_TEMPLATE, Record);
}

/// Write the state of 'pragma clang optimize' at the end of the module.
void ASTWriter::WriteOptimizePragmaOptions(Sema &SemaRef) {
  RecordData Record;
  SourceLocation PragmaLoc = SemaRef.getOptimizeOffPragmaLocation();
  AddSourceLocation(PragmaLoc, Record);
  Stream.EmitRecord(OPTIMIZE_PRAGMA_OPTIONS, Record);
}

/// Write the state of 'pragma ms_struct' at the end of the module.
void ASTWriter::WriteMSStructPragmaOptions(Sema &SemaRef) {
  RecordData Record;
  Record.push_back(SemaRef.MSStructPragmaOn ? PMSST_ON : PMSST_OFF);
  Stream.EmitRecord(MSSTRUCT_PRAGMA_OPTIONS, Record);
}

/// Write the state of 'pragma pointers_to_members' at the end of the
//module.
void ASTWriter::WriteMSPointersToMembersPragmaOptions(Sema &SemaRef) {
  RecordData Record;
  Record.push_back(SemaRef.MSPointerToMemberRepresentationMethod);
  AddSourceLocation(SemaRef.ImplicitMSInheritanceAttrLoc, Record);
  Stream.EmitRecord(POINTERS_TO_MEMBERS_PRAGMA_OPTIONS, Record);
}

/// Write the state of 'pragma align/pack' at the end of the module.
void ASTWriter::WritePackPragmaOptions(Sema &SemaRef) {
  // Don't serialize pragma align/pack state for modules, since it should only
  // take effect on a per-submodule basis.
  if (WritingModule)
    return;

  RecordData Record;
  AddAlignPackInfo(SemaRef.AlignPackStack.CurrentValue, Record);
  AddSourceLocation(SemaRef.AlignPackStack.CurrentPragmaLocation, Record);
  Record.push_back(SemaRef.AlignPackStack.Stack.size());
  for (const auto &StackEntry : SemaRef.AlignPackStack.Stack) {
    AddAlignPackInfo(StackEntry.Value, Record);
    AddSourceLocation(StackEntry.PragmaLocation, Record);
    AddSourceLocation(StackEntry.PragmaPushLocation, Record);
    AddString(StackEntry.StackSlotLabel, Record);
  }
  Stream.EmitRecord(ALIGN_PACK_PRAGMA_OPTIONS, Record);
}

/// Write the state of 'pragma float_control' at the end of the module.
void ASTWriter::WriteFloatControlPragmaOptions(Sema &SemaRef) {
  // Don't serialize pragma float_control state for modules,
  // since it should only take effect on a per-submodule basis.
  if (WritingModule)
    return;

  RecordData Record;
  Record.push_back(SemaRef.FpPragmaStack.CurrentValue.getAsOpaqueInt());
  AddSourceLocation(SemaRef.FpPragmaStack.CurrentPragmaLocation, Record);
  Record.push_back(SemaRef.FpPragmaStack.Stack.size());
  for (const auto &StackEntry : SemaRef.FpPragmaStack.Stack) {
    Record.push_back(StackEntry.Value.getAsOpaqueInt());
    AddSourceLocation(StackEntry.PragmaLocation, Record);
    AddSourceLocation(StackEntry.PragmaPushLocation, Record);
    AddString(StackEntry.StackSlotLabel, Record);
  }
  Stream.EmitRecord(FLOAT_CONTROL_PRAGMA_OPTIONS, Record);
}

/// Write Sema's collected list of declarations with unverified effects.
void ASTWriter::WriteDeclsWithEffectsToVerify(Sema &SemaRef) {
  if (SemaRef.DeclsWithEffectsToVerify.empty())
    return;
  RecordData Record;
  for (const auto *D : SemaRef.DeclsWithEffectsToVerify) {
    AddDeclRef(D, Record);
  }
  Stream.EmitRecord(DECLS_WITH_EFFECTS_TO_VERIFY, Record);
}

void ASTWriter::WriteModuleFileExtension(Sema &SemaRef,
                                         ModuleFileExtensionWriter &Writer) {
  // Enter the extension block.
  Stream.EnterSubblock(EXTENSION_BLOCK_ID, 4);

  // Emit the metadata record abbreviation.
  auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(EXTENSION_METADATA));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  unsigned Abbrev = Stream.EmitAbbrev(std::move(Abv));

  // Emit the metadata record.
  RecordData Record;
  auto Metadata = Writer.getExtension()->getExtensionMetadata();
  Record.push_back(EXTENSION_METADATA);
  Record.push_back(Metadata.MajorVersion);
  Record.push_back(Metadata.MinorVersion);
  Record.push_back(Metadata.BlockName.size());
  Record.push_back(Metadata.UserInfo.size());
  SmallString<64> Buffer;
  Buffer += Metadata.BlockName;
  Buffer += Metadata.UserInfo;
  Stream.EmitRecordWithBlob(Abbrev, Record, Buffer);

  // Emit the contents of the extension block.
  Writer.writeExtensionContents(SemaRef, Stream);

  // Exit the extension block.
  Stream.ExitBlock();
}

void ASTWriter::WriteRISCVIntrinsicPragmas(Sema &SemaRef) {
  RecordData Record;
  // Need to update this when new intrinsic class is added.
  Record.push_back(/*size*/ 3);
  Record.push_back(SemaRef.RISCV().DeclareRVVBuiltins);
  Record.push_back(SemaRef.RISCV().DeclareSiFiveVectorBuiltins);
  Record.push_back(SemaRef.RISCV().DeclareAndesVectorBuiltins);
  Stream.EmitRecord(RISCV_VECTOR_INTRINSICS_PRAGMA, Record);
}

//===----------------------------------------------------------------------===//
// General Serialization Routines
//===----------------------------------------------------------------------===//

void ASTRecordWriter::AddAttr(const Attr *A) {
  auto &Record = *this;
  // FIXME: Clang can't handle the serialization/deserialization of
  // preferred_name properly now. See
  // https://github.com/llvm/llvm-project/issues/56490 for example.
  if (!A ||
      (isa<PreferredNameAttr>(A) && (Writer->isWritingStdCXXNamedModules() ||
                                     Writer->isWritingStdCXXHeaderUnit())))
    return Record.push_back(0);

  Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs

  Record.AddIdentifierRef(A->getAttrName());
  Record.AddIdentifierRef(A->getScopeName());
  Record.AddSourceRange(A->getRange());
  Record.AddSourceLocation(A->getScopeLoc());
  Record.push_back(A->getParsedKind());
  Record.push_back(A->getSyntax());
  Record.push_back(A->getAttributeSpellingListIndexRaw());
  Record.push_back(A->isRegularKeywordAttribute());

#include "clang/Serialization/AttrPCHWrite.inc"
}

/// Emit the list of attributes to the specified record.
void ASTRecordWriter::AddAttributes(ArrayRef<const Attr *> Attrs) {
  push_back(Attrs.size());
  for (const auto *A : Attrs)
    AddAttr(A);
}

void ASTWriter::AddToken(const Token &Tok, RecordDataImpl &Record) {
  AddSourceLocation(Tok.getLocation(), Record);
  // FIXME: Should translate token kind to a stable encoding.
  Record.push_back(Tok.getKind());
  // FIXME: Should translate token flags to a stable encoding.
  Record.push_back(Tok.getFlags());

  if (Tok.isAnnotation()) {
    AddSourceLocation(Tok.getAnnotationEndLoc(), Record);
    switch (Tok.getKind()) {
    case tok::annot_pragma_loop_hint: {
      auto *Info = static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
      AddToken(Info->PragmaName, Record);
      AddToken(Info->Option, Record);
      Record.push_back(Info->Toks.size());
      for (const auto &T : Info->Toks)
        AddToken(T, Record);
      break;
    }
    case tok::annot_pragma_pack: {
      auto *Info =
          static_cast<Sema::PragmaPackInfo *>(Tok.getAnnotationValue());
      Record.push_back(static_cast<unsigned>(Info->Action));
      AddString(Info->SlotLabel, Record);
      AddToken(Info->Alignment, Record);
      break;
    }
    // Some annotation tokens do not use the PtrData field.
    case tok::annot_pragma_openmp:
    case tok::annot_pragma_openmp_end:
    case tok::annot_pragma_unused:
    case tok::annot_pragma_openacc:
    case tok::annot_pragma_openacc_end:
    case tok::annot_repl_input_end:
      break;
    default:
      llvm_unreachable("missing serialization code for annotation token");
    }
  } else {
    Record.push_back(Tok.getLength());
    // FIXME: When reading literal tokens, reconstruct the literal pointer if it
    // is needed.
    AddIdentifierRef(Tok.getIdentifierInfo(), Record);
  }
}

void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {
  Record.push_back(Str.size());
  llvm::append_range(Record, Str);
}

void ASTWriter::AddStringBlob(StringRef Str, RecordDataImpl &Record,
                              SmallVectorImpl<char> &Blob) {
  Record.push_back(Str.size());
  llvm::append_range(Blob, Str);
}

bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
  assert(WritingAST && "can't prepare path for output when not writing AST");

  // Leave special file names as they are.
  StringRef PathStr(Path.data(), Path.size());
  if (PathStr == "<built-in>" || PathStr == "<command line>")
    return false;

  bool Changed =
      PP->getFileManager().makeAbsolutePath(Path, /*Canonicalize=*/true);
  // Remove a prefix to make the path relative, if relevant.
  const char *PathBegin = Path.data();
  const char *PathPtr =
      adjustFilenameForRelocatableAST(PathBegin, BaseDirectory);
  if (PathPtr != PathBegin) {
    Path.erase(Path.begin(), Path.begin() + (PathPtr - PathBegin));
    Changed = true;
  }

  return Changed;
}

void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {
  SmallString<128> FilePath(Path);
  PreparePathForOutput(FilePath);
  AddString(FilePath, Record);
}

void ASTWriter::AddPathBlob(StringRef Path, RecordDataImpl &Record,
                            SmallVectorImpl<char> &Blob) {
  SmallString<128> FilePath(Path);
  PreparePathForOutput(FilePath);
  AddStringBlob(FilePath, Record, Blob);
}

void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
                                   StringRef Path) {
  SmallString<128> FilePath(Path);
  PreparePathForOutput(FilePath);
  Stream.EmitRecordWithBlob(Abbrev, Record, FilePath);
}

void ASTWriter::AddVersionTuple(const VersionTuple &Version,
                                RecordDataImpl &Record) {
  Record.push_back(Version.getMajor());
  if (std::optional<unsigned> Minor = Version.getMinor())
    Record.push_back(*Minor + 1);
  else
    Record.push_back(0);
  if (std::optional<unsigned> Subminor = Version.getSubminor())
    Record.push_back(*Subminor + 1);
  else
    Record.push_back(0);
}

/// Note that the identifier II occurs at the given offset
/// within the identifier table.
void ASTWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) {
  IdentifierID ID = IdentifierIDs[II];
  // Only store offsets new to this AST file. Other identifier names are looked
  // up earlier in the chain and thus don't need an offset.
  if (!isLocalIdentifierID(ID))
    return;

  // For local identifiers, the module file index must be 0.

  assert(ID != 0);
  ID -= NUM_PREDEF_IDENT_IDS;
  assert(ID < IdentifierOffsets.size());
  IdentifierOffsets[ID] = Offset;
}

/// Note that the selector Sel occurs at the given offset
/// within the method pool/selector table.
void ASTWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) {
  unsigned ID = SelectorIDs[Sel];
  assert(ID && "Unknown selector");
  // Don't record offsets for selectors that are also available in a different
  // file.
  if (ID < FirstSelectorID)
    return;
  SelectorOffsets[ID - FirstSelectorID] = Offset;
}

ASTWriter::ASTWriter(llvm::BitstreamWriter &Stream,
                     SmallVectorImpl<char> &Buffer, ModuleCache &ModCache,
                     const CodeGenOptions &CodeGenOpts,
                     ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
                     bool IncludeTimestamps, bool BuildingImplicitModule,
                     bool GeneratingReducedBMI)
    : Stream(Stream), Buffer(Buffer), ModCache(ModCache),
      CodeGenOpts(CodeGenOpts), IncludeTimestamps(IncludeTimestamps),
      BuildingImplicitModule(BuildingImplicitModule),
      GeneratingReducedBMI(GeneratingReducedBMI) {
  for (const auto &Ext : Extensions) {
    if (auto Writer = Ext->createExtensionWriter(*this))
      ModuleFileExtensionWriters.push_back(std::move(Writer));
  }
}

ASTWriter::~ASTWriter() = default;

const LangOptions &ASTWriter::getLangOpts() const {
  assert(WritingAST && "can't determine lang opts when not writing AST");
  return PP->getLangOpts();
}

time_t ASTWriter::getTimestampForOutput(time_t ModTime) const {
  return IncludeTimestamps ? ModTime : 0;
}

ASTFileSignature
ASTWriter::WriteAST(llvm::PointerUnion<Sema *, Preprocessor *> Subject,
                    StringRef OutputFile, Module *WritingModule,
                    StringRef isysroot) {
  llvm::TimeTraceScope scope("WriteAST", OutputFile);
  WritingAST = true;

  Sema *SemaPtr = dyn_cast<Sema *>(Subject);
  Preprocessor &PPRef =
      SemaPtr ? SemaPtr->getPreprocessor() : *cast<Preprocessor *>(Subject);

  ASTHasCompilerErrors = PPRef.getDiagnostics().hasUncompilableErrorOccurred();

  // Emit the file header.
  Stream.Emit((unsigned)'C', 8);
  Stream.Emit((unsigned)'P', 8);
  Stream.Emit((unsigned)'C', 8);
  Stream.Emit((unsigned)'H', 8);

  WriteBlockInfoBlock();

  PP = &PPRef;
  this->WritingModule = WritingModule;
  ASTFileSignature Signature = WriteASTCore(SemaPtr, isysroot, WritingModule);
  PP = nullptr;
  this->WritingModule = nullptr;
  this->BaseDirectory.clear();

  WritingAST = false;

  return Signature;
}

template<typename Vector>
static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) {
  for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();
       I != E; ++I) {
    Writer.GetDeclRef(*I);
  }
}

template <typename Vector>
static void AddLazyVectorEmiitedDecls(ASTWriter &Writer, Vector &Vec,
                                      ASTWriter::RecordData &Record) {
  for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end();
       I != E; ++I) {
    Writer.AddEmittedDeclRef(*I, Record);
  }
}

void ASTWriter::computeNonAffectingInputFiles() {
  SourceManager &SrcMgr = PP->getSourceManager();
  unsigned N = SrcMgr.local_sloc_entry_size();

  IsSLocAffecting.resize(N, true);
  IsSLocFileEntryAffecting.resize(N, true);

  if (!WritingModule)
    return;

  auto AffectingModuleMaps = GetAffectingModuleMaps(*PP, WritingModule);

  unsigned FileIDAdjustment = 0;
  unsigned OffsetAdjustment = 0;

  NonAffectingFileIDAdjustments.reserve(N);
  NonAffectingOffsetAdjustments.reserve(N);

  NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);
  NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);

  for (unsigned I = 1; I != N; ++I) {
    const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);
    FileID FID = FileID::get(I);
    assert(&SrcMgr.getSLocEntry(FID) == SLoc);

    if (!SLoc->isFile())
      continue;
    const SrcMgr::FileInfo &File = SLoc->getFile();
    const SrcMgr::ContentCache *Cache = &File.getContentCache();
    if (!Cache->OrigEntry)
      continue;

    // Don't prune anything other than module maps.
    if (!isModuleMap(File.getFileCharacteristic()))
      continue;

    // Don't prune module maps if all are guaranteed to be affecting.
    if (!AffectingModuleMaps)
      continue;

    // Don't prune module maps that are affecting.
    if (AffectingModuleMaps->DefinitionFileIDs.contains(FID))
      continue;

    IsSLocAffecting[I] = false;
    IsSLocFileEntryAffecting[I] =
        AffectingModuleMaps->DefinitionFiles.contains(*Cache->OrigEntry);

    FileIDAdjustment += 1;
    // Even empty files take up one element in the offset table.
    OffsetAdjustment += SrcMgr.getFileIDSize(FID) + 1;

    // If the previous file was non-affecting as well, just extend its entry
    // with our information.
    if (!NonAffectingFileIDs.empty() &&
        NonAffectingFileIDs.back().ID == FID.ID - 1) {
      NonAffectingFileIDs.back() = FID;
      NonAffectingRanges.back().setEnd(SrcMgr.getLocForEndOfFile(FID));
      NonAffectingFileIDAdjustments.back() = FileIDAdjustment;
      NonAffectingOffsetAdjustments.back() = OffsetAdjustment;
      continue;
    }

    NonAffectingFileIDs.push_back(FID);
    NonAffectingRanges.emplace_back(SrcMgr.getLocForStartOfFile(FID),
                                    SrcMgr.getLocForEndOfFile(FID));
    NonAffectingFileIDAdjustments.push_back(FileIDAdjustment);
    NonAffectingOffsetAdjustments.push_back(OffsetAdjustment);
  }

  if (!PP->getHeaderSearchInfo().getHeaderSearchOpts().ModulesIncludeVFSUsage)
    return;

  FileManager &FileMgr = PP->getFileManager();
  FileMgr.trackVFSUsage(true);
  // Lookup the paths in the VFS to trigger `-ivfsoverlay` usage tracking.
  for (StringRef Path :
       PP->getHeaderSearchInfo().getHeaderSearchOpts().VFSOverlayFiles)
    FileMgr.getVirtualFileSystem().exists(Path);
  for (unsigned I = 1; I != N; ++I) {
    if (IsSLocAffecting[I]) {
      const SrcMgr::SLocEntry *SLoc = &SrcMgr.getLocalSLocEntry(I);
      if (!SLoc->isFile())
        continue;
      const SrcMgr::FileInfo &File = SLoc->getFile();
      const SrcMgr::ContentCache *Cache = &File.getContentCache();
      if (!Cache->OrigEntry)
        continue;
      FileMgr.getVirtualFileSystem().exists(
          Cache->OrigEntry->getNameAsRequested());
    }
  }
  FileMgr.trackVFSUsage(false);
}

void ASTWriter::prepareLazyUpdates() {
  // In C++20 named modules with reduced BMI, we only apply the update
  // if these updates are touched.
  if (!GeneratingReducedBMI)
    return;

  DeclUpdateMap DeclUpdatesTmp;
  // Move updates to DeclUpdatesLazy but leave CXXAddedFunctionDefinition as is.
  // Since added function definition is critical to the AST. If we don't take
  // care of it, user might meet missing definition error at linking time.
  // Here we leave all CXXAddedFunctionDefinition unconditionally to avoid
  // potential issues.
  // TODO: Try to refine the strategy to handle CXXAddedFunctionDefinition
  // precisely.
  for (auto &DeclUpdate : DeclUpdates) {
    const Decl *D = DeclUpdate.first;

    for (auto &Update : DeclUpdate.second) {
      DeclUpdateKind Kind = Update.getKind();

      if (Kind == DeclUpdateKind::CXXAddedFunctionDefinition)
        DeclUpdatesTmp[D].push_back(
            ASTWriter::DeclUpdate(DeclUpdateKind::CXXAddedFunctionDefinition));
      else
        DeclUpdatesLazy[D].push_back(Update);
    }
  }
  DeclUpdates.swap(DeclUpdatesTmp);

  UpdatedDeclContextsLazy.swap(UpdatedDeclContexts);
  // In reduced BMI, we don't have decls have to emit even if unreferenced.
  DeclsToEmitEvenIfUnreferenced.clear();
}

void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) {
  ASTContext &Context = SemaRef.Context;

  bool isModule = WritingModule != nullptr;

  prepareLazyUpdates();

  // Set up predefined declaration IDs.
  auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) {
    if (D) {
      assert(D->isCanonicalDecl() && "predefined decl is not canonical");
      DeclIDs[D] = ID;
      PredefinedDecls.insert(D);
    }
  };
  RegisterPredefDecl(Context.getTranslationUnitDecl(),
                     PREDEF_DECL_TRANSLATION_UNIT_ID);
  RegisterPredefDecl(Context.ObjCIdDecl, PREDEF_DECL_OBJC_ID_ID);
  RegisterPredefDecl(Context.ObjCSelDecl, PREDEF_DECL_OBJC_SEL_ID);
  RegisterPredefDecl(Context.ObjCClassDecl, PREDEF_DECL_OBJC_CLASS_ID);
  RegisterPredefDecl(Context.ObjCProtocolClassDecl,
                     PREDEF_DECL_OBJC_PROTOCOL_ID);
  RegisterPredefDecl(Context.Int128Decl, PREDEF_DECL_INT_128_ID);
  RegisterPredefDecl(Context.UInt128Decl, PREDEF_DECL_UNSIGNED_INT_128_ID);
  RegisterPredefDecl(Context.ObjCInstanceTypeDecl,
                     PREDEF_DECL_OBJC_INSTANCETYPE_ID);
  RegisterPredefDecl(Context.BuiltinVaListDecl, PREDEF_DECL_BUILTIN_VA_LIST_ID);
  RegisterPredefDecl(Context.VaListTagDecl, PREDEF_DECL_VA_LIST_TAG);
  RegisterPredefDecl(Context.BuiltinMSVaListDecl,
                     PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
  RegisterPredefDecl(Context.BuiltinZOSVaListDecl,
                     PREDEF_DECL_BUILTIN_ZOS_VA_LIST_ID);
  RegisterPredefDecl(Context.MSGuidTagDecl,
                     PREDEF_DECL_BUILTIN_MS_GUID_ID);
  RegisterPredefDecl(Context.MSTypeInfoTagDecl,
                     PREDEF_DECL_BUILTIN_MS_TYPE_INFO_TAG_ID);
  RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID);
  RegisterPredefDecl(Context.CFConstantStringTypeDecl,
                     PREDEF_DECL_CF_CONSTANT_STRING_ID);
  RegisterPredefDecl(Context.CFConstantStringTagDecl,
                     PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID);
#define BuiltinTemplate(BTName)                                                \
  RegisterPredefDecl(Context.Decl##BTName, PREDEF_DECL##BTName##_ID);
#include "clang/Basic/BuiltinTemplates.inc"

  const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();

  // Force all top level declarations to be emitted.
  //
  // We start emitting top level declarations from the module purview to
  // implement the eliding unreachable declaration feature.
  for (const auto *D : TU->noload_decls()) {
    if (D->isFromASTFile())
      continue;

    if (GeneratingReducedBMI) {
      if (D->isFromExplicitGlobalModule())
        continue;

      // Don't force emitting static entities.
      //
      // Technically, all static entities shouldn't be in reduced BMI. The
      // language also specifies that the program exposes TU-local entities
      // is ill-formed. However, in practice, there are a lot of projects
      // uses `static inline` in the headers. So we can't get rid of all
      // static entities in reduced BMI now.
      if (IsInternalDeclFromFileContext(D))
        continue;
    }

    // If we're writing C++ named modules, don't emit declarations which are
    // not from modules by default. They may be built in declarations (be
    // handled above) or implcit declarations (see the implementation of
    // `Sema::Initialize()` for example).
    if (isWritingStdCXXNamedModules() && !D->getOwningModule() &&
        D->isImplicit())
      continue;

    GetDeclRef(D);
  }

  if (GeneratingReducedBMI)
    return;

  // Writing all of the tentative definitions in this file, in
  // TentativeDefinitions order.  Generally, this record will be empty for
  // headers.
  AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions);

  // Writing all of the file scoped decls in this file.
  if (!isModule)
    AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls);

  // Writing all of the delegating constructors we still need
  // to resolve.
  if (!isModule)
    AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls);

  // Writing all of the ext_vector declarations.
  AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls);

  // Writing all of the VTable uses information.
  if (!SemaRef.VTableUses.empty())
    for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I)
      GetDeclRef(SemaRef.VTableUses[I].first);

  // Writing all of the UnusedLocalTypedefNameCandidates in a deterministic
  // order.
  SmallVector<const TypedefNameDecl *, 4> UnusedLocalTypedefs;
  SemaRef.getSortedUnusedLocalTypedefNameCandidates(UnusedLocalTypedefs);
  for (const TypedefNameDecl *TD : UnusedLocalTypedefs)
    GetDeclRef(TD);

  // Writing all of pending implicit instantiations.
  for (const auto &I : SemaRef.PendingInstantiations)
    GetDeclRef(I.first);
  assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
         "There are local ones at end of translation unit!");

  // Writing some declaration references.
  if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {
    GetDeclRef(SemaRef.getStdNamespace());
    GetDeclRef(SemaRef.getStdBadAlloc());
    GetDeclRef(SemaRef.getStdAlignValT());
  }

  if (Context.getcudaConfigureCallDecl() ||
      Context.getcudaGetParameterBufferDecl() ||
      Context.getcudaLaunchDeviceDecl()) {
    GetDeclRef(Context.getcudaConfigureCallDecl());
    GetDeclRef(Context.getcudaGetParameterBufferDecl());
    GetDeclRef(Context.getcudaLaunchDeviceDecl());
  }

  // Writing all of the known namespaces.
  for (const auto &I : SemaRef.KnownNamespaces)
    if (!I.second)
      GetDeclRef(I.first);

  // Writing all used, undefined objects that require definitions.
  SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
  SemaRef.getUndefinedButUsed(Undefined);
  for (const auto &I : Undefined)
    GetDeclRef(I.first);

  // Writing all delete-expressions that we would like to
  // analyze later in AST.
  if (!isModule)
    for (const auto &DeleteExprsInfo :
         SemaRef.getMismatchingDeleteExpressions())
      GetDeclRef(DeleteExprsInfo.first);

  // Make sure visible decls, added to DeclContexts previously loaded from
  // an AST file, are registered for serialization. Likewise for template
  // specializations added to imported templates.
  for (const auto *I : DeclsToEmitEvenIfUnreferenced)
    GetDeclRef(I);
  DeclsToEmitEvenIfUnreferenced.clear();

  // Make sure all decls associated with an identifier are registered for
  // serialization, if we're storing decls with identifiers.
  if (!WritingModule || !getLangOpts().CPlusPlus) {
    llvm::SmallVector<const IdentifierInfo*, 256> IIs;
    for (const auto &ID : SemaRef.PP.getIdentifierTable()) {
      const IdentifierInfo *II = ID.second;
      if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization() ||
          II->hasFETokenInfoChangedSinceDeserialization())
        IIs.push_back(II);
    }
    // Sort the identifiers to visit based on their name.
    llvm::sort(IIs, llvm::deref<std::less<>>());
    const LangOptions &LangOpts = getLangOpts();
    for (const IdentifierInfo *II : IIs)
      for (NamedDecl *D : SemaRef.IdResolver.decls(II))
        GetDeclRef(getDeclForLocalLookup(LangOpts, D));
  }

  // Write all of the DeclsToCheckForDeferredDiags.
  for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
    GetDeclRef(D);

  // Write all classes that need to emit the vtable definitions if required.
  if (isWritingStdCXXNamedModules())
    for (CXXRecordDecl *RD : PendingEmittingVTables)
      GetDeclRef(RD);
  else
    PendingEmittingVTables.clear();
}

void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) {
  ASTContext &Context = SemaRef.Context;

  bool isModule = WritingModule != nullptr;

  // Write the record containing external, unnamed definitions.
  if (!EagerlyDeserializedDecls.empty())
    Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls);

  if (!ModularCodegenDecls.empty())
    Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls);

  // Write the record containing tentative definitions.
  RecordData TentativeDefinitions;
  AddLazyVectorEmiitedDecls(*this, SemaRef.TentativeDefinitions,
                            TentativeDefinitions);
  if (!TentativeDefinitions.empty())
    Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions);

  // Write the record containing unused file scoped decls.
  RecordData UnusedFileScopedDecls;
  if (!isModule)
    AddLazyVectorEmiitedDecls(*this, SemaRef.UnusedFileScopedDecls,
                              UnusedFileScopedDecls);
  if (!UnusedFileScopedDecls.empty())
    Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls);

  // Write the record containing ext_vector type names.
  RecordData ExtVectorDecls;
  AddLazyVectorEmiitedDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls);
  if (!ExtVectorDecls.empty())
    Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls);

  // Write the record containing VTable uses information.
  RecordData VTableUses;
  if (!SemaRef.VTableUses.empty()) {
    for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) {
      CXXRecordDecl *D = SemaRef.VTableUses[I].first;
      if (!wasDeclEmitted(D))
        continue;

      AddDeclRef(D, VTableUses);
      AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses);
      VTableUses.push_back(SemaRef.VTablesUsed[D]);
    }
    Stream.EmitRecord(VTABLE_USES, VTableUses);
  }

  // Write the record containing potentially unused local typedefs, in a
  // deterministic order.
  RecordData UnusedLocalTypedefNameCandidates;
  SmallVector<const TypedefNameDecl *, 4> SortedCandidates;
  SemaRef.getSortedUnusedLocalTypedefNameCandidates(SortedCandidates);
  for (const TypedefNameDecl *TD : SortedCandidates)
    AddEmittedDeclRef(TD, UnusedLocalTypedefNameCandidates);
  if (!UnusedLocalTypedefNameCandidates.empty())
    Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES,
                      UnusedLocalTypedefNameCandidates);

  if (!GeneratingReducedBMI) {
    // Write the record containing pending implicit instantiations.
    RecordData PendingInstantiations;
    for (const auto &I : SemaRef.PendingInstantiations) {
      if (!wasDeclEmitted(I.first))
        continue;

      AddDeclRef(I.first, PendingInstantiations);
      AddSourceLocation(I.second, PendingInstantiations);
    }
    if (!PendingInstantiations.empty())
      Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations);
  }

  auto AddEmittedDeclRefOrZero = [this](RecordData &Refs, Decl *D) {
    if (!D || !wasDeclEmitted(D))
      Refs.push_back(0);
    else
      AddDeclRef(D, Refs);
  };

  // Write the record containing declaration references of Sema.
  RecordData SemaDeclRefs;
  if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) {
    AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdNamespace());
    AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdBadAlloc());
    AddEmittedDeclRefOrZero(SemaDeclRefs, SemaRef.getStdAlignValT());
  }
  if (!SemaDeclRefs.empty())
    Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);

  // Write the record containing decls to be checked for deferred diags.
  RecordData DeclsToCheckForDeferredDiags;
  for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
    if (wasDeclEmitted(D))
      AddDeclRef(D, DeclsToCheckForDeferredDiags);
  if (!DeclsToCheckForDeferredDiags.empty())
    Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS,
        DeclsToCheckForDeferredDiags);

  // Write the record containing CUDA-specific declaration references.
  RecordData CUDASpecialDeclRefs;
  if (auto *CudaCallDecl = Context.getcudaConfigureCallDecl(),
      *CudaGetParamDecl = Context.getcudaGetParameterBufferDecl(),
      *CudaLaunchDecl = Context.getcudaLaunchDeviceDecl();
      CudaCallDecl || CudaGetParamDecl || CudaLaunchDecl) {
    AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaCallDecl);
    AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaGetParamDecl);
    AddEmittedDeclRefOrZero(CUDASpecialDeclRefs, CudaLaunchDecl);
    Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);
  }

  // Write the delegating constructors.
  RecordData DelegatingCtorDecls;
  if (!isModule)
    AddLazyVectorEmiitedDecls(*this, SemaRef.DelegatingCtorDecls,
                              DelegatingCtorDecls);
  if (!DelegatingCtorDecls.empty())
    Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);

  // Write the known namespaces.
  RecordData KnownNamespaces;
  for (const auto &I : SemaRef.KnownNamespaces) {
    if (!I.second && wasDeclEmitted(I.first))
      AddDeclRef(I.first, KnownNamespaces);
  }
  if (!KnownNamespaces.empty())
    Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);

  // Write the undefined internal functions and variables, and inline functions.
  RecordData UndefinedButUsed;
  SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined;
  SemaRef.getUndefinedButUsed(Undefined);
  for (const auto &I : Undefined) {
    if (!wasDeclEmitted(I.first))
      continue;

    AddDeclRef(I.first, UndefinedButUsed);
    AddSourceLocation(I.second, UndefinedButUsed);
  }
  if (!UndefinedButUsed.empty())
    Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed);

  // Write all delete-expressions that we would like to
  // analyze later in AST.
  RecordData DeleteExprsToAnalyze;
  if (!isModule) {
    for (const auto &DeleteExprsInfo :
         SemaRef.getMismatchingDeleteExpressions()) {
      if (!wasDeclEmitted(DeleteExprsInfo.first))
        continue;

      AddDeclRef(DeleteExprsInfo.first, DeleteExprsToAnalyze);
      DeleteExprsToAnalyze.push_back(DeleteExprsInfo.second.size());
      for (const auto &DeleteLoc : DeleteExprsInfo.second) {
        AddSourceLocation(DeleteLoc.first, DeleteExprsToAnalyze);
        DeleteExprsToAnalyze.push_back(DeleteLoc.second);
      }
    }
  }
  if (!DeleteExprsToAnalyze.empty())
    Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze);

  RecordData VTablesToEmit;
  for (CXXRecordDecl *RD : PendingEmittingVTables) {
    if (!wasDeclEmitted(RD))
      continue;

    AddDeclRef(RD, VTablesToEmit);
  }

  if (!VTablesToEmit.empty())
    Stream.EmitRecord(VTABLES_TO_EMIT, VTablesToEmit);
}

ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot,
                                         Module *WritingModule) {
  using namespace llvm;

  bool isModule = WritingModule != nullptr;

  // Make sure that the AST reader knows to finalize itself.
  if (Chain)
    Chain->finalizeForWriting();

  // This needs to be done very early, since everything that writes
  // SourceLocations or FileIDs depends on it.
  computeNonAffectingInputFiles();

  writeUnhashedControlBlock(*PP);

  // Don't reuse type ID and Identifier ID from readers for C++ standard named
  // modules since we want to support no-transitive-change model for named
  // modules. The theory for no-transitive-change model is,
  // for a user of a named module, the user can only access the indirectly
  // imported decls via the directly imported module. So that it is possible to
  // control what matters to the users when writing the module. It would be
  // problematic if the users can reuse the type IDs and identifier IDs from
  // indirectly imported modules arbitrarily. So we choose to clear these ID
  // here.
  if (isWritingStdCXXNamedModules()) {
    TypeIdxs.clear();
    IdentifierIDs.clear();
  }

  // Look for any identifiers that were named while processing the
  // headers, but are otherwise not needed. We add these to the hash
  // table to enable checking of the predefines buffer in the case
  // where the user adds new macro definitions when building the AST
  // file.
  //
  // We do this before emitting any Decl and Types to make sure the
  // Identifier ID is stable.
  SmallVector<const IdentifierInfo *, 128> IIs;
  for (const auto &ID : PP->getIdentifierTable())
    if (IsInterestingNonMacroIdentifier(ID.second, *this))
      IIs.push_back(ID.second);
  // Sort the identifiers lexicographically before getting the references so
  // that their order is stable.
  llvm::sort(IIs, llvm::deref<std::less<>>());
  for (const IdentifierInfo *II : IIs)
    getIdentifierRef(II);

  // Write the set of weak, undeclared identifiers. We always write the
  // entire table, since later PCH files in a PCH chain are only interested in
  // the results at the end of the chain.
  RecordData WeakUndeclaredIdentifiers;
  if (SemaPtr) {
    for (const auto &WeakUndeclaredIdentifierList :
         SemaPtr->WeakUndeclaredIdentifiers) {
      const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first;
      for (const auto &WI : WeakUndeclaredIdentifierList.second) {
        AddIdentifierRef(II, WeakUndeclaredIdentifiers);
        AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers);
        AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers);
      }
    }
  }

  // Write the set of #pragma redefine_extname'd, undeclared identifiers. We
  // always write the entire table, since later PCH files in a PCH chain are
  // only interested in the results at the end of the chain.
  RecordData ExtnameUndeclaredIdentifiers;
  if (SemaPtr && !isWritingStdCXXNamedModules()) {
    ASTContext &Context = SemaPtr->Context;
    ASTRecordWriter ExtnameUndeclaredIdentifiersWriter(
        Context, *this, ExtnameUndeclaredIdentifiers);
    for (const auto &[II, AL] : SemaPtr->ExtnameUndeclaredIdentifiers) {
      ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(II);
      ExtnameUndeclaredIdentifiersWriter.AddIdentifierRef(
          &Context.Idents.get(AL->getLabel()));
      ExtnameUndeclaredIdentifiersWriter.AddSourceLocation(AL->getLocation());
    }
  }

  // Form the record of special types.
  RecordData SpecialTypes;
  if (SemaPtr) {
    ASTContext &Context = SemaPtr->Context;
    AddTypeRef(Context, Context.getRawCFConstantStringType(), SpecialTypes);
    AddTypeRef(Context, Context.getFILEType(), SpecialTypes);
    AddTypeRef(Context, Context.getjmp_bufType(), SpecialTypes);
    AddTypeRef(Context, Context.getsigjmp_bufType(), SpecialTypes);
    AddTypeRef(Context, Context.ObjCIdRedefinitionType, SpecialTypes);
    AddTypeRef(Context, Context.ObjCClassRedefinitionType, SpecialTypes);
    AddTypeRef(Context, Context.ObjCSelRedefinitionType, SpecialTypes);
    AddTypeRef(Context, Context.getucontext_tType(), SpecialTypes);
  }

  if (SemaPtr)
    PrepareWritingSpecialDecls(*SemaPtr);

  // Write the control block
  WriteControlBlock(*PP, isysroot);

  // Write the remaining AST contents.
  Stream.FlushToWord();
  ASTBlockRange.first = Stream.GetCurrentBitNo() >> 3;
  Stream.EnterSubblock(AST_BLOCK_ID, 5);
  ASTBlockStartOffset = Stream.GetCurrentBitNo();

  // This is so that older clang versions, before the introduction
  // of the control block, can read and reject the newer PCH format.
  {
    RecordData Record = {VERSION_MAJOR};
    Stream.EmitRecord(METADATA_OLD_FORMAT, Record);
  }

  // For method pool in the module, if it contains an entry for a selector,
  // the entry should be complete, containing everything introduced by that
  // module and all modules it imports. It's possible that the entry is out of
  // date, so we need to pull in the new content here.

  // It's possible that updateOutOfDateSelector can update SelectorIDs. To be
  // safe, we copy all selectors out.
  if (SemaPtr) {
    llvm::SmallVector<Selector, 256> AllSelectors;
    for (auto &SelectorAndID : SelectorIDs)
      AllSelectors.push_back(SelectorAndID.first);
    for (auto &Selector : AllSelectors)
      SemaPtr->ObjC().updateOutOfDateSelector(Selector);
  }

  if (Chain) {
    // Write the mapping information describing our module dependencies and how
    // each of those modules were mapped into our own offset/ID space, so that
    // the reader can build the appropriate mapping to its own offset/ID space.
    // The map consists solely of a blob with the following format:
    // *(module-kind:i8
    //   module-name-len:i16 module-name:len*i8
    //   source-location-offset:i32
    //   identifier-id:i32
    //   preprocessed-entity-id:i32
    //   macro-definition-id:i32
    //   submodule-id:i32
    //   selector-id:i32
    //   declaration-id:i32
    //   c++-base-specifiers-id:i32
    //   type-id:i32)
    //
    // module-kind is the ModuleKind enum value. If it is MK_PrebuiltModule,
    // MK_ExplicitModule or MK_ImplicitModule, then the module-name is the
    // module name. Otherwise, it is the module file name.
    auto Abbrev = std::make_shared<BitCodeAbbrev>();
    Abbrev->Add(BitCodeAbbrevOp(MODULE_OFFSET_MAP));
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
    unsigned ModuleOffsetMapAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
    SmallString<2048> Buffer;
    {
      llvm::raw_svector_ostream Out(Buffer);
      for (ModuleFile &M : Chain->ModuleMgr) {
        using namespace llvm::support;

        endian::Writer LE(Out, llvm::endianness::little);
        LE.write<uint8_t>(static_cast<uint8_t>(M.Kind));
        // FIXME: Storing a PCH's name (M.FileName) as a string does not handle
        // relocatable files. We probably should call
        // `PreparePathForOutput(M.FileName)` to properly support relocatable
        // PCHs.
        StringRef Name = M.isModule() ? M.ModuleName : M.FileName.str();
        LE.write<uint16_t>(Name.size());
        Out.write(Name.data(), Name.size());

        // Note: if a base ID was uint max, it would not be possible to load
        // another module after it or have more than one entity inside it.
        uint32_t None = std::numeric_limits<uint32_t>::max();

        auto writeBaseIDOrNone = [&](auto BaseID, bool ShouldWrite) {
          assert(BaseID < std::numeric_limits<uint32_t>::max() && "base id too high");
          if (ShouldWrite)
            LE.write<uint32_t>(BaseID);
          else
            LE.write<uint32_t>(None);
        };

        // These values should be unique within a chain, since they will be read
        // as keys into ContinuousRangeMaps.
        writeBaseIDOrNone(M.BaseSubmoduleID, M.LocalNumSubmodules);
        writeBaseIDOrNone(M.BaseSelectorID, M.LocalNumSelectors);
      }
    }
    RecordData::value_type Record[] = {MODULE_OFFSET_MAP};
    Stream.EmitRecordWithBlob(ModuleOffsetMapAbbrev, Record,
                              Buffer.data(), Buffer.size());
  }

  if (SemaPtr)
    WriteDeclAndTypes(SemaPtr->Context);

  WriteFileDeclIDsMap();
  WriteSourceManagerBlock(PP->getSourceManager());
  if (SemaPtr)
    WriteComments(SemaPtr->Context);
  WritePreprocessor(*PP, isModule);
  WriteHeaderSearch(PP->getHeaderSearchInfo());
  if (SemaPtr) {
    WriteSelectors(*SemaPtr);
    WriteReferencedSelectorsPool(*SemaPtr);
    WriteLateParsedTemplates(*SemaPtr);
  }
  WriteIdentifierTable(*PP, SemaPtr ? &SemaPtr->IdResolver : nullptr, isModule);
  if (SemaPtr) {
    WriteFPPragmaOptions(SemaPtr->CurFPFeatureOverrides());
    WriteOpenCLExtensions(*SemaPtr);
    WriteCUDAPragmas(*SemaPtr);
    WriteRISCVIntrinsicPragmas(*SemaPtr);
  }

  // If we're emitting a module, write out the submodule information.
  if (WritingModule)
    WriteSubmodules(WritingModule, SemaPtr ? &SemaPtr->Context : nullptr);

  Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes);

  if (SemaPtr)
    WriteSpecialDeclRecords(*SemaPtr);

  // Write the record containing weak undeclared identifiers.
  if (!WeakUndeclaredIdentifiers.empty())
    Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS,
                      WeakUndeclaredIdentifiers);

  // Write the record containing #pragma redefine_extname'd undeclared
  // identifiers.
  if (!ExtnameUndeclaredIdentifiers.empty())
    Stream.EmitRecord(EXTNAME_UNDECLARED_IDENTIFIERS,
                      ExtnameUndeclaredIdentifiers);

  if (!WritingModule) {
    // Write the submodules that were imported, if any.
    struct ModuleInfo {
      uint64_t ID;
      Module *M;
      ModuleInfo(uint64_t ID, Module *M) : ID(ID), M(M) {}
    };
    llvm::SmallVector<ModuleInfo, 64> Imports;
    if (SemaPtr) {
      for (const auto *I : SemaPtr->Context.local_imports()) {
        assert(SubmoduleIDs.contains(I->getImportedModule()));
        Imports.push_back(ModuleInfo(SubmoduleIDs[I->getImportedModule()],
                                     I->getImportedModule()));
      }
    }

    if (!Imports.empty()) {
      auto Cmp = [](const ModuleInfo &A, const ModuleInfo &B) {
        return A.ID < B.ID;
      };
      auto Eq = [](const ModuleInfo &A, const ModuleInfo &B) {
        return A.ID == B.ID;
      };

      // Sort and deduplicate module IDs.
      llvm::sort(Imports, Cmp);
      Imports.erase(llvm::unique(Imports, Eq), Imports.end());

      RecordData ImportedModules;
      for (const auto &Import : Imports) {
        ImportedModules.push_back(Import.ID);
        // FIXME: If the module has macros imported then later has declarations
        // imported, this location won't be the right one as a location for the
        // declaration imports.
        AddSourceLocation(PP->getModuleImportLoc(Import.M), ImportedModules);
      }

      Stream.EmitRecord(IMPORTED_MODULES, ImportedModules);
    }
  }

  WriteObjCCategories();
  if (SemaPtr) {
    if (!WritingModule) {
      WriteOptimizePragmaOptions(*SemaPtr);
      WriteMSStructPragmaOptions(*SemaPtr);
      WriteMSPointersToMembersPragmaOptions(*SemaPtr);
    }
    WritePackPragmaOptions(*SemaPtr);
    WriteFloatControlPragmaOptions(*SemaPtr);
    WriteDeclsWithEffectsToVerify(*SemaPtr);
  }

  // Some simple statistics
  RecordData::value_type Record[] = {NumStatements,
                                     NumMacros,
                                     NumLexicalDeclContexts,
                                     NumVisibleDeclContexts,
                                     NumModuleLocalDeclContexts,
                                     NumTULocalDeclContexts};
  Stream.EmitRecord(STATISTICS, Record);
  Stream.ExitBlock();
  Stream.FlushToWord();
  ASTBlockRange.second = Stream.GetCurrentBitNo() >> 3;

  // Write the module file extension blocks.
  if (SemaPtr)
    for (const auto &ExtWriter : ModuleFileExtensionWriters)
      WriteModuleFileExtension(*SemaPtr, *ExtWriter);

  return backpatchSignature();
}

// Add update records for all mangling numbers and static local numbers.
// These aren't really update records, but this is a convenient way of
// tagging this rare extra data onto the declarations.
void ASTWriter::AddedManglingNumber(const Decl *D, unsigned Number) {
  if (D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::ManglingNumber, Number));
}
void ASTWriter::AddedStaticLocalNumbers(const Decl *D, unsigned Number) {
  if (D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::StaticLocalNumber, Number));
}

void ASTWriter::AddedAnonymousNamespace(const TranslationUnitDecl *TU,
                                        NamespaceDecl *AnonNamespace) {
  // If the translation unit has an anonymous namespace, and we don't already
  // have an update block for it, write it as an update block.
  // FIXME: Why do we not do this if there's already an update block?
  if (NamespaceDecl *NS = TU->getAnonymousNamespace()) {
    ASTWriter::UpdateRecord &Record = DeclUpdates[TU];
    if (Record.empty())
      Record.push_back(
          DeclUpdate(DeclUpdateKind::CXXAddedAnonymousNamespace, NS));
  }
}

void ASTWriter::WriteDeclAndTypes(ASTContext &Context) {
  // Keep writing types, declarations, and declaration update records
  // until we've emitted all of them.
  RecordData DeclUpdatesOffsetsRecord;
  Stream.EnterSubblock(DECLTYPES_BLOCK_ID, /*bits for abbreviations*/ 6);
  DeclTypesBlockStartOffset = Stream.GetCurrentBitNo();
  WriteTypeAbbrevs();
  WriteDeclAbbrevs();
  do {
    WriteDeclUpdatesBlocks(Context, DeclUpdatesOffsetsRecord);
    while (!DeclTypesToEmit.empty()) {
      DeclOrType DOT = DeclTypesToEmit.front();
      DeclTypesToEmit.pop();
      if (DOT.isType())
        WriteType(Context, DOT.getType());
      else
        WriteDecl(Context, DOT.getDecl());
    }
  } while (!DeclUpdates.empty());

  DoneWritingDeclsAndTypes = true;

  // DelayedNamespace is only meaningful in reduced BMI.
  // See the comments of DelayedNamespace for details.
  assert(DelayedNamespace.empty() || GeneratingReducedBMI);
  RecordData DelayedNamespaceRecord;
  for (NamespaceDecl *NS : DelayedNamespace) {
    LookupBlockOffsets Offsets;

    Offsets.LexicalOffset = WriteDeclContextLexicalBlock(Context, NS);
    WriteDeclContextVisibleBlock(Context, NS, Offsets);

    if (Offsets.LexicalOffset)
      Offsets.LexicalOffset -= DeclTypesBlockStartOffset;

    // Write the offset relative to current block.
    if (Offsets.VisibleOffset)
      Offsets.VisibleOffset -= DeclTypesBlockStartOffset;

    if (Offsets.ModuleLocalOffset)
      Offsets.ModuleLocalOffset -= DeclTypesBlockStartOffset;

    if (Offsets.TULocalOffset)
      Offsets.TULocalOffset -= DeclTypesBlockStartOffset;

    AddDeclRef(NS, DelayedNamespaceRecord);
    AddLookupOffsets(Offsets, DelayedNamespaceRecord);
  }

  // The process of writing lexical and visible block for delayed namespace
  // shouldn't introduce any new decls, types or update to emit.
  assert(DeclTypesToEmit.empty());
  assert(DeclUpdates.empty());

  Stream.ExitBlock();

  // These things can only be done once we've written out decls and types.
  WriteTypeDeclOffsets();
  if (!DeclUpdatesOffsetsRecord.empty())
    Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);

  if (!DelayedNamespaceRecord.empty())
    Stream.EmitRecord(DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD,
                      DelayedNamespaceRecord);

  if (!RelatedDeclsMap.empty()) {
    // TODO: on disk hash table for related decls mapping might be more
    // efficent becuase it allows lazy deserialization.
    RecordData RelatedDeclsMapRecord;
    for (const auto &Pair : RelatedDeclsMap) {
      RelatedDeclsMapRecord.push_back(Pair.first.getRawValue());
      RelatedDeclsMapRecord.push_back(Pair.second.size());
      for (const auto &Lambda : Pair.second)
        RelatedDeclsMapRecord.push_back(Lambda.getRawValue());
    }

    auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
    Abv->Add(llvm::BitCodeAbbrevOp(RELATED_DECLS_MAP));
    Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array));
    Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
    unsigned FunctionToLambdaMapAbbrev = Stream.EmitAbbrev(std::move(Abv));
    Stream.EmitRecord(RELATED_DECLS_MAP, RelatedDeclsMapRecord,
                      FunctionToLambdaMapAbbrev);
  }

  if (!SpecializationsUpdates.empty()) {
    WriteSpecializationsUpdates(/*IsPartial=*/false);
    SpecializationsUpdates.clear();
  }

  if (!PartialSpecializationsUpdates.empty()) {
    WriteSpecializationsUpdates(/*IsPartial=*/true);
    PartialSpecializationsUpdates.clear();
  }

  const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
  // Create a lexical update block containing all of the declarations in the
  // translation unit that do not come from other AST files.
  SmallVector<DeclID, 128> NewGlobalKindDeclPairs;
  for (const auto *D : TU->noload_decls()) {
    if (D->isFromASTFile())
      continue;

    // In reduced BMI, skip unreached declarations.
    if (!wasDeclEmitted(D))
      continue;

    NewGlobalKindDeclPairs.push_back(D->getKind());
    NewGlobalKindDeclPairs.push_back(GetDeclRef(D).getRawValue());
  }

  auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));

  RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
  Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
                            bytes(NewGlobalKindDeclPairs));

  Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_MODULE_LOCAL_VISIBLE));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  ModuleLocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_TU_LOCAL_VISIBLE));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  TULocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // And a visible updates block for the translation unit.
  WriteDeclContextVisibleUpdate(Context, TU);

  // If we have any extern "C" names, write out a visible update for them.
  if (Context.ExternCContext)
    WriteDeclContextVisibleUpdate(Context, Context.ExternCContext);

  // Write the visible updates to DeclContexts.
  for (auto *DC : UpdatedDeclContexts)
    WriteDeclContextVisibleUpdate(Context, DC);
}

void ASTWriter::WriteSpecializationsUpdates(bool IsPartial) {
  auto RecordType = IsPartial ? CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION
                              : CXX_ADDED_TEMPLATE_SPECIALIZATION;

  auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
  Abv->Add(llvm::BitCodeAbbrevOp(RecordType));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
  auto UpdateSpecializationAbbrev = Stream.EmitAbbrev(std::move(Abv));

  auto &SpecUpdates =
      IsPartial ? PartialSpecializationsUpdates : SpecializationsUpdates;
  for (auto &SpecializationUpdate : SpecUpdates) {
    const NamedDecl *D = SpecializationUpdate.first;

    llvm::SmallString<4096> LookupTable;
    GenerateSpecializationInfoLookupTable(D, SpecializationUpdate.second,
                                          LookupTable, IsPartial);

    // Write the lookup table
    RecordData::value_type Record[] = {
        static_cast<RecordData::value_type>(RecordType),
        getDeclID(D).getRawValue()};
    Stream.EmitRecordWithBlob(UpdateSpecializationAbbrev, Record, LookupTable);
  }
}

void ASTWriter::WriteDeclUpdatesBlocks(ASTContext &Context,
                                       RecordDataImpl &OffsetsRecord) {
  if (DeclUpdates.empty())
    return;

  DeclUpdateMap LocalUpdates;
  LocalUpdates.swap(DeclUpdates);

  for (auto &DeclUpdate : LocalUpdates) {
    const Decl *D = DeclUpdate.first;

    bool HasUpdatedBody = false;
    bool HasAddedVarDefinition = false;
    RecordData RecordData;
    ASTRecordWriter Record(Context, *this, RecordData);
    for (auto &Update : DeclUpdate.second) {
      DeclUpdateKind Kind = Update.getKind();

      // An updated body is emitted last, so that the reader doesn't need
      // to skip over the lazy body to reach statements for other records.
      if (Kind == DeclUpdateKind::CXXAddedFunctionDefinition)
        HasUpdatedBody = true;
      else if (Kind == DeclUpdateKind::CXXAddedVarDefinition)
        HasAddedVarDefinition = true;
      else
        Record.push_back(llvm::to_underlying(Kind));

      switch (Kind) {
      case DeclUpdateKind::CXXAddedImplicitMember:
      case DeclUpdateKind::CXXAddedAnonymousNamespace:
        assert(Update.getDecl() && "no decl to add?");
        Record.AddDeclRef(Update.getDecl());
        break;
      case DeclUpdateKind::CXXAddedFunctionDefinition:
      case DeclUpdateKind::CXXAddedVarDefinition:
        break;

      case DeclUpdateKind::CXXPointOfInstantiation:
        // FIXME: Do we need to also save the template specialization kind here?
        Record.AddSourceLocation(Update.getLoc());
        break;

      case DeclUpdateKind::CXXInstantiatedDefaultArgument:
        Record.writeStmtRef(
            cast<ParmVarDecl>(Update.getDecl())->getDefaultArg());
        break;

      case DeclUpdateKind::CXXInstantiatedDefaultMemberInitializer:
        Record.AddStmt(
            cast<FieldDecl>(Update.getDecl())->getInClassInitializer());
        break;

      case DeclUpdateKind::CXXInstantiatedClassDefinition: {
        auto *RD = cast<CXXRecordDecl>(D);
        UpdatedDeclContexts.insert(RD->getPrimaryContext());
        Record.push_back(RD->isParamDestroyedInCallee());
        Record.push_back(llvm::to_underlying(RD->getArgPassingRestrictions()));
        Record.AddCXXDefinitionData(RD);
        Record.AddOffset(WriteDeclContextLexicalBlock(Context, RD));

        // This state is sometimes updated by template instantiation, when we
        // switch from the specialization referring to the template declaration
        // to it referring to the template definition.
        if (auto *MSInfo = RD->getMemberSpecializationInfo()) {
          Record.push_back(MSInfo->getTemplateSpecializationKind());
          Record.AddSourceLocation(MSInfo->getPointOfInstantiation());
        } else {
          auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);
          Record.push_back(Spec->getTemplateSpecializationKind());
          Record.AddSourceLocation(Spec->getPointOfInstantiation());

          // The instantiation might have been resolved to a partial
          // specialization. If so, record which one.
          auto From = Spec->getInstantiatedFrom();
          if (auto PartialSpec =
                From.dyn_cast<ClassTemplatePartialSpecializationDecl*>()) {
            Record.push_back(true);
            Record.AddDeclRef(PartialSpec);
            Record.AddTemplateArgumentList(
                &Spec->getTemplateInstantiationArgs());
          } else {
            Record.push_back(false);
          }
        }
        Record.push_back(llvm::to_underlying(RD->getTagKind()));
        Record.AddSourceLocation(RD->getLocation());
        Record.AddSourceLocation(RD->getBeginLoc());
        Record.AddSourceRange(RD->getBraceRange());

        // Instantiation may change attributes; write them all out afresh.
        Record.push_back(D->hasAttrs());
        if (D->hasAttrs())
          Record.AddAttributes(D->getAttrs());

        // FIXME: Ensure we don't get here for explicit instantiations.
        break;
      }

      case DeclUpdateKind::CXXResolvedDtorDelete:
        Record.AddDeclRef(Update.getDecl());
        Record.AddStmt(cast<CXXDestructorDecl>(D)->getOperatorDeleteThisArg());
        break;

      case DeclUpdateKind::CXXResolvedDtorGlobDelete:
        Record.AddDeclRef(Update.getDecl());
        break;

      case DeclUpdateKind::CXXResolvedDtorArrayDelete:
        Record.AddDeclRef(Update.getDecl());
        break;

      case DeclUpdateKind::CXXResolvedDtorGlobArrayDelete:
        Record.AddDeclRef(Update.getDecl());
        break;

      case DeclUpdateKind::CXXResolvedExceptionSpec: {
        auto prototype =
          cast<FunctionDecl>(D)->getType()->castAs<FunctionProtoType>();
        Record.writeExceptionSpecInfo(prototype->getExceptionSpecInfo());
        break;
      }

      case DeclUpdateKind::CXXDeducedReturnType:
        Record.push_back(GetOrCreateTypeID(Context, Update.getType()));
        break;

      case DeclUpdateKind::DeclMarkedUsed:
        break;

      case DeclUpdateKind::ManglingNumber:
      case DeclUpdateKind::StaticLocalNumber:
        Record.push_back(Update.getNumber());
        break;

      case DeclUpdateKind::DeclMarkedOpenMPThreadPrivate:
        Record.AddSourceRange(
            D->getAttr<OMPThreadPrivateDeclAttr>()->getRange());
        break;

      case DeclUpdateKind::DeclMarkedOpenMPAllocate: {
        auto *A = D->getAttr<OMPAllocateDeclAttr>();
        Record.push_back(A->getAllocatorType());
        Record.AddStmt(A->getAllocator());
        Record.AddStmt(A->getAlignment());
        Record.AddSourceRange(A->getRange());
        break;
      }

      case DeclUpdateKind::DeclMarkedOpenMPIndirectCall:
        Record.AddSourceRange(
            D->getAttr<OMPTargetIndirectCallAttr>()->getRange());
        break;

      case DeclUpdateKind::DeclMarkedOpenMPDeclareTarget:
        Record.push_back(D->getAttr<OMPDeclareTargetDeclAttr>()->getMapType());
        Record.AddSourceRange(
            D->getAttr<OMPDeclareTargetDeclAttr>()->getRange());
        break;

      case DeclUpdateKind::DeclExported:
        Record.push_back(getSubmoduleID(Update.getModule()));
        break;

      case DeclUpdateKind::AddedAttrToRecord:
        Record.AddAttributes(llvm::ArrayRef(Update.getAttr()));
        break;
      }
    }

    // Add a trailing update record, if any. These must go last because we
    // lazily load their attached statement.
    if (!GeneratingReducedBMI || !CanElideDeclDef(D)) {
      if (HasUpdatedBody) {
        const auto *Def = cast<FunctionDecl>(D);
        Record.push_back(
            llvm::to_underlying(DeclUpdateKind::CXXAddedFunctionDefinition));
        Record.push_back(Def->isInlined());
        Record.AddSourceLocation(Def->getInnerLocStart());
        Record.AddFunctionDefinition(Def);
      } else if (HasAddedVarDefinition) {
        const auto *VD = cast<VarDecl>(D);
        Record.push_back(
            llvm::to_underlying(DeclUpdateKind::CXXAddedVarDefinition));
        Record.push_back(VD->isInline());
        Record.push_back(VD->isInlineSpecified());
        Record.AddVarDeclInit(VD);
      }
    }

    AddDeclRef(D, OffsetsRecord);
    OffsetsRecord.push_back(Record.Emit(DECL_UPDATES));
  }
}

void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info,
                                 RecordDataImpl &Record) {
  uint32_t Raw = Sema::AlignPackInfo::getRawEncoding(Info);
  Record.push_back(Raw);
}

FileID ASTWriter::getAdjustedFileID(FileID FID) const {
  if (FID.isInvalid() || PP->getSourceManager().isLoadedFileID(FID) ||
      NonAffectingFileIDs.empty())
    return FID;
  auto It = llvm::lower_bound(NonAffectingFileIDs, FID);
  unsigned Idx = std::distance(NonAffectingFileIDs.begin(), It);
  unsigned Offset = NonAffectingFileIDAdjustments[Idx];
  return FileID::get(FID.getOpaqueValue() - Offset);
}

unsigned ASTWriter::getAdjustedNumCreatedFIDs(FileID FID) const {
  unsigned NumCreatedFIDs = PP->getSourceManager()
                                .getLocalSLocEntry(FID.ID)
                                .getFile()
                                .NumCreatedFIDs;

  unsigned AdjustedNumCreatedFIDs = 0;
  for (unsigned I = FID.ID, N = I + NumCreatedFIDs; I != N; ++I)
    if (IsSLocAffecting[I])
      ++AdjustedNumCreatedFIDs;
  return AdjustedNumCreatedFIDs;
}

SourceLocation ASTWriter::getAdjustedLocation(SourceLocation Loc) const {
  if (Loc.isInvalid())
    return Loc;
  return Loc.getLocWithOffset(-getAdjustment(Loc.getOffset()));
}

SourceRange ASTWriter::getAdjustedRange(SourceRange Range) const {
  return SourceRange(getAdjustedLocation(Range.getBegin()),
                     getAdjustedLocation(Range.getEnd()));
}

SourceLocation::UIntTy
ASTWriter::getAdjustedOffset(SourceLocation::UIntTy Offset) const {
  return Offset - getAdjustment(Offset);
}

SourceLocation::UIntTy
ASTWriter::getAdjustment(SourceLocation::UIntTy Offset) const {
  if (NonAffectingRanges.empty())
    return 0;

  if (PP->getSourceManager().isLoadedOffset(Offset))
    return 0;

  if (Offset > NonAffectingRanges.back().getEnd().getOffset())
    return NonAffectingOffsetAdjustments.back();

  if (Offset < NonAffectingRanges.front().getBegin().getOffset())
    return 0;

  auto Contains = [](const SourceRange &Range, SourceLocation::UIntTy Offset) {
    return Range.getEnd().getOffset() < Offset;
  };

  auto It = llvm::lower_bound(NonAffectingRanges, Offset, Contains);
  unsigned Idx = std::distance(NonAffectingRanges.begin(), It);
  return NonAffectingOffsetAdjustments[Idx];
}

void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) {
  Record.push_back(getAdjustedFileID(FID).getOpaqueValue());
}

SourceLocationEncoding::RawLocEncoding
ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc) {
  SourceLocation::UIntTy BaseOffset = 0;
  unsigned ModuleFileIndex = 0;

  // See SourceLocationEncoding.h for the encoding details.
  if (PP->getSourceManager().isLoadedSourceLocation(Loc) && Loc.isValid()) {
    assert(getChain());
    auto SLocMapI = getChain()->GlobalSLocOffsetMap.find(
        SourceManager::MaxLoadedOffset - Loc.getOffset() - 1);
    assert(SLocMapI != getChain()->GlobalSLocOffsetMap.end() &&
           "Corrupted global sloc offset map");
    ModuleFile *F = SLocMapI->second;
    BaseOffset = F->SLocEntryBaseOffset - 2;
    // 0 means the location is not loaded. So we need to add 1 to the index to
    // make it clear.
    ModuleFileIndex = F->Index + 1;
    assert(&getChain()->getModuleManager()[F->Index] == F);
  }

  return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex);
}

void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
  Loc = getAdjustedLocation(Loc);
  Record.push_back(getRawSourceLocationEncoding(Loc));
}

void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) {
  AddSourceLocation(Range.getBegin(), Record);
  AddSourceLocation(Range.getEnd(), Record);
}

void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) {
  AddAPInt(Value.bitcastToAPInt());
}

void ASTWriter::AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record) {
  Record.push_back(getIdentifierRef(II));
}

IdentifierID ASTWriter::getIdentifierRef(const IdentifierInfo *II) {
  if (!II)
    return 0;

  IdentifierID &ID = IdentifierIDs[II];
  if (ID == 0)
    ID = NextIdentID++;
  return ID;
}

MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) {
  // Don't emit builtin macros like __LINE__ to the AST file unless they
  // have been redefined by the header (in which case they are not
  // isBuiltinMacro).
  if (!MI || MI->isBuiltinMacro())
    return 0;

  MacroID &ID = MacroIDs[MI];
  if (ID == 0) {
    ID = NextMacroID++;
    MacroInfoToEmitData Info = { Name, MI, ID };
    MacroInfosToEmit.push_back(Info);
  }
  return ID;
}

uint32_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) {
  return IdentMacroDirectivesOffsetMap.lookup(Name);
}

void ASTRecordWriter::AddSelectorRef(const Selector SelRef) {
  Record->push_back(Writer->getSelectorRef(SelRef));
}

SelectorID ASTWriter::getSelectorRef(Selector Sel) {
  if (Sel.getAsOpaquePtr() == nullptr) {
    return 0;
  }

  SelectorID SID = SelectorIDs[Sel];
  if (SID == 0 && Chain) {
    // This might trigger a ReadSelector callback, which will set the ID for
    // this selector.
    Chain->LoadSelector(Sel);
    SID = SelectorIDs[Sel];
  }
  if (SID == 0) {
    SID = NextSelectorID++;
    SelectorIDs[Sel] = SID;
  }
  return SID;
}

void ASTRecordWriter::AddCXXTemporary(const CXXTemporary *Temp) {
  AddDeclRef(Temp->getDestructor());
}

void ASTRecordWriter::AddTemplateArgumentLocInfo(
    const TemplateArgumentLoc &Arg) {
  const TemplateArgumentLocInfo &Info = Arg.getLocInfo();
  switch (auto K = Arg.getArgument().getKind()) {
  case TemplateArgument::Expression:
    AddStmt(Info.getAsExpr());
    break;
  case TemplateArgument::Type:
    AddTypeSourceInfo(Info.getAsTypeSourceInfo());
    break;
  case TemplateArgument::Template:
  case TemplateArgument::TemplateExpansion:
    AddSourceLocation(Arg.getTemplateKWLoc());
    AddNestedNameSpecifierLoc(Arg.getTemplateQualifierLoc());
    AddSourceLocation(Arg.getTemplateNameLoc());
    if (K == TemplateArgument::TemplateExpansion)
      AddSourceLocation(Arg.getTemplateEllipsisLoc());
    break;
  case TemplateArgument::Null:
  case TemplateArgument::Integral:
  case TemplateArgument::Declaration:
  case TemplateArgument::NullPtr:
  case TemplateArgument::StructuralValue:
  case TemplateArgument::Pack:
    // FIXME: Is this right?
    break;
  }
}

void ASTRecordWriter::AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg) {
  AddTemplateArgument(Arg.getArgument());

  if (Arg.getArgument().getKind() == TemplateArgument::Expression) {
    bool InfoHasSameExpr
      = Arg.getArgument().getAsExpr() == Arg.getLocInfo().getAsExpr();
    Record->push_back(InfoHasSameExpr);
    if (InfoHasSameExpr)
      return; // Avoid storing the same expr twice.
  }
  AddTemplateArgumentLocInfo(Arg);
}

void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) {
  if (!TInfo) {
    AddTypeRef(QualType());
    return;
  }

  AddTypeRef(TInfo->getType());
  AddTypeLoc(TInfo->getTypeLoc());
}

void ASTRecordWriter::AddTypeLoc(TypeLoc TL) {
  TypeLocWriter TLW(*this);
  for (; !TL.isNull(); TL = TL.getNextTypeLoc())
    TLW.Visit(TL);
}

void ASTWriter::AddTypeRef(ASTContext &Context, QualType T,
                           RecordDataImpl &Record) {
  Record.push_back(GetOrCreateTypeID(Context, T));
}

template <typename IdxForTypeTy>
static TypeID MakeTypeID(ASTContext &Context, QualType T,
                         IdxForTypeTy IdxForType) {
  if (T.isNull())
    return PREDEF_TYPE_NULL_ID;

  unsigned FastQuals = T.getLocalFastQualifiers();
  T.removeLocalFastQualifiers();

  if (T.hasLocalNonFastQualifiers())
    return IdxForType(T).asTypeID(FastQuals);

  assert(!T.hasLocalQualifiers());

  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr()))
    return TypeIdxFromBuiltin(BT).asTypeID(FastQuals);

  if (T == Context.AutoDeductTy)
    return TypeIdx(0, PREDEF_TYPE_AUTO_DEDUCT).asTypeID(FastQuals);
  if (T == Context.AutoRRefDeductTy)
    return TypeIdx(0, PREDEF_TYPE_AUTO_RREF_DEDUCT).asTypeID(FastQuals);

  return IdxForType(T).asTypeID(FastQuals);
}

TypeID ASTWriter::GetOrCreateTypeID(ASTContext &Context, QualType T) {
  return MakeTypeID(Context, T, [&](QualType T) -> TypeIdx {
    if (T.isNull())
      return TypeIdx();
    assert(!T.getLocalFastQualifiers());

    TypeIdx &Idx = TypeIdxs[T];
    if (Idx.getValue() == 0) {
      if (DoneWritingDeclsAndTypes) {
        assert(0 && "New type seen after serializing all the types to emit!");
        return TypeIdx();
      }

      // We haven't seen this type before. Assign it a new ID and put it
      // into the queue of types to emit.
      Idx = TypeIdx(0, NextTypeID++);
      DeclTypesToEmit.push(T);
    }
    return Idx;
  });
}

llvm::MapVector<ModuleFile *, const Decl *>
ASTWriter::CollectFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) {
  llvm::MapVector<ModuleFile *, const Decl *> Firsts;
  // FIXME: We can skip entries that we know are implied by others.
  for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl()) {
    if (R->isFromASTFile())
      Firsts[Chain->getOwningModuleFile(R)] = R;
    else if (IncludeLocal)
      Firsts[nullptr] = R;
  }
  return Firsts;
}

void ASTWriter::AddLookupOffsets(const LookupBlockOffsets &Offsets,
                                 RecordDataImpl &Record) {
  Record.push_back(Offsets.LexicalOffset);
  Record.push_back(Offsets.VisibleOffset);
  Record.push_back(Offsets.ModuleLocalOffset);
  Record.push_back(Offsets.TULocalOffset);
}

void ASTWriter::AddMacroRef(MacroInfo *MI, const IdentifierInfo *Name,
                            RecordDataImpl &Record) {
  MacroID MacroRef = getMacroRef(MI, Name);
  Record.push_back(MacroRef >> 32);
  Record.push_back(MacroRef & llvm::maskTrailingOnes<MacroID>(32));
}

void ASTWriter::AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record) {
  if (!wasDeclEmitted(D))
    return;

  AddDeclRef(D, Record);
}

void ASTWriter::AddDeclRef(const Decl *D, RecordDataImpl &Record) {
  Record.push_back(GetDeclRef(D).getRawValue());
}

LocalDeclID ASTWriter::GetDeclRef(const Decl *D) {
  assert(WritingAST && "Cannot request a declaration ID before AST writing");

  if (!D) {
    return LocalDeclID();
  }

  getLazyUpdates(D);

  // If D comes from an AST file, its declaration ID is already known and
  // fixed.
  if (D->isFromASTFile()) {
    if (isWritingStdCXXNamedModules() && D->getOwningModule())
      TouchedTopLevelModules.insert(D->getOwningModule()->getTopLevelModule());

    return LocalDeclID(D->getGlobalID());
  }

  assert(!(reinterpret_cast<uintptr_t>(D) & 0x01) && "Invalid decl pointer");
  LocalDeclID &ID = DeclIDs[D];
  if (ID.isInvalid()) {
    if (DoneWritingDeclsAndTypes) {
      assert(0 && "New decl seen after serializing all the decls to emit!");
      return LocalDeclID();
    }

    // We haven't seen this declaration before. Give it a new ID and
    // enqueue it in the list of declarations to emit.
    ID = NextDeclID++;
    DeclTypesToEmit.push(const_cast<Decl *>(D));
  }

  return ID;
}

LocalDeclID ASTWriter::getDeclID(const Decl *D) {
  if (!D)
    return LocalDeclID();

  // If D comes from an AST file, its declaration ID is already known and
  // fixed.
  if (D->isFromASTFile())
    return LocalDeclID(D->getGlobalID());

  assert(DeclIDs.contains(D) && "Declaration not emitted!");
  return DeclIDs[D];
}

bool ASTWriter::wasDeclEmitted(const Decl *D) const {
  assert(D);

  assert(DoneWritingDeclsAndTypes &&
         "wasDeclEmitted should only be called after writing declarations");

  if (D->isFromASTFile())
    return true;

  bool Emitted = DeclIDs.contains(D);
  assert((Emitted || (!D->getOwningModule() && isWritingStdCXXNamedModules()) ||
          GeneratingReducedBMI) &&
         "The declaration within modules can only be omitted in reduced BMI.");
  return Emitted;
}

void ASTWriter::getLazyUpdates(const Decl *D) {
  if (!GeneratingReducedBMI)
    return;

  if (auto *Iter = DeclUpdatesLazy.find(D); Iter != DeclUpdatesLazy.end()) {
    for (DeclUpdate &Update : Iter->second)
      DeclUpdates[D].push_back(Update);
    DeclUpdatesLazy.erase(Iter);
  }

  // If the Decl in DeclUpdatesLazy gets touched, emit the update.
  if (auto *DC = dyn_cast<DeclContext>(D);
      DC && UpdatedDeclContextsLazy.count(DC)) {
    UpdatedDeclContexts.insert(DC);
    UpdatedDeclContextsLazy.remove(DC);
  }
}

void ASTWriter::associateDeclWithFile(const Decl *D, LocalDeclID ID) {
  assert(ID.isValid());
  assert(D);

  SourceLocation Loc = D->getLocation();
  if (Loc.isInvalid())
    return;

  // We only keep track of the file-level declarations of each file.
  if (!D->getLexicalDeclContext()->isFileContext())
    return;
  // FIXME: ParmVarDecls that are part of a function type of a parameter of
  // a function/objc method, should not have TU as lexical context.
  // TemplateTemplateParmDecls that are part of an alias template, should not
  // have TU as lexical context.
  if (isa<ParmVarDecl, TemplateTemplateParmDecl>(D))
    return;

  SourceManager &SM = PP->getSourceManager();
  SourceLocation FileLoc = SM.getFileLoc(Loc);
  assert(SM.isLocalSourceLocation(FileLoc));
  auto [FID, Offset] = SM.getDecomposedLoc(FileLoc);
  if (FID.isInvalid())
    return;
  assert(SM.getSLocEntry(FID).isFile());
  assert(IsSLocAffecting[FID.ID]);

  std::unique_ptr<DeclIDInFileInfo> &Info = FileDeclIDs[FID];
  if (!Info)
    Info = std::make_unique<DeclIDInFileInfo>();

  std::pair<unsigned, LocalDeclID> LocDecl(Offset, ID);
  LocDeclIDsTy &Decls = Info->DeclIDs;
  Decls.push_back(LocDecl);
}

unsigned ASTWriter::getAnonymousDeclarationNumber(const NamedDecl *D) {
  assert(needsAnonymousDeclarationNumber(D) &&
         "expected an anonymous declaration");

  // Number the anonymous declarations within this context, if we've not
  // already done so.
  auto It = AnonymousDeclarationNumbers.find(D);
  if (It == AnonymousDeclarationNumbers.end()) {
    auto *DC = D->getLexicalDeclContext();
    numberAnonymousDeclsWithin(DC, [&](const NamedDecl *ND, unsigned Number) {
      AnonymousDeclarationNumbers[ND] = Number;
    });

    It = AnonymousDeclarationNumbers.find(D);
    assert(It != AnonymousDeclarationNumbers.end() &&
           "declaration not found within its lexical context");
  }

  return It->second;
}

void ASTRecordWriter::AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc,
                                            DeclarationName Name) {
  switch (Name.getNameKind()) {
  case DeclarationName::CXXConstructorName:
  case DeclarationName::CXXDestructorName:
  case DeclarationName::CXXConversionFunctionName:
    AddTypeSourceInfo(DNLoc.getNamedTypeInfo());
    break;

  case DeclarationName::CXXOperatorName:
    AddSourceRange(DNLoc.getCXXOperatorNameRange());
    break;

  case DeclarationName::CXXLiteralOperatorName:
    AddSourceLocation(DNLoc.getCXXLiteralOperatorNameLoc());
    break;

  case DeclarationName::Identifier:
  case DeclarationName::ObjCZeroArgSelector:
  case DeclarationName::ObjCOneArgSelector:
  case DeclarationName::ObjCMultiArgSelector:
  case DeclarationName::CXXUsingDirective:
  case DeclarationName::CXXDeductionGuideName:
    break;
  }
}

void ASTRecordWriter::AddDeclarationNameInfo(
    const DeclarationNameInfo &NameInfo) {
  AddDeclarationName(NameInfo.getName());
  AddSourceLocation(NameInfo.getLoc());
  AddDeclarationNameLoc(NameInfo.getInfo(), NameInfo.getName());
}

void ASTRecordWriter::AddQualifierInfo(const QualifierInfo &Info) {
  AddNestedNameSpecifierLoc(Info.QualifierLoc);
  Record->push_back(Info.NumTemplParamLists);
  for (unsigned i = 0, e = Info.NumTemplParamLists; i != e; ++i)
    AddTemplateParameterList(Info.TemplParamLists[i]);
}

void ASTRecordWriter::AddNestedNameSpecifierLoc(
    NestedNameSpecifierLoc QualifierLoc) {
  // Nested name specifiers usually aren't too long. I think that 8 would
  // typically accommodate the vast majority.
  SmallVector<NestedNameSpecifierLoc , 8> NestedNames;

  // Push each of the nested-name-specifiers's onto a stack for
  // serialization in reverse order.
  while (QualifierLoc) {
    NestedNames.push_back(QualifierLoc);
    QualifierLoc = QualifierLoc.getAsNamespaceAndPrefix().Prefix;
  }

  Record->push_back(NestedNames.size());
  while(!NestedNames.empty()) {
    QualifierLoc = NestedNames.pop_back_val();
    NestedNameSpecifier Qualifier = QualifierLoc.getNestedNameSpecifier();
    NestedNameSpecifier::Kind Kind = Qualifier.getKind();
    Record->push_back(llvm::to_underlying(Kind));
    switch (Kind) {
    case NestedNameSpecifier::Kind::Namespace:
      AddDeclRef(Qualifier.getAsNamespaceAndPrefix().Namespace);
      AddSourceRange(QualifierLoc.getLocalSourceRange());
      break;

    case NestedNameSpecifier::Kind::Type: {
      TypeLoc TL = QualifierLoc.castAsTypeLoc();
      AddTypeRef(TL.getType());
      AddTypeLoc(TL);
      AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
      break;
    }

    case NestedNameSpecifier::Kind::Global:
      AddSourceLocation(QualifierLoc.getLocalSourceRange().getEnd());
      break;

    case NestedNameSpecifier::Kind::MicrosoftSuper:
      AddDeclRef(Qualifier.getAsMicrosoftSuper());
      AddSourceRange(QualifierLoc.getLocalSourceRange());
      break;

    case NestedNameSpecifier::Kind::Null:
      llvm_unreachable("unexpected null nested name specifier");
    }
  }
}

void ASTRecordWriter::AddTemplateParameterList(
    const TemplateParameterList *TemplateParams) {
  assert(TemplateParams && "No TemplateParams!");
  AddSourceLocation(TemplateParams->getTemplateLoc());
  AddSourceLocation(TemplateParams->getLAngleLoc());
  AddSourceLocation(TemplateParams->getRAngleLoc());

  Record->push_back(TemplateParams->size());
  for (const auto &P : *TemplateParams)
    AddDeclRef(P);
  if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) {
    Record->push_back(true);
    writeStmtRef(RequiresClause);
  } else {
    Record->push_back(false);
  }
}

/// Emit a template argument list.
void ASTRecordWriter::AddTemplateArgumentList(
    const TemplateArgumentList *TemplateArgs) {
  assert(TemplateArgs && "No TemplateArgs!");
  Record->push_back(TemplateArgs->size());
  for (int i = 0, e = TemplateArgs->size(); i != e; ++i)
    AddTemplateArgument(TemplateArgs->get(i));
}

void ASTRecordWriter::AddASTTemplateArgumentListInfo(
    const ASTTemplateArgumentListInfo *ASTTemplArgList) {
  assert(ASTTemplArgList && "No ASTTemplArgList!");
  AddSourceLocation(ASTTemplArgList->LAngleLoc);
  AddSourceLocation(ASTTemplArgList->RAngleLoc);
  Record->push_back(ASTTemplArgList->NumTemplateArgs);
  const TemplateArgumentLoc *TemplArgs = ASTTemplArgList->getTemplateArgs();
  for (int i = 0, e = ASTTemplArgList->NumTemplateArgs; i != e; ++i)
    AddTemplateArgumentLoc(TemplArgs[i]);
}

void ASTRecordWriter::AddUnresolvedSet(const ASTUnresolvedSet &Set) {
  Record->push_back(Set.size());
  for (ASTUnresolvedSet::const_iterator
         I = Set.begin(), E = Set.end(); I != E; ++I) {
    AddDeclRef(I.getDecl());
    Record->push_back(I.getAccess());
  }
}

// FIXME: Move this out of the main ASTRecordWriter interface.
void ASTRecordWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base) {
  Record->push_back(Base.isVirtual());
  Record->push_back(Base.isBaseOfClass());
  Record->push_back(Base.getAccessSpecifierAsWritten());
  Record->push_back(Base.getInheritConstructors());
  AddTypeSourceInfo(Base.getTypeSourceInfo());
  AddSourceRange(Base.getSourceRange());
  AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
                                          : SourceLocation());
}

static uint64_t EmitCXXBaseSpecifiers(ASTContext &Context, ASTWriter &W,
                                      ArrayRef<CXXBaseSpecifier> Bases) {
  ASTWriter::RecordData Record;
  ASTRecordWriter Writer(Context, W, Record);
  Writer.push_back(Bases.size());

  for (auto &Base : Bases)
    Writer.AddCXXBaseSpecifier(Base);

  return Writer.Emit(serialization::DECL_CXX_BASE_SPECIFIERS);
}

// FIXME: Move this out of the main ASTRecordWriter interface.
void ASTRecordWriter::AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases) {
  AddOffset(EmitCXXBaseSpecifiers(getASTContext(), *Writer, Bases));
}

static uint64_t
EmitCXXCtorInitializers(ASTContext &Context, ASTWriter &W,
                        ArrayRef<CXXCtorInitializer *> CtorInits) {
  ASTWriter::RecordData Record;
  ASTRecordWriter Writer(Context, W, Record);
  Writer.push_back(CtorInits.size());

  for (auto *Init : CtorInits) {
    if (Init->isBaseInitializer()) {
      Writer.push_back(CTOR_INITIALIZER_BASE);
      Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());
      Writer.push_back(Init->isBaseVirtual());
    } else if (Init->isDelegatingInitializer()) {
      Writer.push_back(CTOR_INITIALIZER_DELEGATING);
      Writer.AddTypeSourceInfo(Init->getTypeSourceInfo());
    } else if (Init->isMemberInitializer()){
      Writer.push_back(CTOR_INITIALIZER_MEMBER);
      Writer.AddDeclRef(Init->getMember());
    } else {
      Writer.push_back(CTOR_INITIALIZER_INDIRECT_MEMBER);
      Writer.AddDeclRef(Init->getIndirectMember());
    }

    Writer.AddSourceLocation(Init->getMemberLocation());
    Writer.AddStmt(Init->getInit());
    Writer.AddSourceLocation(Init->getLParenLoc());
    Writer.AddSourceLocation(Init->getRParenLoc());
    Writer.push_back(Init->isWritten());
    if (Init->isWritten())
      Writer.push_back(Init->getSourceOrder());
  }

  return Writer.Emit(serialization::DECL_CXX_CTOR_INITIALIZERS);
}

// FIXME: Move this out of the main ASTRecordWriter interface.
void ASTRecordWriter::AddCXXCtorInitializers(
    ArrayRef<CXXCtorInitializer *> CtorInits) {
  AddOffset(EmitCXXCtorInitializers(getASTContext(), *Writer, CtorInits));
}

void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
  auto &Data = D->data();

  Record->push_back(Data.IsLambda);

  BitsPacker DefinitionBits;

#define FIELD(Name, Width, Merge)                                              \
  if (!DefinitionBits.canWriteNextNBits(Width)) {                              \
    Record->push_back(DefinitionBits);                                         \
    DefinitionBits.reset(0);                                                   \
  }                                                                            \
  DefinitionBits.addBits(Data.Name, Width);

#include "clang/AST/CXXRecordDeclDefinitionBits.def"
#undef FIELD

  Record->push_back(DefinitionBits);

  // getODRHash will compute the ODRHash if it has not been previously
  // computed.
  Record->push_back(D->getODRHash());

  bool ModulesCodegen =
      !D->isDependentType() &&
      D->getTemplateSpecializationKind() !=
          TSK_ExplicitInstantiationDeclaration &&
      (Writer->getLangOpts().ModulesDebugInfo || D->isInNamedModule());
  Record->push_back(ModulesCodegen);
  if (ModulesCodegen)
    Writer->AddDeclRef(D, Writer->ModularCodegenDecls);

  // IsLambda bit is already saved.

  AddUnresolvedSet(Data.Conversions.get(getASTContext()));
  Record->push_back(Data.ComputedVisibleConversions);
  if (Data.ComputedVisibleConversions)
    AddUnresolvedSet(Data.VisibleConversions.get(getASTContext()));
  // Data.Definition is the owning decl, no need to write it.

  if (!Data.IsLambda) {
    Record->push_back(Data.NumBases);
    if (Data.NumBases > 0)
      AddCXXBaseSpecifiers(Data.bases());

    // FIXME: Make VBases lazily computed when needed to avoid storing them.
    Record->push_back(Data.NumVBases);
    if (Data.NumVBases > 0)
      AddCXXBaseSpecifiers(Data.vbases());

    AddDeclRef(D->getFirstFriend());
  } else {
    auto &Lambda = D->getLambdaData();

    BitsPacker LambdaBits;
    LambdaBits.addBits(Lambda.DependencyKind, /*Width=*/2);
    LambdaBits.addBit(Lambda.IsGenericLambda);
    LambdaBits.addBits(Lambda.CaptureDefault, /*Width=*/2);
    LambdaBits.addBits(Lambda.NumCaptures, /*Width=*/15);
    LambdaBits.addBit(Lambda.HasKnownInternalLinkage);
    Record->push_back(LambdaBits);

    Record->push_back(Lambda.NumExplicitCaptures);
    Record->push_back(Lambda.ManglingNumber);
    Record->push_back(D->getDeviceLambdaManglingNumber());
    // The lambda context declaration and index within the context are provided
    // separately, so that they can be used for merging.
    AddTypeSourceInfo(Lambda.MethodTyInfo);
    for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
      const LambdaCapture &Capture = Lambda.Captures.front()[I];
      AddSourceLocation(Capture.getLocation());

      BitsPacker CaptureBits;
      CaptureBits.addBit(Capture.isImplicit());
      CaptureBits.addBits(Capture.getCaptureKind(), /*Width=*/3);
      Record->push_back(CaptureBits);

      switch (Capture.getCaptureKind()) {
      case LCK_StarThis:
      case LCK_This:
      case LCK_VLAType:
        break;
      case LCK_ByCopy:
      case LCK_ByRef:
        ValueDecl *Var =
            Capture.capturesVariable() ? Capture.getCapturedVar() : nullptr;
        AddDeclRef(Var);
        AddSourceLocation(Capture.isPackExpansion() ? Capture.getEllipsisLoc()
                                                    : SourceLocation());
        break;
      }
    }
  }
}

void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) {
  const Expr *Init = VD->getInit();
  if (!Init) {
    push_back(0);
    return;
  }

  uint64_t Val = 1;
  if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) {
    // This may trigger evaluation, so run it first
    if (VD->hasInitWithSideEffects())
      Val |= 16;
    assert(ES->CheckedForSideEffects);
    Val |= (ES->HasConstantInitialization ? 2 : 0);
    Val |= (ES->HasConstantDestruction ? 4 : 0);
    const APValue *Evaluated = VD->getEvaluatedValue();
    // If the evaluated result is constant, emit it.
    if (Evaluated && (Evaluated->isInt() || Evaluated->isFloat()))
      Val |= 8;
  }
  push_back(Val);
  if (Val & 8) {
    AddAPValue(*VD->getEvaluatedValue());
  }

  writeStmtRef(Init);
}

void ASTWriter::ReaderInitialized(ASTReader *Reader) {
  assert(Reader && "Cannot remove chain");
  assert((!Chain || Chain == Reader) && "Cannot replace chain");
  assert(FirstDeclID == NextDeclID &&
         FirstTypeID == NextTypeID &&
         FirstIdentID == NextIdentID &&
         FirstMacroID == NextMacroID &&
         FirstSubmoduleID == NextSubmoduleID &&
         FirstSelectorID == NextSelectorID &&
         "Setting chain after writing has started.");

  Chain = Reader;

  FirstSubmoduleID = NUM_PREDEF_SUBMODULE_IDS + Chain->getTotalNumSubmodules();
  FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors();
  NextSelectorID = FirstSelectorID;
  NextSubmoduleID = FirstSubmoduleID;
}

void ASTWriter::IdentifierRead(IdentifierID ID, IdentifierInfo *II) {
  // Don't reuse Type ID from external modules for named modules. See the
  // comments in WriteASTCore for details.
  if (isWritingStdCXXNamedModules())
    return;

  IdentifierID &StoredID = IdentifierIDs[II];
  unsigned OriginalModuleFileIndex = StoredID >> 32;

  // Always keep the local identifier ID. See \p TypeRead() for more
  // information.
  if (OriginalModuleFileIndex == 0 && StoredID)
    return;

  // Otherwise, keep the highest ID since the module file comes later has
  // higher module file indexes.
  if (ID > StoredID)
    StoredID = ID;
}

void ASTWriter::MacroRead(serialization::MacroID ID, MacroInfo *MI) {
  // Always keep the highest ID. See \p TypeRead() for more information.
  MacroID &StoredID = MacroIDs[MI];
  unsigned OriginalModuleFileIndex = StoredID >> 32;

  // Always keep the local macro ID. See \p TypeRead() for more information.
  if (OriginalModuleFileIndex == 0 && StoredID)
    return;

  // Otherwise, keep the highest ID since the module file comes later has
  // higher module file indexes.
  if (ID > StoredID)
    StoredID = ID;
}

void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {
  // Don't reuse Type ID from external modules for named modules. See the
  // comments in WriteASTCore for details.
  if (isWritingStdCXXNamedModules())
    return;

  // Always take the type index that comes in later module files.
  // This copes with an interesting
  // case for chained AST writing where we schedule writing the type and then,
  // later, deserialize the type from another AST. In this case, we want to
  // keep the entry from a later module so that we can properly write it out to
  // the AST file.
  TypeIdx &StoredIdx = TypeIdxs[T];

  // Ignore it if the type comes from the current being written module file.
  // Since the current module file being written logically has the highest
  // index.
  unsigned ModuleFileIndex = StoredIdx.getModuleFileIndex();
  if (ModuleFileIndex == 0 && StoredIdx.getValue())
    return;

  // Otherwise, keep the highest ID since the module file comes later has
  // higher module file indexes.
  if (Idx.getModuleFileIndex() >= StoredIdx.getModuleFileIndex())
    StoredIdx = Idx;
}

void ASTWriter::PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {
  assert(D->isCanonicalDecl() && "predefined decl is not canonical");
  DeclIDs[D] = LocalDeclID(ID);
  PredefinedDecls.insert(D);
}

void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
  // Always keep the highest ID. See \p TypeRead() for more information.
  SelectorID &StoredID = SelectorIDs[S];
  if (ID > StoredID)
    StoredID = ID;
}

void ASTWriter::MacroDefinitionRead(serialization::PreprocessedEntityID ID,
                                    MacroDefinitionRecord *MD) {
  assert(!MacroDefinitions.contains(MD));
  MacroDefinitions[MD] = ID;
}

void ASTWriter::ModuleRead(serialization::SubmoduleID ID, Module *Mod) {
  assert(!SubmoduleIDs.contains(Mod));
  SubmoduleIDs[Mod] = ID;
}

void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(D->isCompleteDefinition());
  assert(!WritingAST && "Already writing the AST!");
  if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
    // We are interested when a PCH decl is modified.
    if (RD->isFromASTFile()) {
      // A forward reference was mutated into a definition. Rewrite it.
      // FIXME: This happens during template instantiation, should we
      // have created a new definition decl instead ?
      assert(isTemplateInstantiation(RD->getTemplateSpecializationKind()) &&
             "completed a tag from another module but not by instantiation?");
      DeclUpdates[RD].push_back(
          DeclUpdate(DeclUpdateKind::CXXInstantiatedClassDefinition));
    }
  }
}

static bool isImportedDeclContext(ASTReader *Chain, const Decl *D) {
  if (D->isFromASTFile())
    return true;

  // The predefined __va_list_tag struct is imported if we imported any decls.
  // FIXME: This is a gross hack.
  return D == D->getASTContext().getVaListTagDecl();
}

void ASTWriter::AddedVisibleDecl(const DeclContext *DC, const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(DC->isLookupContext() &&
          "Should not add lookup results to non-lookup contexts!");

  // TU is handled elsewhere.
  if (isa<TranslationUnitDecl>(DC))
    return;

  // Namespaces are handled elsewhere, except for template instantiations of
  // FunctionTemplateDecls in namespaces. We are interested in cases where the
  // local instantiations are added to an imported context. Only happens when
  // adding ADL lookup candidates, for example templated friends.
  if (isa<NamespaceDecl>(DC) && D->getFriendObjectKind() == Decl::FOK_None &&
      !isa<FunctionTemplateDecl>(D))
    return;

  // We're only interested in cases where a local declaration is added to an
  // imported context.
  if (D->isFromASTFile() || !isImportedDeclContext(Chain, cast<Decl>(DC)))
    return;

  assert(DC == DC->getPrimaryContext() && "added to non-primary context");
  assert(!getDefinitiveDeclContext(DC) && "DeclContext not definitive!");
  assert(!WritingAST && "Already writing the AST!");
  if (UpdatedDeclContexts.insert(DC) && !cast<Decl>(DC)->isFromASTFile()) {
    // We're adding a visible declaration to a predefined decl context. Ensure
    // that we write out all of its lookup results so we don't get a nasty
    // surprise when we try to emit its lookup table.
    llvm::append_range(DeclsToEmitEvenIfUnreferenced, DC->decls());
  }
  DeclsToEmitEvenIfUnreferenced.push_back(D);
}

void ASTWriter::AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(D->isImplicit());

  // We're only interested in cases where a local declaration is added to an
  // imported context.
  if (D->isFromASTFile() || !isImportedDeclContext(Chain, RD))
    return;

  if (!isa<CXXMethodDecl>(D))
    return;

  // A decl coming from PCH was modified.
  assert(RD->isCompleteDefinition());
  assert(!WritingAST && "Already writing the AST!");
  DeclUpdates[RD].push_back(
      DeclUpdate(DeclUpdateKind::CXXAddedImplicitMember, D));
}

void ASTWriter::ResolvedExceptionSpec(const FunctionDecl *FD) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!DoneWritingDeclsAndTypes && "Already done writing updates!");
  if (!Chain) return;
  Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
    // If we don't already know the exception specification for this redecl
    // chain, add an update record for it.
    if (isUnresolvedExceptionSpec(cast<FunctionDecl>(D)
                                      ->getType()
                                      ->castAs<FunctionProtoType>()
                                      ->getExceptionSpecType()))
      DeclUpdates[D].push_back(DeclUpdateKind::CXXResolvedExceptionSpec);
  });
}

void ASTWriter::DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!Chain) return;
  Chain->forEachImportedKeyDecl(FD, [&](const Decl *D) {
    DeclUpdates[D].push_back(
        DeclUpdate(DeclUpdateKind::CXXDeducedReturnType, ReturnType));
  });
}

void ASTWriter::ResolvedOperatorDelete(const CXXDestructorDecl *DD,
                                       const FunctionDecl *Delete,
                                       Expr *ThisArg) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  assert(Delete && "Not given an operator delete");
  if (!Chain) return;
  Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
    DeclUpdates[D].push_back(
        DeclUpdate(DeclUpdateKind::CXXResolvedDtorDelete, Delete));
  });
}

void ASTWriter::ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                           const FunctionDecl *GlobDelete) {
  if (Chain && Chain->isProcessingUpdateRecords())
    return;
  assert(!WritingAST && "Already writing the AST!");
  assert(GlobDelete && "Not given an operator delete");
  if (!Chain)
    return;
  Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
    DeclUpdates[D].push_back(
        DeclUpdate(DeclUpdateKind::CXXResolvedDtorGlobDelete, GlobDelete));
  });
}

void ASTWriter::ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
                                            const FunctionDecl *ArrayDelete) {
  if (Chain && Chain->isProcessingUpdateRecords())
    return;
  assert(!WritingAST && "Already writing the AST!");
  assert(ArrayDelete && "Not given an operator delete");
  if (!Chain)
    return;
  Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
    DeclUpdates[D].push_back(
        DeclUpdate(DeclUpdateKind::CXXResolvedDtorArrayDelete, ArrayDelete));
  });
}

void ASTWriter::ResolvedOperatorGlobArrayDelete(
    const CXXDestructorDecl *DD, const FunctionDecl *GlobArrayDelete) {
  if (Chain && Chain->isProcessingUpdateRecords())
    return;
  assert(!WritingAST && "Already writing the AST!");
  assert(GlobArrayDelete && "Not given an operator delete");
  if (!Chain)
    return;
  Chain->forEachImportedKeyDecl(DD, [&](const Decl *D) {
    DeclUpdates[D].push_back(DeclUpdate(
        DeclUpdateKind::CXXResolvedDtorGlobArrayDelete, GlobArrayDelete));
  });
}

void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return; // Declaration not imported from PCH.

  // The function definition may not have a body due to parsing errors.
  if (!D->doesThisDeclarationHaveABody())
    return;

  // Implicit function decl from a PCH was defined.
  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::CXXAddedFunctionDefinition));
}

void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::CXXAddedVarDefinition));
}

void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  // The function definition may not have a body due to parsing errors.
  if (!D->doesThisDeclarationHaveABody())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::CXXAddedFunctionDefinition));
}

void ASTWriter::InstantiationRequested(const ValueDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  // Since the actual instantiation is delayed, this really means that we need
  // to update the instantiation location.
  SourceLocation POI;
  if (auto *VD = dyn_cast<VarDecl>(D))
    POI = VD->getPointOfInstantiation();
  else
    POI = cast<FunctionDecl>(D)->getPointOfInstantiation();
  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::CXXPointOfInstantiation, POI));
}

void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::CXXInstantiatedDefaultArgument, D));
}

void ASTWriter::DefaultMemberInitializerInstantiated(const FieldDecl *D) {
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::CXXInstantiatedDefaultMemberInitializer, D));
}

void ASTWriter::AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                             const ObjCInterfaceDecl *IFD) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!IFD->isFromASTFile())
    return; // Declaration not imported from PCH.

  assert(IFD->getDefinition() && "Category on a class without a definition?");
  ObjCClassesWithCategories.insert(
    const_cast<ObjCInterfaceDecl *>(IFD->getDefinition()));
}

void ASTWriter::DeclarationMarkedUsed(const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");

  // If there is *any* declaration of the entity that's not from an AST file,
  // we can skip writing the update record. We make sure that isUsed() triggers
  // completion of the redeclaration chain of the entity.
  for (auto Prev = D->getMostRecentDecl(); Prev; Prev = Prev->getPreviousDecl())
    if (IsLocalDecl(Prev))
      return;

  DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::DeclMarkedUsed));
}

void ASTWriter::DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPThreadPrivate));
}

void ASTWriter::DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPAllocate, A));
}

void ASTWriter::DeclarationMarkedOpenMPIndirectCall(const Decl *D) {
  if (Chain && Chain->isProcessingUpdateRecords())
    return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPIndirectCall));
}

void ASTWriter::DeclarationMarkedOpenMPDeclareTarget(const Decl *D,
                                                     const Attr *Attr) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!D->isFromASTFile())
    return;

  DeclUpdates[D].push_back(
      DeclUpdate(DeclUpdateKind::DeclMarkedOpenMPDeclareTarget, Attr));
}

void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  assert(!D->isUnconditionallyVisible() && "expected a hidden declaration");
  DeclUpdates[D].push_back(DeclUpdate(DeclUpdateKind::DeclExported, M));
}

void ASTWriter::AddedAttributeToRecord(const Attr *Attr,
                                       const RecordDecl *Record) {
  if (Chain && Chain->isProcessingUpdateRecords()) return;
  assert(!WritingAST && "Already writing the AST!");
  if (!Record->isFromASTFile())
    return;
  DeclUpdates[Record].push_back(
      DeclUpdate(DeclUpdateKind::AddedAttrToRecord, Attr));
}

void ASTWriter::AddedCXXTemplateSpecialization(
    const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {
  assert(!WritingAST && "Already writing the AST!");

  if (!TD->getFirstDecl()->isFromASTFile())
    return;
  if (Chain && Chain->isProcessingUpdateRecords())
    return;

  DeclsToEmitEvenIfUnreferenced.push_back(D);
}

void ASTWriter::AddedCXXTemplateSpecialization(
    const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {
  assert(!WritingAST && "Already writing the AST!");

  if (!TD->getFirstDecl()->isFromASTFile())
    return;
  if (Chain && Chain->isProcessingUpdateRecords())
    return;

  DeclsToEmitEvenIfUnreferenced.push_back(D);
}

void ASTWriter::AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD,
                                               const FunctionDecl *D) {
  assert(!WritingAST && "Already writing the AST!");

  if (!TD->getFirstDecl()->isFromASTFile())
    return;
  if (Chain && Chain->isProcessingUpdateRecords())
    return;

  DeclsToEmitEvenIfUnreferenced.push_back(D);
}

//===----------------------------------------------------------------------===//
//// OMPClause Serialization
////===----------------------------------------------------------------------===//

namespace {

class OMPClauseWriter : public OMPClauseVisitor<OMPClauseWriter> {
  ASTRecordWriter &Record;

public:
  OMPClauseWriter(ASTRecordWriter &Record) : Record(Record) {}
#define GEN_CLANG_CLAUSE_CLASS
#define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);
#include "llvm/Frontend/OpenMP/OMP.inc"
  void writeClause(OMPClause *C);
  void VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C);
  void VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C);
};

}

void ASTRecordWriter::writeOMPClause(OMPClause *C) {
  OMPClauseWriter(*this).writeClause(C);
}

void OMPClauseWriter::writeClause(OMPClause *C) {
  Record.push_back(unsigned(C->getClauseKind()));
  Visit(C);
  Record.AddSourceLocation(C->getBeginLoc());
  Record.AddSourceLocation(C->getEndLoc());
}

void OMPClauseWriter::VisitOMPClauseWithPreInit(OMPClauseWithPreInit *C) {
  Record.push_back(uint64_t(C->getCaptureRegion()));
  Record.AddStmt(C->getPreInitStmt());
}

void OMPClauseWriter::VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getPostUpdateExpr());
}

void OMPClauseWriter::VisitOMPIfClause(OMPIfClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.push_back(uint64_t(C->getNameModifier()));
  Record.AddSourceLocation(C->getNameModifierLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddStmt(C->getCondition());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPFinalClause(OMPFinalClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getCondition());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPNumThreadsClause(OMPNumThreadsClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.writeEnum(C->getModifier());
  Record.AddStmt(C->getNumThreads());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPSafelenClause(OMPSafelenClause *C) {
  Record.AddStmt(C->getSafelen());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPSimdlenClause(OMPSimdlenClause *C) {
  Record.AddStmt(C->getSimdlen());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPSizesClause(OMPSizesClause *C) {
  Record.push_back(C->getNumSizes());
  for (Expr *Size : C->getSizesRefs())
    Record.AddStmt(Size);
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPCountsClause(OMPCountsClause *C) {
  Record.push_back(C->getNumCounts());
  Record.push_back(C->hasOmpFill());
  if (C->hasOmpFill())
    Record.push_back(*C->getOmpFillIndex());
  Record.AddSourceLocation(C->getOmpFillLoc());
  for (Expr *Count : C->getCountsRefs())
    Record.AddStmt(Count);
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPPermutationClause(OMPPermutationClause *C) {
  Record.push_back(C->getNumLoops());
  for (Expr *Size : C->getArgsRefs())
    Record.AddStmt(Size);
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPFullClause(OMPFullClause *C) {}

void OMPClauseWriter::VisitOMPPartialClause(OMPPartialClause *C) {
  Record.AddStmt(C->getFactor());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPLoopRangeClause(OMPLoopRangeClause *C) {
  Record.AddStmt(C->getFirst());
  Record.AddStmt(C->getCount());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getFirstLoc());
  Record.AddSourceLocation(C->getCountLoc());
}

void OMPClauseWriter::VisitOMPAllocatorClause(OMPAllocatorClause *C) {
  Record.AddStmt(C->getAllocator());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPCollapseClause(OMPCollapseClause *C) {
  Record.AddStmt(C->getNumForLoops());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPDetachClause(OMPDetachClause *C) {
  Record.AddStmt(C->getEventHandler());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPDefaultClause(OMPDefaultClause *C) {
  Record.push_back(unsigned(C->getDefaultKind()));
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getDefaultKindKwLoc());
  Record.push_back(unsigned(C->getDefaultVC()));
  Record.AddSourceLocation(C->getDefaultVCLoc());
}

void OMPClauseWriter::VisitOMPThreadsetClause(OMPThreadsetClause *C) {
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getThreadsetKindLoc());
  Record.writeEnum(C->getThreadsetKind());
}

void OMPClauseWriter::VisitOMPTransparentClause(OMPTransparentClause *C) {
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddStmt(C->getImpexType());
}

void OMPClauseWriter::VisitOMPProcBindClause(OMPProcBindClause *C) {
  Record.push_back(unsigned(C->getProcBindKind()));
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getProcBindKindKwLoc());
}

void OMPClauseWriter::VisitOMPScheduleClause(OMPScheduleClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.push_back(C->getScheduleKind());
  Record.push_back(C->getFirstScheduleModifier());
  Record.push_back(C->getSecondScheduleModifier());
  Record.AddStmt(C->getChunkSize());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getFirstScheduleModifierLoc());
  Record.AddSourceLocation(C->getSecondScheduleModifierLoc());
  Record.AddSourceLocation(C->getScheduleKindLoc());
  Record.AddSourceLocation(C->getCommaLoc());
}

void OMPClauseWriter::VisitOMPOrderedClause(OMPOrderedClause *C) {
  Record.push_back(C->getLoopNumIterations().size());
  Record.AddStmt(C->getNumForLoops());
  for (Expr *NumIter : C->getLoopNumIterations())
    Record.AddStmt(NumIter);
  for (unsigned I = 0, E = C->getLoopNumIterations().size(); I <E; ++I)
    Record.AddStmt(C->getLoopCounter(I));
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPNowaitClause(OMPNowaitClause *C) {
  Record.AddStmt(C->getCondition());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPUntiedClause(OMPUntiedClause *) {}

void OMPClauseWriter::VisitOMPMergeableClause(OMPMergeableClause *) {}

void OMPClauseWriter::VisitOMPReadClause(OMPReadClause *) {}

void OMPClauseWriter::VisitOMPWriteClause(OMPWriteClause *) {}

void OMPClauseWriter::VisitOMPUpdateClause(OMPUpdateClause *) {}

void OMPClauseWriter::VisitOMPUpdateDependObjectsClause(
    OMPUpdateDependObjectsClause *C) {
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getArgumentLoc());
  Record.writeEnum(C->getDependencyKind());
}

void OMPClauseWriter::VisitOMPCaptureClause(OMPCaptureClause *) {}

void OMPClauseWriter::VisitOMPCompareClause(OMPCompareClause *) {}

// Save the parameter of fail clause.
void OMPClauseWriter::VisitOMPFailClause(OMPFailClause *C) {
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getFailParameterLoc());
  Record.writeEnum(C->getFailParameter());
}

void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}

void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}

void OMPClauseWriter::VisitOMPAbsentClause(OMPAbsentClause *C) {
  Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto K : C->getDirectiveKinds()) {
    Record.writeEnum(K);
  }
}

void OMPClauseWriter::VisitOMPHoldsClause(OMPHoldsClause *C) {
  Record.AddStmt(C->getExpr());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPContainsClause(OMPContainsClause *C) {
  Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto K : C->getDirectiveKinds()) {
    Record.writeEnum(K);
  }
}

void OMPClauseWriter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}

void OMPClauseWriter::VisitOMPNoOpenMPRoutinesClause(
    OMPNoOpenMPRoutinesClause *) {}

void OMPClauseWriter::VisitOMPNoOpenMPConstructsClause(
    OMPNoOpenMPConstructsClause *) {}

void OMPClauseWriter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {}

void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}

void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}

void OMPClauseWriter::VisitOMPRelaxedClause(OMPRelaxedClause *) {}

void OMPClauseWriter::VisitOMPWeakClause(OMPWeakClause *) {}

void OMPClauseWriter::VisitOMPThreadsClause(OMPThreadsClause *) {}

void OMPClauseWriter::VisitOMPSIMDClause(OMPSIMDClause *) {}

void OMPClauseWriter::VisitOMPNogroupClause(OMPNogroupClause *) {}

void OMPClauseWriter::VisitOMPInitClause(OMPInitClause *C) {
  // Sizes for CreateEmpty on the read side: varlist_size = 1 + NumPrefs, then
  // NumAttrs (total attrs across all pref-specs).
  Record.push_back(C->varlist_size());
  Record.push_back(C->attrs().size());
  // Varlist (interop var + Fr block).
  for (Expr *VE : C->varlist())
    Record.AddStmt(VE);
  Record.writeBool(C->getIsTarget());
  Record.writeBool(C->getIsTargetSync());
  Record.writeBool(C->hasPreferAttrs());
  // Per-pref-spec: attr count + that many attr exprs, in order.
  for (OMPInitClause::PrefView P : C->prefs()) {
    Record.push_back(P.Attrs.size());
    for (Expr *A : P.Attrs)
      Record.AddStmt(A);
  }
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getVarLoc());
}

void OMPClauseWriter::VisitOMPUseClause(OMPUseClause *C) {
  Record.AddStmt(C->getInteropVar());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getVarLoc());
}

void OMPClauseWriter::VisitOMPDestroyClause(OMPDestroyClause *C) {
  Record.AddStmt(C->getInteropVar());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getVarLoc());
}

void OMPClauseWriter::VisitOMPNovariantsClause(OMPNovariantsClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getCondition());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPNocontextClause(OMPNocontextClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getCondition());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPFilterClause(OMPFilterClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getThreadID());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPAlignClause(OMPAlignClause *C) {
  Record.AddStmt(C->getAlignment());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPPrivateClause(OMPPrivateClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->private_copies()) {
    Record.AddStmt(VE);
  }
}

void OMPClauseWriter::VisitOMPFirstprivateClause(OMPFirstprivateClause *C) {
  Record.push_back(C->varlist_size());
  VisitOMPClauseWithPreInit(C);
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->private_copies()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->inits()) {
    Record.AddStmt(VE);
  }
}

void OMPClauseWriter::VisitOMPLastprivateClause(OMPLastprivateClause *C) {
  Record.push_back(C->varlist_size());
  VisitOMPClauseWithPostUpdate(C);
  Record.AddSourceLocation(C->getLParenLoc());
  Record.writeEnum(C->getKind());
  Record.AddSourceLocation(C->getKindLoc());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *E : C->private_copies())
    Record.AddStmt(E);
  for (auto *E : C->source_exprs())
    Record.AddStmt(E);
  for (auto *E : C->destination_exprs())
    Record.AddStmt(E);
  for (auto *E : C->assignment_ops())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPSharedClause(OMPSharedClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
  Record.push_back(C->varlist_size());
  Record.writeEnum(C->getModifier());
  VisitOMPClauseWithPostUpdate(C);
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
  Record.AddDeclarationNameInfo(C->getNameInfo());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *VE : C->privates())
    Record.AddStmt(VE);
  for (auto *E : C->lhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->rhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->reduction_ops())
    Record.AddStmt(E);
  if (C->getModifier() == clang::OMPC_REDUCTION_inscan) {
    for (auto *E : C->copy_ops())
      Record.AddStmt(E);
    for (auto *E : C->copy_array_temps())
      Record.AddStmt(E);
    for (auto *E : C->copy_array_elems())
      Record.AddStmt(E);
  }
  auto PrivateFlags = C->private_var_reduction_flags();
  Record.push_back(std::distance(PrivateFlags.begin(), PrivateFlags.end()));
  for (bool Flag : PrivateFlags)
    Record.push_back(Flag);
}

void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {
  Record.push_back(C->varlist_size());
  VisitOMPClauseWithPostUpdate(C);
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
  Record.AddDeclarationNameInfo(C->getNameInfo());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *VE : C->privates())
    Record.AddStmt(VE);
  for (auto *E : C->lhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->rhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->reduction_ops())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPInReductionClause(OMPInReductionClause *C) {
  Record.push_back(C->varlist_size());
  VisitOMPClauseWithPostUpdate(C);
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddNestedNameSpecifierLoc(C->getQualifierLoc());
  Record.AddDeclarationNameInfo(C->getNameInfo());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *VE : C->privates())
    Record.AddStmt(VE);
  for (auto *E : C->lhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->rhs_exprs())
    Record.AddStmt(E);
  for (auto *E : C->reduction_ops())
    Record.AddStmt(E);
  for (auto *E : C->taskgroup_descriptors())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPLinearClause(OMPLinearClause *C) {
  Record.push_back(C->varlist_size());
  VisitOMPClauseWithPostUpdate(C);
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.push_back(C->getModifier());
  Record.AddSourceLocation(C->getModifierLoc());
  for (auto *VE : C->varlist()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->privates()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->inits()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->updates()) {
    Record.AddStmt(VE);
  }
  for (auto *VE : C->finals()) {
    Record.AddStmt(VE);
  }
  Record.AddStmt(C->getStep());
  Record.AddStmt(C->getCalcStep());
  for (auto *VE : C->used_expressions())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPAlignedClause(OMPAlignedClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  Record.AddStmt(C->getAlignment());
}

void OMPClauseWriter::VisitOMPCopyinClause(OMPCopyinClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *E : C->source_exprs())
    Record.AddStmt(E);
  for (auto *E : C->destination_exprs())
    Record.AddStmt(E);
  for (auto *E : C->assignment_ops())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPCopyprivateClause(OMPCopyprivateClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *E : C->source_exprs())
    Record.AddStmt(E);
  for (auto *E : C->destination_exprs())
    Record.AddStmt(E);
  for (auto *E : C->assignment_ops())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPFlushClause(OMPFlushClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPDepobjClause(OMPDepobjClause *C) {
  Record.AddStmt(C->getDepobj());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getNumLoops());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddStmt(C->getModifier());
  Record.push_back(C->getDependencyKind());
  Record.AddSourceLocation(C->getDependencyLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddSourceLocation(C->getOmpAllMemoryLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
    Record.AddStmt(C->getLoopData(I));
}

void OMPClauseWriter::VisitOMPDeviceClause(OMPDeviceClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.writeEnum(C->getModifier());
  Record.AddStmt(C->getDevice());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPMapClause(OMPMapClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  bool HasIteratorModifier = false;
  for (unsigned I = 0; I < NumberOfOMPMapClauseModifiers; ++I) {
    Record.push_back(C->getMapTypeModifier(I));
    Record.AddSourceLocation(C->getMapTypeModifierLoc(I));
    if (C->getMapTypeModifier(I) == OMPC_MAP_MODIFIER_iterator)
      HasIteratorModifier = true;
  }
  Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());
  Record.AddDeclarationNameInfo(C->getMapperIdInfo());
  Record.push_back(C->getMapType());
  Record.AddSourceLocation(C->getMapLoc());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *E : C->mapperlists())
    Record.AddStmt(E);
  if (HasIteratorModifier)
    Record.AddStmt(C->getIteratorModifier());
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPAllocateClause(OMPAllocateClause *C) {
  Record.push_back(C->varlist_size());
  Record.writeEnum(C->getFirstAllocateModifier());
  Record.writeEnum(C->getSecondAllocateModifier());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getColonLoc());
  Record.AddStmt(C->getAllocator());
  Record.AddStmt(C->getAlignment());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPNumTeamsClause(OMPNumTeamsClause *C) {
  Record.push_back(C->varlist_size());
  Record.writeEnum(C->getModifier());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddStmt(C->getModifierExpr());
  VisitOMPClauseWithPreInit(C);
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPThreadLimitClause(OMPThreadLimitClause *C) {
  Record.push_back(C->varlist_size());
  Record.writeEnum(C->getModifier());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddStmt(C->getModifierExpr());
  VisitOMPClauseWithPreInit(C);
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPPriorityClause(OMPPriorityClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getPriority());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPGrainsizeClause(OMPGrainsizeClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.writeEnum(C->getModifier());
  Record.AddStmt(C->getGrainsize());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPNumTasksClause(OMPNumTasksClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.writeEnum(C->getModifier());
  Record.AddStmt(C->getNumTasks());
  Record.AddSourceLocation(C->getModifierLoc());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPHintClause(OMPHintClause *C) {
  Record.AddStmt(C->getHint());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPDistScheduleClause(OMPDistScheduleClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.push_back(C->getDistScheduleKind());
  Record.AddStmt(C->getChunkSize());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getDistScheduleKindLoc());
  Record.AddSourceLocation(C->getCommaLoc());
}

void OMPClauseWriter::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) {
  Record.push_back(C->getDefaultmapKind());
  Record.push_back(C->getDefaultmapModifier());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getDefaultmapModifierLoc());
  Record.AddSourceLocation(C->getDefaultmapKindLoc());
}

void OMPClauseWriter::VisitOMPToClause(OMPToClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {
    Record.push_back(C->getMotionModifier(I));
    Record.AddSourceLocation(C->getMotionModifierLoc(I));
    if (C->getMotionModifier(I) == OMPC_MOTION_MODIFIER_iterator)
      Record.AddStmt(C->getIteratorModifier());
  }
  Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());
  Record.AddDeclarationNameInfo(C->getMapperIdInfo());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *E : C->mapperlists())
    Record.AddStmt(E);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.writeBool(M.isNonContiguous());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPFromClause(OMPFromClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  for (unsigned I = 0; I < NumberOfOMPMotionModifiers; ++I) {
    Record.push_back(C->getMotionModifier(I));
    Record.AddSourceLocation(C->getMotionModifierLoc(I));
    if (C->getMotionModifier(I) == OMPC_MOTION_MODIFIER_iterator)
      Record.AddStmt(C->getIteratorModifier());
  }
  Record.AddNestedNameSpecifierLoc(C->getMapperQualifierLoc());
  Record.AddDeclarationNameInfo(C->getMapperIdInfo());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *E : C->mapperlists())
    Record.AddStmt(E);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.writeBool(M.isNonContiguous());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPUseDevicePtrClause(OMPUseDevicePtrClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.writeEnum(C->getFallbackModifier());
  Record.AddSourceLocation(C->getFallbackModifierLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *VE : C->private_copies())
    Record.AddStmt(VE);
  for (auto *VE : C->inits())
    Record.AddStmt(VE);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPUseDeviceAddrClause(OMPUseDeviceAddrClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPIsDevicePtrClause(OMPIsDevicePtrClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPHasDeviceAddrClause(OMPHasDeviceAddrClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getUniqueDeclarationsNum());
  Record.push_back(C->getTotalComponentListNum());
  Record.push_back(C->getTotalComponentsNum());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *E : C->varlist())
    Record.AddStmt(E);
  for (auto *D : C->all_decls())
    Record.AddDeclRef(D);
  for (auto N : C->all_num_lists())
    Record.push_back(N);
  for (auto N : C->all_lists_sizes())
    Record.push_back(N);
  for (auto &M : C->all_components()) {
    Record.AddStmt(M.getAssociatedExpression());
    Record.AddDeclRef(M.getAssociatedDeclaration());
  }
}

void OMPClauseWriter::VisitOMPUnifiedAddressClause(OMPUnifiedAddressClause *) {}

void OMPClauseWriter::VisitOMPUnifiedSharedMemoryClause(
    OMPUnifiedSharedMemoryClause *) {}

void OMPClauseWriter::VisitOMPReverseOffloadClause(OMPReverseOffloadClause *) {}

void
OMPClauseWriter::VisitOMPDynamicAllocatorsClause(OMPDynamicAllocatorsClause *) {
}

void OMPClauseWriter::VisitOMPAtomicDefaultMemOrderClause(
    OMPAtomicDefaultMemOrderClause *C) {
  Record.push_back(C->getAtomicDefaultMemOrderKind());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc());
}

void OMPClauseWriter::VisitOMPSelfMapsClause(OMPSelfMapsClause *) {}

void OMPClauseWriter::VisitOMPAtClause(OMPAtClause *C) {
  Record.push_back(C->getAtKind());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getAtKindKwLoc());
}

void OMPClauseWriter::VisitOMPSeverityClause(OMPSeverityClause *C) {
  Record.push_back(C->getSeverityKind());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getSeverityKindKwLoc());
}

void OMPClauseWriter::VisitOMPMessageClause(OMPMessageClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getMessageString());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPNontemporalClause(OMPNontemporalClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (auto *E : C->private_refs())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPInclusiveClause(OMPInclusiveClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPExclusiveClause(OMPExclusiveClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
}

void OMPClauseWriter::VisitOMPOrderClause(OMPOrderClause *C) {
  Record.writeEnum(C->getKind());
  Record.writeEnum(C->getModifier());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getKindKwLoc());
  Record.AddSourceLocation(C->getModifierKwLoc());
}

void OMPClauseWriter::VisitOMPUsesAllocatorsClause(OMPUsesAllocatorsClause *C) {
  Record.push_back(C->getNumberOfAllocators());
  Record.AddSourceLocation(C->getLParenLoc());
  for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
    OMPUsesAllocatorsClause::Data Data = C->getAllocatorData(I);
    Record.AddStmt(Data.Allocator);
    Record.AddStmt(Data.AllocatorTraits);
    Record.AddSourceLocation(Data.LParenLoc);
    Record.AddSourceLocation(Data.RParenLoc);
  }
}

void OMPClauseWriter::VisitOMPAffinityClause(OMPAffinityClause *C) {
  Record.push_back(C->varlist_size());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddStmt(C->getModifier());
  Record.AddSourceLocation(C->getColonLoc());
  for (Expr *E : C->varlist())
    Record.AddStmt(E);
}

void OMPClauseWriter::VisitOMPBindClause(OMPBindClause *C) {
  Record.writeEnum(C->getBindKind());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getBindKindLoc());
}

void OMPClauseWriter::VisitOMPXDynCGroupMemClause(OMPXDynCGroupMemClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.AddStmt(C->getSize());
  Record.AddSourceLocation(C->getLParenLoc());
}

void OMPClauseWriter::VisitOMPDynGroupprivateClause(
    OMPDynGroupprivateClause *C) {
  VisitOMPClauseWithPreInit(C);
  Record.push_back(C->getDynGroupprivateModifier());
  Record.push_back(C->getDynGroupprivateFallbackModifier());
  Record.AddStmt(C->getSize());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getDynGroupprivateModifierLoc());
  Record.AddSourceLocation(C->getDynGroupprivateFallbackModifierLoc());
}

void OMPClauseWriter::VisitOMPDoacrossClause(OMPDoacrossClause *C) {
  Record.push_back(C->varlist_size());
  Record.push_back(C->getNumLoops());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.push_back(C->getDependenceType());
  Record.AddSourceLocation(C->getDependenceLoc());
  Record.AddSourceLocation(C->getColonLoc());
  for (auto *VE : C->varlist())
    Record.AddStmt(VE);
  for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I)
    Record.AddStmt(C->getLoopData(I));
}

void OMPClauseWriter::VisitOMPXAttributeClause(OMPXAttributeClause *C) {
  Record.AddAttributes(C->getAttrs());
  Record.AddSourceLocation(C->getBeginLoc());
  Record.AddSourceLocation(C->getLParenLoc());
  Record.AddSourceLocation(C->getEndLoc());
}

void OMPClauseWriter::VisitOMPXBareClause(OMPXBareClause *C) {}

void ASTRecordWriter::writeOMPTraitInfo(const OMPTraitInfo *TI) {
  writeUInt32(TI->Sets.size());
  for (const auto &Set : TI->Sets) {
    writeEnum(Set.Kind);
    writeUInt32(Set.Selectors.size());
    for (const auto &Selector : Set.Selectors) {
      writeEnum(Selector.Kind);
      writeBool(Selector.ScoreOrCondition);
      if (Selector.ScoreOrCondition)
        writeExprRef(Selector.ScoreOrCondition);
      writeUInt32(Selector.Properties.size());
      for (const auto &Property : Selector.Properties)
        writeEnum(Property.Kind);
    }
  }
}

void ASTRecordWriter::writeOMPChildren(OMPChildren *Data) {
  if (!Data)
    return;
  writeUInt32(Data->getNumClauses());
  writeUInt32(Data->getNumChildren());
  writeBool(Data->hasAssociatedStmt());
  for (unsigned I = 0, E = Data->getNumClauses(); I < E; ++I)
    writeOMPClause(Data->getClauses()[I]);
  if (Data->hasAssociatedStmt())
    AddStmt(Data->getAssociatedStmt());
  for (unsigned I = 0, E = Data->getNumChildren(); I < E; ++I)
    AddStmt(Data->getChildren()[I]);
}

void ASTRecordWriter::writeOpenACCVarList(const OpenACCClauseWithVarList *C) {
  writeUInt32(C->getVarList().size());
  for (Expr *E : C->getVarList())
    AddStmt(E);
}

void ASTRecordWriter::writeOpenACCIntExprList(ArrayRef<Expr *> Exprs) {
  writeUInt32(Exprs.size());
  for (Expr *E : Exprs)
    AddStmt(E);
}

void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
  writeEnum(C->getClauseKind());
  writeSourceLocation(C->getBeginLoc());
  writeSourceLocation(C->getEndLoc());

  switch (C->getClauseKind()) {
  case OpenACCClauseKind::Default: {
    const auto *DC = cast<OpenACCDefaultClause>(C);
    writeSourceLocation(DC->getLParenLoc());
    writeEnum(DC->getDefaultClauseKind());
    return;
  }
  case OpenACCClauseKind::If: {
    const auto *IC = cast<OpenACCIfClause>(C);
    writeSourceLocation(IC->getLParenLoc());
    AddStmt(const_cast<Expr*>(IC->getConditionExpr()));
    return;
  }
  case OpenACCClauseKind::Self: {
    const auto *SC = cast<OpenACCSelfClause>(C);
    writeSourceLocation(SC->getLParenLoc());
    writeBool(SC->isConditionExprClause());
    if (SC->isConditionExprClause()) {
      writeBool(SC->hasConditionExpr());
      if (SC->hasConditionExpr())
        AddStmt(const_cast<Expr *>(SC->getConditionExpr()));
    } else {
      writeUInt32(SC->getVarList().size());
      for (Expr *E : SC->getVarList())
        AddStmt(E);
    }
    return;
  }
  case OpenACCClauseKind::NumGangs: {
    const auto *NGC = cast<OpenACCNumGangsClause>(C);
    writeSourceLocation(NGC->getLParenLoc());
    writeUInt32(NGC->getIntExprs().size());
    for (Expr *E : NGC->getIntExprs())
      AddStmt(E);
    return;
  }
  case OpenACCClauseKind::DeviceNum: {
    const auto *DNC = cast<OpenACCDeviceNumClause>(C);
    writeSourceLocation(DNC->getLParenLoc());
    AddStmt(const_cast<Expr*>(DNC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::DefaultAsync: {
    const auto *DAC = cast<OpenACCDefaultAsyncClause>(C);
    writeSourceLocation(DAC->getLParenLoc());
    AddStmt(const_cast<Expr *>(DAC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::NumWorkers: {
    const auto *NWC = cast<OpenACCNumWorkersClause>(C);
    writeSourceLocation(NWC->getLParenLoc());
    AddStmt(const_cast<Expr*>(NWC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::VectorLength: {
    const auto *NWC = cast<OpenACCVectorLengthClause>(C);
    writeSourceLocation(NWC->getLParenLoc());
    AddStmt(const_cast<Expr*>(NWC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::Private: {
    const auto *PC = cast<OpenACCPrivateClause>(C);
    writeSourceLocation(PC->getLParenLoc());
    writeOpenACCVarList(PC);

    for (const OpenACCPrivateRecipe &R : PC->getInitRecipes()) {
      static_assert(sizeof(R) == 1 * sizeof(int *));
      AddDeclRef(R.AllocaDecl);
    }
    return;
  }
  case OpenACCClauseKind::Host: {
    const auto *HC = cast<OpenACCHostClause>(C);
    writeSourceLocation(HC->getLParenLoc());
    writeOpenACCVarList(HC);
    return;
  }
  case OpenACCClauseKind::Device: {
    const auto *DC = cast<OpenACCDeviceClause>(C);
    writeSourceLocation(DC->getLParenLoc());
    writeOpenACCVarList(DC);
    return;
  }
  case OpenACCClauseKind::FirstPrivate: {
    const auto *FPC = cast<OpenACCFirstPrivateClause>(C);
    writeSourceLocation(FPC->getLParenLoc());
    writeOpenACCVarList(FPC);

    for (const OpenACCFirstPrivateRecipe &R : FPC->getInitRecipes()) {
      static_assert(sizeof(R) == 2 * sizeof(int *));
      AddDeclRef(R.AllocaDecl);
      AddDeclRef(R.InitFromTemporary);
    }
    return;
  }
  case OpenACCClauseKind::Attach: {
    const auto *AC = cast<OpenACCAttachClause>(C);
    writeSourceLocation(AC->getLParenLoc());
    writeOpenACCVarList(AC);
    return;
  }
  case OpenACCClauseKind::Detach: {
    const auto *DC = cast<OpenACCDetachClause>(C);
    writeSourceLocation(DC->getLParenLoc());
    writeOpenACCVarList(DC);
    return;
  }
  case OpenACCClauseKind::Delete: {
    const auto *DC = cast<OpenACCDeleteClause>(C);
    writeSourceLocation(DC->getLParenLoc());
    writeOpenACCVarList(DC);
    return;
  }
  case OpenACCClauseKind::UseDevice: {
    const auto *UDC = cast<OpenACCUseDeviceClause>(C);
    writeSourceLocation(UDC->getLParenLoc());
    writeOpenACCVarList(UDC);
    return;
  }
  case OpenACCClauseKind::DevicePtr: {
    const auto *DPC = cast<OpenACCDevicePtrClause>(C);
    writeSourceLocation(DPC->getLParenLoc());
    writeOpenACCVarList(DPC);
    return;
  }
  case OpenACCClauseKind::NoCreate: {
    const auto *NCC = cast<OpenACCNoCreateClause>(C);
    writeSourceLocation(NCC->getLParenLoc());
    writeOpenACCVarList(NCC);
    return;
  }
  case OpenACCClauseKind::Present: {
    const auto *PC = cast<OpenACCPresentClause>(C);
    writeSourceLocation(PC->getLParenLoc());
    writeOpenACCVarList(PC);
    return;
  }
  case OpenACCClauseKind::Copy:
  case OpenACCClauseKind::PCopy:
  case OpenACCClauseKind::PresentOrCopy: {
    const auto *CC = cast<OpenACCCopyClause>(C);
    writeSourceLocation(CC->getLParenLoc());
    writeEnum(CC->getModifierList());
    writeOpenACCVarList(CC);
    return;
  }
  case OpenACCClauseKind::CopyIn:
  case OpenACCClauseKind::PCopyIn:
  case OpenACCClauseKind::PresentOrCopyIn: {
    const auto *CIC = cast<OpenACCCopyInClause>(C);
    writeSourceLocation(CIC->getLParenLoc());
    writeEnum(CIC->getModifierList());
    writeOpenACCVarList(CIC);
    return;
  }
  case OpenACCClauseKind::CopyOut:
  case OpenACCClauseKind::PCopyOut:
  case OpenACCClauseKind::PresentOrCopyOut: {
    const auto *COC = cast<OpenACCCopyOutClause>(C);
    writeSourceLocation(COC->getLParenLoc());
    writeEnum(COC->getModifierList());
    writeOpenACCVarList(COC);
    return;
  }
  case OpenACCClauseKind::Create:
  case OpenACCClauseKind::PCreate:
  case OpenACCClauseKind::PresentOrCreate: {
    const auto *CC = cast<OpenACCCreateClause>(C);
    writeSourceLocation(CC->getLParenLoc());
    writeEnum(CC->getModifierList());
    writeOpenACCVarList(CC);
    return;
  }
  case OpenACCClauseKind::Async: {
    const auto *AC = cast<OpenACCAsyncClause>(C);
    writeSourceLocation(AC->getLParenLoc());
    writeBool(AC->hasIntExpr());
    if (AC->hasIntExpr())
      AddStmt(const_cast<Expr*>(AC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::Wait: {
    const auto *WC = cast<OpenACCWaitClause>(C);
    writeSourceLocation(WC->getLParenLoc());
    writeBool(WC->getDevNumExpr());
    if (Expr *DNE = WC->getDevNumExpr())
      AddStmt(DNE);
    writeSourceLocation(WC->getQueuesLoc());

    writeOpenACCIntExprList(WC->getQueueIdExprs());
    return;
  }
  case OpenACCClauseKind::DeviceType:
  case OpenACCClauseKind::DType: {
    const auto *DTC = cast<OpenACCDeviceTypeClause>(C);
    writeSourceLocation(DTC->getLParenLoc());
    writeUInt32(DTC->getArchitectures().size());
    for (const DeviceTypeArgument &Arg : DTC->getArchitectures()) {
      writeBool(Arg.getIdentifierInfo());
      if (Arg.getIdentifierInfo())
        AddIdentifierRef(Arg.getIdentifierInfo());
      writeSourceLocation(Arg.getLoc());
    }
    return;
  }
  case OpenACCClauseKind::Reduction: {
    const auto *RC = cast<OpenACCReductionClause>(C);
    writeSourceLocation(RC->getLParenLoc());
    writeEnum(RC->getReductionOp());
    writeOpenACCVarList(RC);

    for (const OpenACCReductionRecipe &R : RC->getRecipes()) {
      AddDeclRef(R.AllocaDecl);

      static_assert(sizeof(OpenACCReductionRecipe::CombinerRecipe) ==
                    3 * sizeof(int *));
      writeUInt32(R.CombinerRecipes.size());

      for (auto &CombinerRecipe : R.CombinerRecipes) {
        AddDeclRef(CombinerRecipe.LHS);
        AddDeclRef(CombinerRecipe.RHS);
        AddStmt(CombinerRecipe.Op);
      }
    }
    return;
  }
  case OpenACCClauseKind::Seq:
  case OpenACCClauseKind::Independent:
  case OpenACCClauseKind::NoHost:
  case OpenACCClauseKind::Auto:
  case OpenACCClauseKind::Finalize:
  case OpenACCClauseKind::IfPresent:
    // Nothing to do here, there is no additional information beyond the
    // begin/end loc and clause kind.
    return;
  case OpenACCClauseKind::Collapse: {
    const auto *CC = cast<OpenACCCollapseClause>(C);
    writeSourceLocation(CC->getLParenLoc());
    writeBool(CC->hasForce());
    AddStmt(const_cast<Expr *>(CC->getLoopCount()));
    return;
  }
  case OpenACCClauseKind::Tile: {
    const auto *TC = cast<OpenACCTileClause>(C);
    writeSourceLocation(TC->getLParenLoc());
    writeUInt32(TC->getSizeExprs().size());
    for (Expr *E : TC->getSizeExprs())
      AddStmt(E);
    return;
  }
  case OpenACCClauseKind::Gang: {
    const auto *GC = cast<OpenACCGangClause>(C);
    writeSourceLocation(GC->getLParenLoc());
    writeUInt32(GC->getNumExprs());
    for (unsigned I = 0; I < GC->getNumExprs(); ++I) {
      writeEnum(GC->getExpr(I).first);
      AddStmt(const_cast<Expr *>(GC->getExpr(I).second));
    }
    return;
  }
  case OpenACCClauseKind::Worker: {
    const auto *WC = cast<OpenACCWorkerClause>(C);
    writeSourceLocation(WC->getLParenLoc());
    writeBool(WC->hasIntExpr());
    if (WC->hasIntExpr())
      AddStmt(const_cast<Expr *>(WC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::Vector: {
    const auto *VC = cast<OpenACCVectorClause>(C);
    writeSourceLocation(VC->getLParenLoc());
    writeBool(VC->hasIntExpr());
    if (VC->hasIntExpr())
      AddStmt(const_cast<Expr *>(VC->getIntExpr()));
    return;
  }
  case OpenACCClauseKind::Link: {
    const auto *LC = cast<OpenACCLinkClause>(C);
    writeSourceLocation(LC->getLParenLoc());
    writeOpenACCVarList(LC);
    return;
  }
  case OpenACCClauseKind::DeviceResident: {
    const auto *DRC = cast<OpenACCDeviceResidentClause>(C);
    writeSourceLocation(DRC->getLParenLoc());
    writeOpenACCVarList(DRC);
    return;
  }

  case OpenACCClauseKind::Bind: {
    const auto *BC = cast<OpenACCBindClause>(C);
    writeSourceLocation(BC->getLParenLoc());
    writeBool(BC->isStringArgument());
    if (BC->isStringArgument())
      AddStmt(const_cast<StringLiteral *>(BC->getStringArgument()));
    else
      AddIdentifierRef(BC->getIdentifierArgument());

    return;
  }
  case OpenACCClauseKind::Invalid:
  case OpenACCClauseKind::Shortloop:
    llvm_unreachable("Clause serialization not yet implemented");
  }
  llvm_unreachable("Invalid Clause Kind");
}

void ASTRecordWriter::writeOpenACCClauseList(
    ArrayRef<const OpenACCClause *> Clauses) {
  for (const OpenACCClause *Clause : Clauses)
    writeOpenACCClause(Clause);
}
void ASTRecordWriter::AddOpenACCRoutineDeclAttr(
    const OpenACCRoutineDeclAttr *A) {
  // We have to write the size so that the reader can do a resize. Unlike the
  // Decl version of this, we can't count on trailing storage to get this right.
  writeUInt32(A->Clauses.size());
  writeOpenACCClauseList(A->Clauses);
}
