//===--- ASTWriterDecl.cpp - Declaration Serialization --------------------===//
//
// 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 implements serialization for Declarations.
//
//===----------------------------------------------------------------------===//

#include "ASTCommon.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTRecordWriter.h"
#include "llvm/Bitstream/BitstreamWriter.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>
using namespace clang;
using namespace serialization;

//===----------------------------------------------------------------------===//
// Declaration serialization
//===----------------------------------------------------------------------===//

namespace clang {
  class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> {
    ASTWriter &Writer;
    ASTRecordWriter Record;

    serialization::DeclCode Code;
    unsigned AbbrevToUse;

    bool GeneratingReducedBMI = false;

  public:
    ASTDeclWriter(ASTWriter &Writer, ASTContext &Context,
                  ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI)
        : Writer(Writer), Record(Context, Writer, Record),
          Code((serialization::DeclCode)0), AbbrevToUse(0),
          GeneratingReducedBMI(GeneratingReducedBMI) {}

    uint64_t Emit(Decl *D) {
      if (!Code)
        llvm::report_fatal_error(StringRef("unexpected declaration kind '") +
            D->getDeclKindName() + "'");
      return Record.Emit(Code, AbbrevToUse);
    }

    void Visit(Decl *D);

    void VisitDecl(Decl *D);
    void VisitPragmaCommentDecl(PragmaCommentDecl *D);
    void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D);
    void VisitTranslationUnitDecl(TranslationUnitDecl *D);
    void VisitNamedDecl(NamedDecl *D);
    void VisitLabelDecl(LabelDecl *LD);
    void VisitNamespaceDecl(NamespaceDecl *D);
    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
    void VisitTypeDecl(TypeDecl *D);
    void VisitTypedefNameDecl(TypedefNameDecl *D);
    void VisitTypedefDecl(TypedefDecl *D);
    void VisitTypeAliasDecl(TypeAliasDecl *D);
    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
    void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D);
    void VisitTagDecl(TagDecl *D);
    void VisitEnumDecl(EnumDecl *D);
    void VisitRecordDecl(RecordDecl *D);
    void VisitCXXRecordDecl(CXXRecordDecl *D);
    void VisitClassTemplateSpecializationDecl(
                                            ClassTemplateSpecializationDecl *D);
    void VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *D);
    void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
    void VisitVarTemplatePartialSpecializationDecl(
        VarTemplatePartialSpecializationDecl *D);
    void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
    void VisitValueDecl(ValueDecl *D);
    void VisitEnumConstantDecl(EnumConstantDecl *D);
    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
    void VisitDeclaratorDecl(DeclaratorDecl *D);
    void VisitFunctionDecl(FunctionDecl *D);
    void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D);
    void VisitCXXMethodDecl(CXXMethodDecl *D);
    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
    void VisitCXXConversionDecl(CXXConversionDecl *D);
    void VisitFieldDecl(FieldDecl *D);
    void VisitMSPropertyDecl(MSPropertyDecl *D);
    void VisitMSGuidDecl(MSGuidDecl *D);
    void VisitUnnamedGlobalConstantDecl(UnnamedGlobalConstantDecl *D);
    void VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D);
    void VisitIndirectFieldDecl(IndirectFieldDecl *D);
    void VisitVarDecl(VarDecl *D);
    void VisitImplicitParamDecl(ImplicitParamDecl *D);
    void VisitParmVarDecl(ParmVarDecl *D);
    void VisitDecompositionDecl(DecompositionDecl *D);
    void VisitBindingDecl(BindingDecl *D);
    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
    void VisitTemplateDecl(TemplateDecl *D);
    void VisitConceptDecl(ConceptDecl *D);
    void VisitImplicitConceptSpecializationDecl(
        ImplicitConceptSpecializationDecl *D);
    void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D);
    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
    void VisitClassTemplateDecl(ClassTemplateDecl *D);
    void VisitVarTemplateDecl(VarTemplateDecl *D);
    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
    void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
    void VisitUsingDecl(UsingDecl *D);
    void VisitUsingEnumDecl(UsingEnumDecl *D);
    void VisitUsingPackDecl(UsingPackDecl *D);
    void VisitUsingShadowDecl(UsingShadowDecl *D);
    void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
    void VisitExportDecl(ExportDecl *D);
    void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
    void VisitTopLevelStmtDecl(TopLevelStmtDecl *D);
    void VisitImportDecl(ImportDecl *D);
    void VisitAccessSpecDecl(AccessSpecDecl *D);
    void VisitFriendDecl(FriendDecl *D);
    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
    void VisitStaticAssertDecl(StaticAssertDecl *D);
    void VisitBlockDecl(BlockDecl *D);
    void VisitCapturedDecl(CapturedDecl *D);
    void VisitEmptyDecl(EmptyDecl *D);
    void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D);
    void VisitDeclContext(DeclContext *DC);
    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
    void VisitHLSLBufferDecl(HLSLBufferDecl *D);

    // FIXME: Put in the same order is DeclNodes.td?
    void VisitObjCMethodDecl(ObjCMethodDecl *D);
    void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D);
    void VisitObjCContainerDecl(ObjCContainerDecl *D);
    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
    void VisitObjCIvarDecl(ObjCIvarDecl *D);
    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
    void VisitObjCCategoryDecl(ObjCCategoryDecl *D);
    void VisitObjCImplDecl(ObjCImplDecl *D);
    void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
    void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
    void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
    void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
    void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
    void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
    void VisitOMPAllocateDecl(OMPAllocateDecl *D);
    void VisitOMPRequiresDecl(OMPRequiresDecl *D);
    void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
    void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
    void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);

    /// Add an Objective-C type parameter list to the given record.
    void AddObjCTypeParamList(ObjCTypeParamList *typeParams) {
      // Empty type parameter list.
      if (!typeParams) {
        Record.push_back(0);
        return;
      }

      Record.push_back(typeParams->size());
      for (auto *typeParam : *typeParams) {
        Record.AddDeclRef(typeParam);
      }
      Record.AddSourceLocation(typeParams->getLAngleLoc());
      Record.AddSourceLocation(typeParams->getRAngleLoc());
    }

    /// Collect the first declaration from each module file that provides a
    /// declaration of D.
    void 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[Writer.Chain->getOwningModuleFile(R)] = R;
        else if (IncludeLocal)
          Firsts[nullptr] = R;
      }
    }

    /// Add to the record the first declaration from each module file that
    /// provides a declaration of D. The intent is to provide a sufficient
    /// set such that reloading this set will load all current redeclarations.
    void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) {
      llvm::MapVector<ModuleFile *, const Decl *> Firsts;
      CollectFirstDeclFromEachModule(D, IncludeLocal, Firsts);

      for (const auto &F : Firsts)
        Record.AddDeclRef(F.second);
    }

    /// Add to the record the first template specialization from each module
    /// file that provides a declaration of D. We store the DeclId and an
    /// ODRHash of the template arguments of D which should provide enough
    /// information to load D only if the template instantiator needs it.
    void AddFirstSpecializationDeclFromEachModule(
        const Decl *D, llvm::SmallVectorImpl<const Decl *> &SpecsInMap,
        llvm::SmallVectorImpl<const Decl *> &PartialSpecsInMap) {
      assert((isa<ClassTemplateSpecializationDecl>(D) ||
              isa<VarTemplateSpecializationDecl>(D) || isa<FunctionDecl>(D)) &&
             "Must not be called with other decls");
      llvm::MapVector<ModuleFile *, const Decl *> Firsts;
      CollectFirstDeclFromEachModule(D, /*IncludeLocal*/ true, Firsts);

      for (const auto &F : Firsts) {
        if (isa<ClassTemplatePartialSpecializationDecl,
                VarTemplatePartialSpecializationDecl>(F.second))
          PartialSpecsInMap.push_back(F.second);
        else
          SpecsInMap.push_back(F.second);
      }
    }

    /// Get the specialization decl from an entry in the specialization list.
    template <typename EntryType>
    typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
    getSpecializationDecl(EntryType &T) {
      return RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::getDecl(&T);
    }

    /// Get the list of partial specializations from a template's common ptr.
    template<typename T>
    decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) {
      return Common->PartialSpecializations;
    }
    MutableArrayRef<FunctionTemplateSpecializationInfo>
    getPartialSpecializations(FunctionTemplateDecl::Common *) {
      return std::nullopt;
    }

    template<typename DeclTy>
    void AddTemplateSpecializations(DeclTy *D) {
      auto *Common = D->getCommonPtr();

      // If we have any lazy specializations, and the external AST source is
      // our chained AST reader, we can just write out the DeclIDs. Otherwise,
      // we need to resolve them to actual declarations.
      if (Writer.Chain != Record.getASTContext().getExternalSource() &&
          Writer.Chain && Writer.Chain->haveUnloadedSpecializations(D)) {
        D->LoadLazySpecializations();
        assert(!Writer.Chain->haveUnloadedSpecializations(D));
      }

      // AddFirstSpecializationDeclFromEachModule might trigger deserialization,
      // invalidating *Specializations iterators.
      llvm::SmallVector<const Decl *, 16> AllSpecs;
      for (auto &Entry : Common->Specializations)
        AllSpecs.push_back(getSpecializationDecl(Entry));
      for (auto &Entry : getPartialSpecializations(Common))
        AllSpecs.push_back(getSpecializationDecl(Entry));

      llvm::SmallVector<const Decl *, 16> Specs;
      llvm::SmallVector<const Decl *, 16> PartialSpecs;
      for (auto *D : AllSpecs) {
        assert(D->isCanonicalDecl() && "non-canonical decl in set");
        AddFirstSpecializationDeclFromEachModule(D, Specs, PartialSpecs);
      }

      Record.AddOffset(Writer.WriteSpecializationInfoLookupTable(
          D, Specs, /*IsPartial=*/false));

      // Function Template Decl doesn't have partial decls.
      if (isa<FunctionTemplateDecl>(D)) {
        assert(PartialSpecs.empty());
        return;
      }

      Record.AddOffset(Writer.WriteSpecializationInfoLookupTable(
          D, PartialSpecs, /*IsPartial=*/true));
    }

    /// Ensure that this template specialization is associated with the specified
    /// template on reload.
    void RegisterTemplateSpecialization(const Decl *Template,
                                        const Decl *Specialization) {
      Template = Template->getCanonicalDecl();

      // If the canonical template is local, we'll write out this specialization
      // when we emit it.
      // FIXME: We can do the same thing if there is any local declaration of
      // the template, to avoid emitting an update record.
      if (!Template->isFromASTFile())
        return;

      // We only need to associate the first local declaration of the
      // specialization. The other declarations will get pulled in by it.
      if (Writer.getFirstLocalDecl(Specialization) != Specialization)
        return;

      if (isa<ClassTemplatePartialSpecializationDecl,
              VarTemplatePartialSpecializationDecl>(Specialization))
        Writer.PartialSpecializationsUpdates[cast<NamedDecl>(Template)]
            .push_back(cast<NamedDecl>(Specialization));
      else
        Writer.SpecializationsUpdates[cast<NamedDecl>(Template)].push_back(
            cast<NamedDecl>(Specialization));
    }
  };
}

bool clang::CanElideDeclDef(const Decl *D) {
  if (auto *FD = dyn_cast<FunctionDecl>(D)) {
    if (FD->isInlined() || FD->isConstexpr())
      return false;

    if (FD->isDependentContext())
      return false;

    if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
      return false;
  }

  if (auto *VD = dyn_cast<VarDecl>(D)) {
    if (!VD->getDeclContext()->getRedeclContext()->isFileContext() ||
        VD->isInline() || VD->isConstexpr() || isa<ParmVarDecl>(VD) ||
        // Constant initialized variable may not affect the ABI, but they
        // may be used in constant evaluation in the frontend, so we have
        // to remain them.
        VD->hasConstantInitialization())
      return false;

    if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
      return false;
  }

  return true;
}

void ASTDeclWriter::Visit(Decl *D) {
  DeclVisitor<ASTDeclWriter>::Visit(D);

  // Source locations require array (variable-length) abbreviations.  The
  // abbreviation infrastructure requires that arrays are encoded last, so
  // we handle it here in the case of those classes derived from DeclaratorDecl
  if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
    if (auto *TInfo = DD->getTypeSourceInfo())
      Record.AddTypeLoc(TInfo->getTypeLoc());
  }

  // Handle FunctionDecl's body here and write it after all other Stmts/Exprs
  // have been written. We want it last because we will not read it back when
  // retrieving it from the AST, we'll just lazily set the offset.
  if (auto *FD = dyn_cast<FunctionDecl>(D)) {
    if (!GeneratingReducedBMI || !CanElideDeclDef(FD)) {
      Record.push_back(FD->doesThisDeclarationHaveABody());
      if (FD->doesThisDeclarationHaveABody())
        Record.AddFunctionDefinition(FD);
    } else
      Record.push_back(0);
  }

  // Similar to FunctionDecls, handle VarDecl's initializer here and write it
  // after all other Stmts/Exprs. We will not read the initializer until after
  // we have finished recursive deserialization, because it can recursively
  // refer back to the variable.
  if (auto *VD = dyn_cast<VarDecl>(D)) {
    if (!GeneratingReducedBMI || !CanElideDeclDef(VD))
      Record.AddVarDeclInit(VD);
    else
      Record.push_back(0);
  }

  // And similarly for FieldDecls. We already serialized whether there is a
  // default member initializer.
  if (auto *FD = dyn_cast<FieldDecl>(D)) {
    if (FD->hasInClassInitializer()) {
      if (Expr *Init = FD->getInClassInitializer()) {
        Record.push_back(1);
        Record.AddStmt(Init);
      } else {
        Record.push_back(0);
        // Initializer has not been instantiated yet.
      }
    }
  }

  // If this declaration is also a DeclContext, write blocks for the
  // declarations that lexically stored inside its context and those
  // declarations that are visible from its context.
  if (auto *DC = dyn_cast<DeclContext>(D))
    VisitDeclContext(DC);
}

void ASTDeclWriter::VisitDecl(Decl *D) {
  BitsPacker DeclBits;

  // The order matters here. It will be better to put the bit with higher
  // probability to be 0 in the end of the bits.
  //
  // Since we're using VBR6 format to store it.
  // It will be pretty effient if all the higher bits are 0.
  // For example, if we need to pack 8 bits into a value and the stored value
  // is 0xf0, the actual stored value will be 0b000111'110000, which takes 12
  // bits actually. However, if we changed the order to be 0x0f, then we can
  // store it as 0b001111, which takes 6 bits only now.
  DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3);
  DeclBits.addBit(D->isReferenced());
  DeclBits.addBit(D->isUsed(false));
  DeclBits.addBits(D->getAccess(), /*BitWidth=*/2);
  DeclBits.addBit(D->isImplicit());
  DeclBits.addBit(D->getDeclContext() != D->getLexicalDeclContext());
  DeclBits.addBit(D->hasAttrs());
  DeclBits.addBit(D->isTopLevelDeclInObjCContainer());
  DeclBits.addBit(D->isInvalidDecl());
  Record.push_back(DeclBits);

  Record.AddDeclRef(cast_or_null<Decl>(D->getDeclContext()));
  if (D->getDeclContext() != D->getLexicalDeclContext())
    Record.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext()));

  if (D->hasAttrs())
    Record.AddAttributes(D->getAttrs());

  Record.push_back(Writer.getSubmoduleID(D->getOwningModule()));

  // If this declaration injected a name into a context different from its
  // lexical context, and that context is an imported namespace, we need to
  // update its visible declarations to include this name.
  //
  // This happens when we instantiate a class with a friend declaration or a
  // function with a local extern declaration, for instance.
  //
  // FIXME: Can we handle this in AddedVisibleDecl instead?
  if (D->isOutOfLine()) {
    auto *DC = D->getDeclContext();
    while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) {
      if (!NS->isFromASTFile())
        break;
      Writer.UpdatedDeclContexts.insert(NS->getPrimaryContext());
      if (!NS->isInlineNamespace())
        break;
      DC = NS->getParent();
    }
  }
}

void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
  StringRef Arg = D->getArg();
  Record.push_back(Arg.size());
  VisitDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Record.push_back(D->getCommentKind());
  Record.AddString(Arg);
  Code = serialization::DECL_PRAGMA_COMMENT;
}

void ASTDeclWriter::VisitPragmaDetectMismatchDecl(
    PragmaDetectMismatchDecl *D) {
  StringRef Name = D->getName();
  StringRef Value = D->getValue();
  Record.push_back(Name.size() + 1 + Value.size());
  VisitDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Record.AddString(Name);
  Record.AddString(Value);
  Code = serialization::DECL_PRAGMA_DETECT_MISMATCH;
}

void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
  llvm_unreachable("Translation units aren't directly serialized");
}

void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) {
  VisitDecl(D);
  Record.AddDeclarationName(D->getDeclName());
  Record.push_back(needsAnonymousDeclarationNumber(D)
                       ? Writer.getAnonymousDeclarationNumber(D)
                       : 0);
}

void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Record.AddTypeRef(QualType(D->getTypeForDecl(), 0));
}

void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) {
  VisitRedeclarable(D);
  VisitTypeDecl(D);
  Record.AddTypeSourceInfo(D->getTypeSourceInfo());
  Record.push_back(D->isModed());
  if (D->isModed())
    Record.AddTypeRef(D->getUnderlyingType());
  Record.AddDeclRef(D->getAnonDeclWithTypedefName(false));
}

void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) {
  VisitTypedefNameDecl(D);
  if (D->getDeclContext() == D->getLexicalDeclContext() &&
      !D->hasAttrs() &&
      !D->isImplicit() &&
      D->getFirstDecl() == D->getMostRecentDecl() &&
      !D->isInvalidDecl() &&
      !D->isTopLevelDeclInObjCContainer() &&
      !D->isModulePrivate() &&
      !needsAnonymousDeclarationNumber(D) &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier)
    AbbrevToUse = Writer.getDeclTypedefAbbrev();

  Code = serialization::DECL_TYPEDEF;
}

void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
  VisitTypedefNameDecl(D);
  Record.AddDeclRef(D->getDescribedAliasTemplate());
  Code = serialization::DECL_TYPEALIAS;
}

void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
  static_assert(DeclContext::NumTagDeclBits == 23,
                "You need to update the serializer after you change the "
                "TagDeclBits");

  VisitRedeclarable(D);
  VisitTypeDecl(D);
  Record.push_back(D->getIdentifierNamespace());

  BitsPacker TagDeclBits;
  TagDeclBits.addBits(llvm::to_underlying(D->getTagKind()), /*BitWidth=*/3);
  TagDeclBits.addBit(!isa<CXXRecordDecl>(D) ? D->isCompleteDefinition() : 0);
  TagDeclBits.addBit(D->isEmbeddedInDeclarator());
  TagDeclBits.addBit(D->isFreeStanding());
  TagDeclBits.addBit(D->isCompleteDefinitionRequired());
  TagDeclBits.addBits(
      D->hasExtInfo() ? 1 : (D->getTypedefNameForAnonDecl() ? 2 : 0),
      /*BitWidth=*/2);
  Record.push_back(TagDeclBits);

  Record.AddSourceRange(D->getBraceRange());

  if (D->hasExtInfo()) {
    Record.AddQualifierInfo(*D->getExtInfo());
  } else if (auto *TD = D->getTypedefNameForAnonDecl()) {
    Record.AddDeclRef(TD);
    Record.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo());
  }
}

void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
  static_assert(DeclContext::NumEnumDeclBits == 43,
                "You need to update the serializer after you change the "
                "EnumDeclBits");

  VisitTagDecl(D);
  Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo());
  if (!D->getIntegerTypeSourceInfo())
    Record.AddTypeRef(D->getIntegerType());
  Record.AddTypeRef(D->getPromotionType());

  BitsPacker EnumDeclBits;
  EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8);
  EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8);
  EnumDeclBits.addBit(D->isScoped());
  EnumDeclBits.addBit(D->isScopedUsingClassTag());
  EnumDeclBits.addBit(D->isFixed());
  Record.push_back(EnumDeclBits);

  Record.push_back(D->getODRHash());

  if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) {
    Record.AddDeclRef(MemberInfo->getInstantiatedFrom());
    Record.push_back(MemberInfo->getTemplateSpecializationKind());
    Record.AddSourceLocation(MemberInfo->getPointOfInstantiation());
  } else {
    Record.AddDeclRef(nullptr);
  }

  if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() &&
      !D->isInvalidDecl() && !D->isImplicit() && !D->hasExtInfo() &&
      !D->getTypedefNameForAnonDecl() &&
      D->getFirstDecl() == D->getMostRecentDecl() &&
      !D->isTopLevelDeclInObjCContainer() &&
      !CXXRecordDecl::classofKind(D->getKind()) &&
      !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() &&
      !needsAnonymousDeclarationNumber(D) &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier)
    AbbrevToUse = Writer.getDeclEnumAbbrev();

  Code = serialization::DECL_ENUM;
}

void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
  static_assert(DeclContext::NumRecordDeclBits == 64,
                "You need to update the serializer after you change the "
                "RecordDeclBits");

  VisitTagDecl(D);

  BitsPacker RecordDeclBits;
  RecordDeclBits.addBit(D->hasFlexibleArrayMember());
  RecordDeclBits.addBit(D->isAnonymousStructOrUnion());
  RecordDeclBits.addBit(D->hasObjectMember());
  RecordDeclBits.addBit(D->hasVolatileMember());
  RecordDeclBits.addBit(D->isNonTrivialToPrimitiveDefaultInitialize());
  RecordDeclBits.addBit(D->isNonTrivialToPrimitiveCopy());
  RecordDeclBits.addBit(D->isNonTrivialToPrimitiveDestroy());
  RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion());
  RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveDestructCUnion());
  RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveCopyCUnion());
  RecordDeclBits.addBit(D->isParamDestroyedInCallee());
  RecordDeclBits.addBits(llvm::to_underlying(D->getArgPassingRestrictions()), 2);
  Record.push_back(RecordDeclBits);

  // Only compute this for C/Objective-C, in C++ this is computed as part
  // of CXXRecordDecl.
  if (!isa<CXXRecordDecl>(D))
    Record.push_back(D->getODRHash());

  if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() &&
      !D->isImplicit() && !D->isInvalidDecl() && !D->hasExtInfo() &&
      !D->getTypedefNameForAnonDecl() &&
      D->getFirstDecl() == D->getMostRecentDecl() &&
      !D->isTopLevelDeclInObjCContainer() &&
      !CXXRecordDecl::classofKind(D->getKind()) &&
      !needsAnonymousDeclarationNumber(D) &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier)
    AbbrevToUse = Writer.getDeclRecordAbbrev();

  Code = serialization::DECL_RECORD;
}

void ASTDeclWriter::VisitValueDecl(ValueDecl *D) {
  VisitNamedDecl(D);
  Record.AddTypeRef(D->getType());
}

void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {
  VisitValueDecl(D);
  Record.push_back(D->getInitExpr()? 1 : 0);
  if (D->getInitExpr())
    Record.AddStmt(D->getInitExpr());
  Record.AddAPSInt(D->getInitVal());

  Code = serialization::DECL_ENUM_CONSTANT;
}

void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
  VisitValueDecl(D);
  Record.AddSourceLocation(D->getInnerLocStart());
  Record.push_back(D->hasExtInfo());
  if (D->hasExtInfo()) {
    DeclaratorDecl::ExtInfo *Info = D->getExtInfo();
    Record.AddQualifierInfo(*Info);
    Record.AddStmt(Info->TrailingRequiresClause);
  }
  // The location information is deferred until the end of the record.
  Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType()
                                           : QualType());
}

void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
  static_assert(DeclContext::NumFunctionDeclBits == 44,
                "You need to update the serializer after you change the "
                "FunctionDeclBits");

  VisitRedeclarable(D);

  Record.push_back(D->getTemplatedKind());
  switch (D->getTemplatedKind()) {
  case FunctionDecl::TK_NonTemplate:
    break;
  case FunctionDecl::TK_DependentNonTemplate:
    Record.AddDeclRef(D->getInstantiatedFromDecl());
    break;
  case FunctionDecl::TK_FunctionTemplate:
    Record.AddDeclRef(D->getDescribedFunctionTemplate());
    break;
  case FunctionDecl::TK_MemberSpecialization: {
    MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo();
    Record.AddDeclRef(MemberInfo->getInstantiatedFrom());
    Record.push_back(MemberInfo->getTemplateSpecializationKind());
    Record.AddSourceLocation(MemberInfo->getPointOfInstantiation());
    break;
  }
  case FunctionDecl::TK_FunctionTemplateSpecialization: {
    FunctionTemplateSpecializationInfo *
      FTSInfo = D->getTemplateSpecializationInfo();

    RegisterTemplateSpecialization(FTSInfo->getTemplate(), D);

    Record.AddDeclRef(FTSInfo->getTemplate());
    Record.push_back(FTSInfo->getTemplateSpecializationKind());

    // Template arguments.
    Record.AddTemplateArgumentList(FTSInfo->TemplateArguments);

    // Template args as written.
    Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
    if (FTSInfo->TemplateArgumentsAsWritten)
      Record.AddASTTemplateArgumentListInfo(
          FTSInfo->TemplateArgumentsAsWritten);

    Record.AddSourceLocation(FTSInfo->getPointOfInstantiation());

    if (MemberSpecializationInfo *MemberInfo =
        FTSInfo->getMemberSpecializationInfo()) {
      Record.push_back(1);
      Record.AddDeclRef(MemberInfo->getInstantiatedFrom());
      Record.push_back(MemberInfo->getTemplateSpecializationKind());
      Record.AddSourceLocation(MemberInfo->getPointOfInstantiation());
    } else {
      Record.push_back(0);
    }

    if (D->isCanonicalDecl()) {
      // Write the template that contains the specializations set. We will
      // add a FunctionTemplateSpecializationInfo to it when reading.
      Record.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl());
    }
    break;
  }
  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
    DependentFunctionTemplateSpecializationInfo *
      DFTSInfo = D->getDependentSpecializationInfo();

    // Candidates.
    Record.push_back(DFTSInfo->getCandidates().size());
    for (FunctionTemplateDecl *FTD : DFTSInfo->getCandidates())
      Record.AddDeclRef(FTD);

    // Templates args.
    Record.push_back(DFTSInfo->TemplateArgumentsAsWritten != nullptr);
    if (DFTSInfo->TemplateArgumentsAsWritten)
      Record.AddASTTemplateArgumentListInfo(
          DFTSInfo->TemplateArgumentsAsWritten);
    break;
  }
  }

  VisitDeclaratorDecl(D);
  Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
  Record.push_back(D->getIdentifierNamespace());

  // The order matters here. It will be better to put the bit with higher
  // probability to be 0 in the end of the bits. See the comments in VisitDecl
  // for details.
  BitsPacker FunctionDeclBits;
  // FIXME: stable encoding
  FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3);
  FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3);
  FunctionDeclBits.addBit(D->isInlineSpecified());
  FunctionDeclBits.addBit(D->isInlined());
  FunctionDeclBits.addBit(D->hasSkippedBody());
  FunctionDeclBits.addBit(D->isVirtualAsWritten());
  FunctionDeclBits.addBit(D->isPureVirtual());
  FunctionDeclBits.addBit(D->hasInheritedPrototype());
  FunctionDeclBits.addBit(D->hasWrittenPrototype());
  FunctionDeclBits.addBit(D->isDeletedBit());
  FunctionDeclBits.addBit(D->isTrivial());
  FunctionDeclBits.addBit(D->isTrivialForCall());
  FunctionDeclBits.addBit(D->isDefaulted());
  FunctionDeclBits.addBit(D->isExplicitlyDefaulted());
  FunctionDeclBits.addBit(D->isIneligibleOrNotSelected());
  FunctionDeclBits.addBits((uint64_t)(D->getConstexprKind()), /*BitWidth=*/2);
  FunctionDeclBits.addBit(D->hasImplicitReturnZero());
  FunctionDeclBits.addBit(D->isMultiVersion());
  FunctionDeclBits.addBit(D->isLateTemplateParsed());
  FunctionDeclBits.addBit(D->FriendConstraintRefersToEnclosingTemplate());
  FunctionDeclBits.addBit(D->usesSEHTry());
  Record.push_back(FunctionDeclBits);

  Record.AddSourceLocation(D->getEndLoc());
  if (D->isExplicitlyDefaulted())
    Record.AddSourceLocation(D->getDefaultLoc());

  Record.push_back(D->getODRHash());

  if (D->isDefaulted() || D->isDeletedAsWritten()) {
    if (auto *FDI = D->getDefalutedOrDeletedInfo()) {
      // Store both that there is an DefaultedOrDeletedInfo and whether it
      // contains a DeletedMessage.
      StringLiteral *DeletedMessage = FDI->getDeletedMessage();
      Record.push_back(1 | (DeletedMessage ? 2 : 0));
      if (DeletedMessage)
        Record.AddStmt(DeletedMessage);

      Record.push_back(FDI->getUnqualifiedLookups().size());
      for (DeclAccessPair P : FDI->getUnqualifiedLookups()) {
        Record.AddDeclRef(P.getDecl());
        Record.push_back(P.getAccess());
      }
    } else {
      Record.push_back(0);
    }
  }

  if (D->getFriendObjectKind()) {
    // For a function defined inline within a class template, we have to force
    // the canonical definition to be the one inside the canonical definition of
    // the template. Remember this relation to deserialize them together.
    if (auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalParent()))
      if (RD->isDependentContext() && RD->isThisDeclarationADefinition()) {
        Writer.RelatedDeclsMap[Writer.GetDeclRef(RD)].push_back(
            Writer.GetDeclRef(D));
      }
  }

  Record.push_back(D->param_size());
  for (auto *P : D->parameters())
    Record.AddDeclRef(P);
  Code = serialization::DECL_FUNCTION;
}

static void addExplicitSpecifier(ExplicitSpecifier ES,
                                 ASTRecordWriter &Record) {
  uint64_t Kind = static_cast<uint64_t>(ES.getKind());
  Kind = Kind << 1 | static_cast<bool>(ES.getExpr());
  Record.push_back(Kind);
  if (ES.getExpr()) {
    Record.AddStmt(ES.getExpr());
  }
}

void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
  addExplicitSpecifier(D->getExplicitSpecifier(), Record);
  Record.AddDeclRef(D->Ctor);
  VisitFunctionDecl(D);
  Record.push_back(static_cast<unsigned char>(D->getDeductionCandidateKind()));
  Code = serialization::DECL_CXX_DEDUCTION_GUIDE;
}

void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
  static_assert(DeclContext::NumObjCMethodDeclBits == 37,
                "You need to update the serializer after you change the "
                "ObjCMethodDeclBits");

  VisitNamedDecl(D);
  // FIXME: convert to LazyStmtPtr?
  // Unlike C/C++, method bodies will never be in header files.
  bool HasBodyStuff = D->getBody() != nullptr;
  Record.push_back(HasBodyStuff);
  if (HasBodyStuff) {
    Record.AddStmt(D->getBody());
  }
  Record.AddDeclRef(D->getSelfDecl());
  Record.AddDeclRef(D->getCmdDecl());
  Record.push_back(D->isInstanceMethod());
  Record.push_back(D->isVariadic());
  Record.push_back(D->isPropertyAccessor());
  Record.push_back(D->isSynthesizedAccessorStub());
  Record.push_back(D->isDefined());
  Record.push_back(D->isOverriding());
  Record.push_back(D->hasSkippedBody());

  Record.push_back(D->isRedeclaration());
  Record.push_back(D->hasRedeclaration());
  if (D->hasRedeclaration()) {
    assert(Record.getASTContext().getObjCMethodRedeclaration(D));
    Record.AddDeclRef(Record.getASTContext().getObjCMethodRedeclaration(D));
  }

  // FIXME: stable encoding for @required/@optional
  Record.push_back(llvm::to_underlying(D->getImplementationControl()));
  // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway/nullability
  Record.push_back(D->getObjCDeclQualifier());
  Record.push_back(D->hasRelatedResultType());
  Record.AddTypeRef(D->getReturnType());
  Record.AddTypeSourceInfo(D->getReturnTypeSourceInfo());
  Record.AddSourceLocation(D->getEndLoc());
  Record.push_back(D->param_size());
  for (const auto *P : D->parameters())
    Record.AddDeclRef(P);

  Record.push_back(D->getSelLocsKind());
  unsigned NumStoredSelLocs = D->getNumStoredSelLocs();
  SourceLocation *SelLocs = D->getStoredSelLocs();
  Record.push_back(NumStoredSelLocs);
  for (unsigned i = 0; i != NumStoredSelLocs; ++i)
    Record.AddSourceLocation(SelLocs[i]);

  Code = serialization::DECL_OBJC_METHOD;
}

void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
  VisitTypedefNameDecl(D);
  Record.push_back(D->Variance);
  Record.push_back(D->Index);
  Record.AddSourceLocation(D->VarianceLoc);
  Record.AddSourceLocation(D->ColonLoc);

  Code = serialization::DECL_OBJC_TYPE_PARAM;
}

void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
  static_assert(DeclContext::NumObjCContainerDeclBits == 64,
                "You need to update the serializer after you change the "
                "ObjCContainerDeclBits");

  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getAtStartLoc());
  Record.AddSourceRange(D->getAtEndRange());
  // Abstract class (no need to define a stable serialization::DECL code).
}

void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
  VisitRedeclarable(D);
  VisitObjCContainerDecl(D);
  Record.AddTypeRef(QualType(D->getTypeForDecl(), 0));
  AddObjCTypeParamList(D->TypeParamList);

  Record.push_back(D->isThisDeclarationADefinition());
  if (D->isThisDeclarationADefinition()) {
    // Write the DefinitionData
    ObjCInterfaceDecl::DefinitionData &Data = D->data();

    Record.AddTypeSourceInfo(D->getSuperClassTInfo());
    Record.AddSourceLocation(D->getEndOfDefinitionLoc());
    Record.push_back(Data.HasDesignatedInitializers);
    Record.push_back(D->getODRHash());

    // Write out the protocols that are directly referenced by the @interface.
    Record.push_back(Data.ReferencedProtocols.size());
    for (const auto *P : D->protocols())
      Record.AddDeclRef(P);
    for (const auto &PL : D->protocol_locs())
      Record.AddSourceLocation(PL);

    // Write out the protocols that are transitively referenced.
    Record.push_back(Data.AllReferencedProtocols.size());
    for (ObjCList<ObjCProtocolDecl>::iterator
              P = Data.AllReferencedProtocols.begin(),
           PEnd = Data.AllReferencedProtocols.end();
         P != PEnd; ++P)
      Record.AddDeclRef(*P);


    if (ObjCCategoryDecl *Cat = D->getCategoryListRaw()) {
      // Ensure that we write out the set of categories for this class.
      Writer.ObjCClassesWithCategories.insert(D);

      // Make sure that the categories get serialized.
      for (; Cat; Cat = Cat->getNextClassCategoryRaw())
        (void)Writer.GetDeclRef(Cat);
    }
  }

  Code = serialization::DECL_OBJC_INTERFACE;
}

void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) {
  VisitFieldDecl(D);
  // FIXME: stable encoding for @public/@private/@protected/@package
  Record.push_back(D->getAccessControl());
  Record.push_back(D->getSynthesize());

  if (D->getDeclContext() == D->getLexicalDeclContext() &&
      !D->hasAttrs() &&
      !D->isImplicit() &&
      !D->isUsed(false) &&
      !D->isInvalidDecl() &&
      !D->isReferenced() &&
      !D->isModulePrivate() &&
      !D->getBitWidth() &&
      !D->hasExtInfo() &&
      D->getDeclName())
    AbbrevToUse = Writer.getDeclObjCIvarAbbrev();

  Code = serialization::DECL_OBJC_IVAR;
}

void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) {
  VisitRedeclarable(D);
  VisitObjCContainerDecl(D);

  Record.push_back(D->isThisDeclarationADefinition());
  if (D->isThisDeclarationADefinition()) {
    Record.push_back(D->protocol_size());
    for (const auto *I : D->protocols())
      Record.AddDeclRef(I);
    for (const auto &PL : D->protocol_locs())
      Record.AddSourceLocation(PL);
    Record.push_back(D->getODRHash());
  }

  Code = serialization::DECL_OBJC_PROTOCOL;
}

void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) {
  VisitFieldDecl(D);
  Code = serialization::DECL_OBJC_AT_DEFS_FIELD;
}

void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) {
  VisitObjCContainerDecl(D);
  Record.AddSourceLocation(D->getCategoryNameLoc());
  Record.AddSourceLocation(D->getIvarLBraceLoc());
  Record.AddSourceLocation(D->getIvarRBraceLoc());
  Record.AddDeclRef(D->getClassInterface());
  AddObjCTypeParamList(D->TypeParamList);
  Record.push_back(D->protocol_size());
  for (const auto *I : D->protocols())
    Record.AddDeclRef(I);
  for (const auto &PL : D->protocol_locs())
    Record.AddSourceLocation(PL);
  Code = serialization::DECL_OBJC_CATEGORY;
}

void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) {
  VisitNamedDecl(D);
  Record.AddDeclRef(D->getClassInterface());
  Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS;
}

void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getAtLoc());
  Record.AddSourceLocation(D->getLParenLoc());
  Record.AddTypeRef(D->getType());
  Record.AddTypeSourceInfo(D->getTypeSourceInfo());
  // FIXME: stable encoding
  Record.push_back((unsigned)D->getPropertyAttributes());
  Record.push_back((unsigned)D->getPropertyAttributesAsWritten());
  // FIXME: stable encoding
  Record.push_back((unsigned)D->getPropertyImplementation());
  Record.AddDeclarationName(D->getGetterName());
  Record.AddSourceLocation(D->getGetterNameLoc());
  Record.AddDeclarationName(D->getSetterName());
  Record.AddSourceLocation(D->getSetterNameLoc());
  Record.AddDeclRef(D->getGetterMethodDecl());
  Record.AddDeclRef(D->getSetterMethodDecl());
  Record.AddDeclRef(D->getPropertyIvarDecl());
  Code = serialization::DECL_OBJC_PROPERTY;
}

void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) {
  VisitObjCContainerDecl(D);
  Record.AddDeclRef(D->getClassInterface());
  // Abstract class (no need to define a stable serialization::DECL code).
}

void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
  VisitObjCImplDecl(D);
  Record.AddSourceLocation(D->getCategoryNameLoc());
  Code = serialization::DECL_OBJC_CATEGORY_IMPL;
}

void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
  VisitObjCImplDecl(D);
  Record.AddDeclRef(D->getSuperClass());
  Record.AddSourceLocation(D->getSuperClassLoc());
  Record.AddSourceLocation(D->getIvarLBraceLoc());
  Record.AddSourceLocation(D->getIvarRBraceLoc());
  Record.push_back(D->hasNonZeroConstructors());
  Record.push_back(D->hasDestructors());
  Record.push_back(D->NumIvarInitializers);
  if (D->NumIvarInitializers)
    Record.AddCXXCtorInitializers(
        llvm::ArrayRef(D->init_begin(), D->init_end()));
  Code = serialization::DECL_OBJC_IMPLEMENTATION;
}

void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
  VisitDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Record.AddDeclRef(D->getPropertyDecl());
  Record.AddDeclRef(D->getPropertyIvarDecl());
  Record.AddSourceLocation(D->getPropertyIvarDeclLoc());
  Record.AddDeclRef(D->getGetterMethodDecl());
  Record.AddDeclRef(D->getSetterMethodDecl());
  Record.AddStmt(D->getGetterCXXConstructor());
  Record.AddStmt(D->getSetterCXXAssignment());
  Code = serialization::DECL_OBJC_PROPERTY_IMPL;
}

void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) {
  VisitDeclaratorDecl(D);
  Record.push_back(D->isMutable());

  Record.push_back((D->StorageKind << 1) | D->BitField);
  if (D->StorageKind == FieldDecl::ISK_CapturedVLAType)
    Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0));
  else if (D->BitField)
    Record.AddStmt(D->getBitWidth());

  if (!D->getDeclName() || D->isPlaceholderVar(Writer.getLangOpts()))
    Record.AddDeclRef(
        Record.getASTContext().getInstantiatedFromUnnamedFieldDecl(D));

  if (D->getDeclContext() == D->getLexicalDeclContext() &&
      !D->hasAttrs() &&
      !D->isImplicit() &&
      !D->isUsed(false) &&
      !D->isInvalidDecl() &&
      !D->isReferenced() &&
      !D->isTopLevelDeclInObjCContainer() &&
      !D->isModulePrivate() &&
      !D->getBitWidth() &&
      !D->hasInClassInitializer() &&
      !D->hasCapturedVLAType() &&
      !D->hasExtInfo() &&
      !ObjCIvarDecl::classofKind(D->getKind()) &&
      !ObjCAtDefsFieldDecl::classofKind(D->getKind()) &&
      D->getDeclName())
    AbbrevToUse = Writer.getDeclFieldAbbrev();

  Code = serialization::DECL_FIELD;
}

void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) {
  VisitDeclaratorDecl(D);
  Record.AddIdentifierRef(D->getGetterId());
  Record.AddIdentifierRef(D->getSetterId());
  Code = serialization::DECL_MS_PROPERTY;
}

void ASTDeclWriter::VisitMSGuidDecl(MSGuidDecl *D) {
  VisitValueDecl(D);
  MSGuidDecl::Parts Parts = D->getParts();
  Record.push_back(Parts.Part1);
  Record.push_back(Parts.Part2);
  Record.push_back(Parts.Part3);
  Record.append(std::begin(Parts.Part4And5), std::end(Parts.Part4And5));
  Code = serialization::DECL_MS_GUID;
}

void ASTDeclWriter::VisitUnnamedGlobalConstantDecl(
    UnnamedGlobalConstantDecl *D) {
  VisitValueDecl(D);
  Record.AddAPValue(D->getValue());
  Code = serialization::DECL_UNNAMED_GLOBAL_CONSTANT;
}

void ASTDeclWriter::VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D) {
  VisitValueDecl(D);
  Record.AddAPValue(D->getValue());
  Code = serialization::DECL_TEMPLATE_PARAM_OBJECT;
}

void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) {
  VisitValueDecl(D);
  Record.push_back(D->getChainingSize());

  for (const auto *P : D->chain())
    Record.AddDeclRef(P);
  Code = serialization::DECL_INDIRECTFIELD;
}

void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
  VisitRedeclarable(D);
  VisitDeclaratorDecl(D);

  // The order matters here. It will be better to put the bit with higher
  // probability to be 0 in the end of the bits. See the comments in VisitDecl
  // for details.
  BitsPacker VarDeclBits;
  VarDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()),
                      /*BitWidth=*/3);

  bool ModulesCodegen = false;
  if (Writer.WritingModule && D->getStorageDuration() == SD_Static &&
      !D->getDescribedVarTemplate()) {
    // When building a C++20 module interface unit or a partition unit, a
    // strong definition in the module interface is provided by the
    // compilation of that unit, not by its users. (Inline variables are still
    // emitted in module users.)
    ModulesCodegen = (Writer.WritingModule->isInterfaceOrPartition() ||
                      (D->hasAttr<DLLExportAttr>() &&
                       Writer.getLangOpts().BuildingPCHWithObjectFile)) &&
                     Record.getASTContext().GetGVALinkageForVariable(D) >=
                         GVA_StrongExternal;
  }
  VarDeclBits.addBit(ModulesCodegen);

  VarDeclBits.addBits(D->getStorageClass(), /*BitWidth=*/3);
  VarDeclBits.addBits(D->getTSCSpec(), /*BitWidth=*/2);
  VarDeclBits.addBits(D->getInitStyle(), /*BitWidth=*/2);
  VarDeclBits.addBit(D->isARCPseudoStrong());

  bool HasDeducedType = false;
  if (!isa<ParmVarDecl>(D)) {
    VarDeclBits.addBit(D->isThisDeclarationADemotedDefinition());
    VarDeclBits.addBit(D->isExceptionVariable());
    VarDeclBits.addBit(D->isNRVOVariable());
    VarDeclBits.addBit(D->isCXXForRangeDecl());

    VarDeclBits.addBit(D->isInline());
    VarDeclBits.addBit(D->isInlineSpecified());
    VarDeclBits.addBit(D->isConstexpr());
    VarDeclBits.addBit(D->isInitCapture());
    VarDeclBits.addBit(D->isPreviousDeclInSameBlockScope());

    VarDeclBits.addBit(D->isEscapingByref());
    HasDeducedType = D->getType()->getContainedDeducedType();
    VarDeclBits.addBit(HasDeducedType);

    if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D))
      VarDeclBits.addBits(llvm::to_underlying(IPD->getParameterKind()),
                          /*Width=*/3);
    else
      VarDeclBits.addBits(0, /*Width=*/3);

    VarDeclBits.addBit(D->isObjCForDecl());
  }

  Record.push_back(VarDeclBits);

  if (ModulesCodegen)
    Writer.AddDeclRef(D, Writer.ModularCodegenDecls);

  if (D->hasAttr<BlocksAttr>()) {
    BlockVarCopyInit Init = Record.getASTContext().getBlockVarCopyInit(D);
    Record.AddStmt(Init.getCopyExpr());
    if (Init.getCopyExpr())
      Record.push_back(Init.canThrow());
  }

  enum {
    VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
  };
  if (VarTemplateDecl *TemplD = D->getDescribedVarTemplate()) {
    Record.push_back(VarTemplate);
    Record.AddDeclRef(TemplD);
  } else if (MemberSpecializationInfo *SpecInfo
               = D->getMemberSpecializationInfo()) {
    Record.push_back(StaticDataMemberSpecialization);
    Record.AddDeclRef(SpecInfo->getInstantiatedFrom());
    Record.push_back(SpecInfo->getTemplateSpecializationKind());
    Record.AddSourceLocation(SpecInfo->getPointOfInstantiation());
  } else {
    Record.push_back(VarNotTemplate);
  }

  if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() &&
      !D->isTopLevelDeclInObjCContainer() &&
      !needsAnonymousDeclarationNumber(D) &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier &&
      !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() &&
      D->getKind() == Decl::Var && !D->isInline() && !D->isConstexpr() &&
      !D->isInitCapture() && !D->isPreviousDeclInSameBlockScope() &&
      !D->isEscapingByref() && !HasDeducedType &&
      D->getStorageDuration() != SD_Static && !D->getDescribedVarTemplate() &&
      !D->getMemberSpecializationInfo() && !D->isObjCForDecl() &&
      !isa<ImplicitParamDecl>(D) && !D->isEscapingByref())
    AbbrevToUse = Writer.getDeclVarAbbrev();

  Code = serialization::DECL_VAR;
}

void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) {
  VisitVarDecl(D);
  Code = serialization::DECL_IMPLICIT_PARAM;
}

void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {
  VisitVarDecl(D);

  // See the implementation of `ParmVarDecl::getParameterIndex()`, which may
  // exceed the size of the normal bitfield. So it may be better to not pack
  // these bits.
  Record.push_back(D->getFunctionScopeIndex());

  BitsPacker ParmVarDeclBits;
  ParmVarDeclBits.addBit(D->isObjCMethodParameter());
  ParmVarDeclBits.addBits(D->getFunctionScopeDepth(), /*BitsWidth=*/7);
  // FIXME: stable encoding
  ParmVarDeclBits.addBits(D->getObjCDeclQualifier(), /*BitsWidth=*/7);
  ParmVarDeclBits.addBit(D->isKNRPromoted());
  ParmVarDeclBits.addBit(D->hasInheritedDefaultArg());
  ParmVarDeclBits.addBit(D->hasUninstantiatedDefaultArg());
  ParmVarDeclBits.addBit(D->getExplicitObjectParamThisLoc().isValid());
  Record.push_back(ParmVarDeclBits);

  if (D->hasUninstantiatedDefaultArg())
    Record.AddStmt(D->getUninstantiatedDefaultArg());
  if (D->getExplicitObjectParamThisLoc().isValid())
    Record.AddSourceLocation(D->getExplicitObjectParamThisLoc());
  Code = serialization::DECL_PARM_VAR;

  // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here
  // we dynamically check for the properties that we optimize for, but don't
  // know are true of all PARM_VAR_DECLs.
  if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() &&
      !D->hasExtInfo() && D->getStorageClass() == 0 && !D->isInvalidDecl() &&
      !D->isTopLevelDeclInObjCContainer() &&
      D->getInitStyle() == VarDecl::CInit && // Can params have anything else?
      D->getInit() == nullptr)               // No default expr.
    AbbrevToUse = Writer.getDeclParmVarAbbrev();

  // Check things we know are true of *every* PARM_VAR_DECL, which is more than
  // just us assuming it.
  assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS");
  assert(!D->isThisDeclarationADemotedDefinition()
         && "PARM_VAR_DECL can't be demoted definition.");
  assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private");
  assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var");
  assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl");
  assert(!D->isStaticDataMember() &&
         "PARM_VAR_DECL can't be static data member");
}

void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) {
  // Record the number of bindings first to simplify deserialization.
  Record.push_back(D->bindings().size());

  VisitVarDecl(D);
  for (auto *B : D->bindings())
    Record.AddDeclRef(B);
  Code = serialization::DECL_DECOMPOSITION;
}

void ASTDeclWriter::VisitBindingDecl(BindingDecl *D) {
  VisitValueDecl(D);
  Record.AddStmt(D->getBinding());
  Code = serialization::DECL_BINDING;
}

void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) {
  VisitDecl(D);
  Record.AddStmt(D->getAsmString());
  Record.AddSourceLocation(D->getRParenLoc());
  Code = serialization::DECL_FILE_SCOPE_ASM;
}

void ASTDeclWriter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) {
  VisitDecl(D);
  Record.AddStmt(D->getStmt());
  Code = serialization::DECL_TOP_LEVEL_STMT_DECL;
}

void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) {
  VisitDecl(D);
  Code = serialization::DECL_EMPTY;
}

void ASTDeclWriter::VisitLifetimeExtendedTemporaryDecl(
    LifetimeExtendedTemporaryDecl *D) {
  VisitDecl(D);
  Record.AddDeclRef(D->getExtendingDecl());
  Record.AddStmt(D->getTemporaryExpr());
  Record.push_back(static_cast<bool>(D->getValue()));
  if (D->getValue())
    Record.AddAPValue(*D->getValue());
  Record.push_back(D->getManglingNumber());
  Code = serialization::DECL_LIFETIME_EXTENDED_TEMPORARY;
}
void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) {
  VisitDecl(D);
  Record.AddStmt(D->getBody());
  Record.AddTypeSourceInfo(D->getSignatureAsWritten());
  Record.push_back(D->param_size());
  for (ParmVarDecl *P : D->parameters())
    Record.AddDeclRef(P);
  Record.push_back(D->isVariadic());
  Record.push_back(D->blockMissingReturnType());
  Record.push_back(D->isConversionFromLambda());
  Record.push_back(D->doesNotEscape());
  Record.push_back(D->canAvoidCopyToHeap());
  Record.push_back(D->capturesCXXThis());
  Record.push_back(D->getNumCaptures());
  for (const auto &capture : D->captures()) {
    Record.AddDeclRef(capture.getVariable());

    unsigned flags = 0;
    if (capture.isByRef()) flags |= 1;
    if (capture.isNested()) flags |= 2;
    if (capture.hasCopyExpr()) flags |= 4;
    Record.push_back(flags);

    if (capture.hasCopyExpr()) Record.AddStmt(capture.getCopyExpr());
  }

  Code = serialization::DECL_BLOCK;
}

void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) {
  Record.push_back(CD->getNumParams());
  VisitDecl(CD);
  Record.push_back(CD->getContextParamPosition());
  Record.push_back(CD->isNothrow() ? 1 : 0);
  // Body is stored by VisitCapturedStmt.
  for (unsigned I = 0; I < CD->getNumParams(); ++I)
    Record.AddDeclRef(CD->getParam(I));
  Code = serialization::DECL_CAPTURED;
}

void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
  static_assert(DeclContext::NumLinkageSpecDeclBits == 17,
                "You need to update the serializer after you change the"
                "LinkageSpecDeclBits");

  VisitDecl(D);
  Record.push_back(llvm::to_underlying(D->getLanguage()));
  Record.AddSourceLocation(D->getExternLoc());
  Record.AddSourceLocation(D->getRBraceLoc());
  Code = serialization::DECL_LINKAGE_SPEC;
}

void ASTDeclWriter::VisitExportDecl(ExportDecl *D) {
  VisitDecl(D);
  Record.AddSourceLocation(D->getRBraceLoc());
  Code = serialization::DECL_EXPORT;
}

void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Code = serialization::DECL_LABEL;
}


void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
  VisitRedeclarable(D);
  VisitNamedDecl(D);

  BitsPacker NamespaceDeclBits;
  NamespaceDeclBits.addBit(D->isInline());
  NamespaceDeclBits.addBit(D->isNested());
  Record.push_back(NamespaceDeclBits);

  Record.AddSourceLocation(D->getBeginLoc());
  Record.AddSourceLocation(D->getRBraceLoc());

  if (D->isFirstDecl())
    Record.AddDeclRef(D->getAnonymousNamespace());
  Code = serialization::DECL_NAMESPACE;

  if (Writer.hasChain() && D->isAnonymousNamespace() &&
      D == D->getMostRecentDecl()) {
    // This is a most recent reopening of the anonymous namespace. If its parent
    // is in a previous PCH (or is the TU), mark that parent for update, because
    // the original namespace always points to the latest re-opening of its
    // anonymous namespace.
    Decl *Parent = cast<Decl>(
        D->getParent()->getRedeclContext()->getPrimaryContext());
    if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) {
      Writer.DeclUpdates[Parent].push_back(
          ASTWriter::DeclUpdate(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, D));
    }
  }
}

void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
  VisitRedeclarable(D);
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getNamespaceLoc());
  Record.AddSourceLocation(D->getTargetNameLoc());
  Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
  Record.AddDeclRef(D->getNamespace());
  Code = serialization::DECL_NAMESPACE_ALIAS;
}

void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getUsingLoc());
  Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
  Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
  Record.AddDeclRef(D->FirstUsingShadow.getPointer());
  Record.push_back(D->hasTypename());
  Record.AddDeclRef(Record.getASTContext().getInstantiatedFromUsingDecl(D));
  Code = serialization::DECL_USING;
}

void ASTDeclWriter::VisitUsingEnumDecl(UsingEnumDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getUsingLoc());
  Record.AddSourceLocation(D->getEnumLoc());
  Record.AddTypeSourceInfo(D->getEnumType());
  Record.AddDeclRef(D->FirstUsingShadow.getPointer());
  Record.AddDeclRef(Record.getASTContext().getInstantiatedFromUsingEnumDecl(D));
  Code = serialization::DECL_USING_ENUM;
}

void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) {
  Record.push_back(D->NumExpansions);
  VisitNamedDecl(D);
  Record.AddDeclRef(D->getInstantiatedFromUsingDecl());
  for (auto *E : D->expansions())
    Record.AddDeclRef(E);
  Code = serialization::DECL_USING_PACK;
}

void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
  VisitRedeclarable(D);
  VisitNamedDecl(D);
  Record.AddDeclRef(D->getTargetDecl());
  Record.push_back(D->getIdentifierNamespace());
  Record.AddDeclRef(D->UsingOrNextShadow);
  Record.AddDeclRef(
      Record.getASTContext().getInstantiatedFromUsingShadowDecl(D));

  if (D->getDeclContext() == D->getLexicalDeclContext() &&
      D->getFirstDecl() == D->getMostRecentDecl() && !D->hasAttrs() &&
      !needsAnonymousDeclarationNumber(D) &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier)
    AbbrevToUse = Writer.getDeclUsingShadowAbbrev();

  Code = serialization::DECL_USING_SHADOW;
}

void ASTDeclWriter::VisitConstructorUsingShadowDecl(
    ConstructorUsingShadowDecl *D) {
  VisitUsingShadowDecl(D);
  Record.AddDeclRef(D->NominatedBaseClassShadowDecl);
  Record.AddDeclRef(D->ConstructedBaseClassShadowDecl);
  Record.push_back(D->IsVirtual);
  Code = serialization::DECL_CONSTRUCTOR_USING_SHADOW;
}

void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
  VisitNamedDecl(D);
  Record.AddSourceLocation(D->getUsingLoc());
  Record.AddSourceLocation(D->getNamespaceKeyLocation());
  Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
  Record.AddDeclRef(D->getNominatedNamespace());
  Record.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()));
  Code = serialization::DECL_USING_DIRECTIVE;
}

void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
  VisitValueDecl(D);
  Record.AddSourceLocation(D->getUsingLoc());
  Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
  Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName());
  Record.AddSourceLocation(D->getEllipsisLoc());
  Code = serialization::DECL_UNRESOLVED_USING_VALUE;
}

void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl(
                                               UnresolvedUsingTypenameDecl *D) {
  VisitTypeDecl(D);
  Record.AddSourceLocation(D->getTypenameLoc());
  Record.AddNestedNameSpecifierLoc(D->getQualifierLoc());
  Record.AddSourceLocation(D->getEllipsisLoc());
  Code = serialization::DECL_UNRESOLVED_USING_TYPENAME;
}

void ASTDeclWriter::VisitUnresolvedUsingIfExistsDecl(
    UnresolvedUsingIfExistsDecl *D) {
  VisitNamedDecl(D);
  Code = serialization::DECL_UNRESOLVED_USING_IF_EXISTS;
}

void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
  VisitRecordDecl(D);

  enum {
    CXXRecNotTemplate = 0,
    CXXRecTemplate,
    CXXRecMemberSpecialization,
    CXXLambda
  };
  if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) {
    Record.push_back(CXXRecTemplate);
    Record.AddDeclRef(TemplD);
  } else if (MemberSpecializationInfo *MSInfo
               = D->getMemberSpecializationInfo()) {
    Record.push_back(CXXRecMemberSpecialization);
    Record.AddDeclRef(MSInfo->getInstantiatedFrom());
    Record.push_back(MSInfo->getTemplateSpecializationKind());
    Record.AddSourceLocation(MSInfo->getPointOfInstantiation());
  } else if (D->isLambda()) {
    // For a lambda, we need some information early for merging.
    Record.push_back(CXXLambda);
    if (auto *Context = D->getLambdaContextDecl()) {
      Record.AddDeclRef(Context);
      Record.push_back(D->getLambdaIndexInContext());
    } else {
      Record.push_back(0);
    }
    // For lambdas inside canonical FunctionDecl remember the mapping.
    if (auto FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext());
        FD && FD->isCanonicalDecl()) {
      Writer.RelatedDeclsMap[Writer.GetDeclRef(FD)].push_back(
          Writer.GetDeclRef(D));
    }
  } else {
    Record.push_back(CXXRecNotTemplate);
  }

  Record.push_back(D->isThisDeclarationADefinition());
  if (D->isThisDeclarationADefinition())
    Record.AddCXXDefinitionData(D);

  if (D->isCompleteDefinition() && D->isInNamedModule())
    Writer.AddDeclRef(D, Writer.ModularCodegenDecls);

  // Store (what we currently believe to be) the key function to avoid
  // deserializing every method so we can compute it.
  //
  // FIXME: Avoid adding the key function if the class is defined in
  // module purview since in that case the key function is meaningless.
  if (D->isCompleteDefinition())
    Record.AddDeclRef(Record.getASTContext().getCurrentKeyFunction(D));

  Code = serialization::DECL_CXX_RECORD;
}

void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
  VisitFunctionDecl(D);
  if (D->isCanonicalDecl()) {
    Record.push_back(D->size_overridden_methods());
    for (const CXXMethodDecl *MD : D->overridden_methods())
      Record.AddDeclRef(MD);
  } else {
    // We only need to record overridden methods once for the canonical decl.
    Record.push_back(0);
  }

  if (D->getDeclContext() == D->getLexicalDeclContext() &&
      D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() &&
      !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier &&
      !D->hasExtInfo() && !D->isExplicitlyDefaulted()) {
    if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate ||
        D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate ||
        D->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
        D->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate)
      AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind());
    else if (D->getTemplatedKind() ==
             FunctionDecl::TK_FunctionTemplateSpecialization) {
      FunctionTemplateSpecializationInfo *FTSInfo =
          D->getTemplateSpecializationInfo();

      if (FTSInfo->TemplateArguments->size() == 1) {
        const TemplateArgument &TA = FTSInfo->TemplateArguments->get(0);
        if (TA.getKind() == TemplateArgument::Type &&
            !FTSInfo->TemplateArgumentsAsWritten &&
            !FTSInfo->getMemberSpecializationInfo())
          AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind());
      }
    } else if (D->getTemplatedKind() ==
               FunctionDecl::TK_DependentFunctionTemplateSpecialization) {
      DependentFunctionTemplateSpecializationInfo *DFTSInfo =
          D->getDependentSpecializationInfo();
      if (!DFTSInfo->TemplateArgumentsAsWritten)
        AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind());
    }
  }

  Code = serialization::DECL_CXX_METHOD;
}

void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
  static_assert(DeclContext::NumCXXConstructorDeclBits == 64,
                "You need to update the serializer after you change the "
                "CXXConstructorDeclBits");

  Record.push_back(D->getTrailingAllocKind());
  addExplicitSpecifier(D->getExplicitSpecifier(), Record);
  if (auto Inherited = D->getInheritedConstructor()) {
    Record.AddDeclRef(Inherited.getShadowDecl());
    Record.AddDeclRef(Inherited.getConstructor());
  }

  VisitCXXMethodDecl(D);
  Code = serialization::DECL_CXX_CONSTRUCTOR;
}

void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
  VisitCXXMethodDecl(D);

  Record.AddDeclRef(D->getOperatorDelete());
  if (D->getOperatorDelete())
    Record.AddStmt(D->getOperatorDeleteThisArg());

  Code = serialization::DECL_CXX_DESTRUCTOR;
}

void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
  addExplicitSpecifier(D->getExplicitSpecifier(), Record);
  VisitCXXMethodDecl(D);
  Code = serialization::DECL_CXX_CONVERSION;
}

void ASTDeclWriter::VisitImportDecl(ImportDecl *D) {
  VisitDecl(D);
  Record.push_back(Writer.getSubmoduleID(D->getImportedModule()));
  ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs();
  Record.push_back(!IdentifierLocs.empty());
  if (IdentifierLocs.empty()) {
    Record.AddSourceLocation(D->getEndLoc());
    Record.push_back(1);
  } else {
    for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I)
      Record.AddSourceLocation(IdentifierLocs[I]);
    Record.push_back(IdentifierLocs.size());
  }
  // Note: the number of source locations must always be the last element in
  // the record.
  Code = serialization::DECL_IMPORT;
}

void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) {
  VisitDecl(D);
  Record.AddSourceLocation(D->getColonLoc());
  Code = serialization::DECL_ACCESS_SPEC;
}

void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) {
  // Record the number of friend type template parameter lists here
  // so as to simplify memory allocation during deserialization.
  Record.push_back(D->NumTPLists);
  VisitDecl(D);
  bool hasFriendDecl = isa<NamedDecl *>(D->Friend);
  Record.push_back(hasFriendDecl);
  if (hasFriendDecl)
    Record.AddDeclRef(D->getFriendDecl());
  else
    Record.AddTypeSourceInfo(D->getFriendType());
  for (unsigned i = 0; i < D->NumTPLists; ++i)
    Record.AddTemplateParameterList(D->getFriendTypeTemplateParameterList(i));
  Record.AddDeclRef(D->getNextFriend());
  Record.push_back(D->UnsupportedFriend);
  Record.AddSourceLocation(D->FriendLoc);
  Record.AddSourceLocation(D->EllipsisLoc);
  Code = serialization::DECL_FRIEND;
}

void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
  VisitDecl(D);
  Record.push_back(D->getNumTemplateParameters());
  for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i)
    Record.AddTemplateParameterList(D->getTemplateParameterList(i));
  Record.push_back(D->getFriendDecl() != nullptr);
  if (D->getFriendDecl())
    Record.AddDeclRef(D->getFriendDecl());
  else
    Record.AddTypeSourceInfo(D->getFriendType());
  Record.AddSourceLocation(D->getFriendLoc());
  Code = serialization::DECL_FRIEND_TEMPLATE;
}

void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
  VisitNamedDecl(D);

  Record.AddTemplateParameterList(D->getTemplateParameters());
  Record.AddDeclRef(D->getTemplatedDecl());
}

void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) {
  VisitTemplateDecl(D);
  Record.AddStmt(D->getConstraintExpr());
  Code = serialization::DECL_CONCEPT;
}

void ASTDeclWriter::VisitImplicitConceptSpecializationDecl(
    ImplicitConceptSpecializationDecl *D) {
  Record.push_back(D->getTemplateArguments().size());
  VisitDecl(D);
  for (const TemplateArgument &Arg : D->getTemplateArguments())
    Record.AddTemplateArgument(Arg);
  Code = serialization::DECL_IMPLICIT_CONCEPT_SPECIALIZATION;
}

void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) {
  Code = serialization::DECL_REQUIRES_EXPR_BODY;
}

void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
  VisitRedeclarable(D);

  // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
  // getCommonPtr() can be used while this is still initializing.
  if (D->isFirstDecl()) {
    // This declaration owns the 'common' pointer, so serialize that data now.
    Record.AddDeclRef(D->getInstantiatedFromMemberTemplate());
    if (D->getInstantiatedFromMemberTemplate())
      Record.push_back(D->isMemberSpecialization());
  }

  VisitTemplateDecl(D);
  Record.push_back(D->getIdentifierNamespace());
}

void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
  VisitRedeclarableTemplateDecl(D);

  if (D->isFirstDecl())
    AddTemplateSpecializations(D);

  // Force emitting the corresponding deduction guide in reduced BMI mode.
  // Otherwise, the deduction guide may be optimized out incorrectly.
  if (Writer.isGeneratingReducedBMI()) {
    auto Name =
        Record.getASTContext().DeclarationNames.getCXXDeductionGuideName(D);
    for (auto *DG : D->getDeclContext()->noload_lookup(Name))
      Writer.GetDeclRef(DG->getCanonicalDecl());
  }

  Code = serialization::DECL_CLASS_TEMPLATE;
}

void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
                                           ClassTemplateSpecializationDecl *D) {
  RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);

  VisitCXXRecordDecl(D);

  llvm::PointerUnion<ClassTemplateDecl *,
                     ClassTemplatePartialSpecializationDecl *> InstFrom
    = D->getSpecializedTemplateOrPartial();
  if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) {
    Record.AddDeclRef(InstFromD);
  } else {
    Record.AddDeclRef(cast<ClassTemplatePartialSpecializationDecl *>(InstFrom));
    Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs());
  }

  Record.AddTemplateArgumentList(&D->getTemplateArgs());
  Record.AddSourceLocation(D->getPointOfInstantiation());
  Record.push_back(D->getSpecializationKind());
  Record.push_back(D->isCanonicalDecl());

  if (D->isCanonicalDecl()) {
    // When reading, we'll add it to the folding set of the following template.
    Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
  }

  bool ExplicitInstantiation =
      D->getTemplateSpecializationKind() ==
          TSK_ExplicitInstantiationDeclaration ||
      D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
  Record.push_back(ExplicitInstantiation);
  if (ExplicitInstantiation) {
    Record.AddSourceLocation(D->getExternKeywordLoc());
    Record.AddSourceLocation(D->getTemplateKeywordLoc());
  }

  const ASTTemplateArgumentListInfo *ArgsWritten =
      D->getTemplateArgsAsWritten();
  Record.push_back(!!ArgsWritten);
  if (ArgsWritten)
    Record.AddASTTemplateArgumentListInfo(ArgsWritten);

  // Mention the implicitly generated C++ deduction guide to make sure the
  // deduction guide will be rewritten as expected.
  //
  // FIXME: Would it be more efficient to add a callback register function
  // in sema to register the deduction guide?
  if (Writer.isWritingStdCXXNamedModules()) {
    auto Name =
        Record.getASTContext().DeclarationNames.getCXXDeductionGuideName(
            D->getSpecializedTemplate());
    for (auto *DG : D->getDeclContext()->noload_lookup(Name))
      Writer.GetDeclRef(DG->getCanonicalDecl());
  }

  Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION;
}

void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
                                    ClassTemplatePartialSpecializationDecl *D) {
  Record.AddTemplateParameterList(D->getTemplateParameters());

  VisitClassTemplateSpecializationDecl(D);

  // These are read/set from/to the first declaration.
  if (D->getPreviousDecl() == nullptr) {
    Record.AddDeclRef(D->getInstantiatedFromMember());
    Record.push_back(D->isMemberSpecialization());
  }

  Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
}

void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) {
  VisitRedeclarableTemplateDecl(D);

  if (D->isFirstDecl())
    AddTemplateSpecializations(D);
  Code = serialization::DECL_VAR_TEMPLATE;
}

void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
    VarTemplateSpecializationDecl *D) {
  RegisterTemplateSpecialization(D->getSpecializedTemplate(), D);

  llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
  InstFrom = D->getSpecializedTemplateOrPartial();
  if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) {
    Record.AddDeclRef(InstFromD);
  } else {
    Record.AddDeclRef(cast<VarTemplatePartialSpecializationDecl *>(InstFrom));
    Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs());
  }

  bool ExplicitInstantiation =
      D->getTemplateSpecializationKind() ==
          TSK_ExplicitInstantiationDeclaration ||
      D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
  Record.push_back(ExplicitInstantiation);
  if (ExplicitInstantiation) {
    Record.AddSourceLocation(D->getExternKeywordLoc());
    Record.AddSourceLocation(D->getTemplateKeywordLoc());
  }

  const ASTTemplateArgumentListInfo *ArgsWritten =
      D->getTemplateArgsAsWritten();
  Record.push_back(!!ArgsWritten);
  if (ArgsWritten)
    Record.AddASTTemplateArgumentListInfo(ArgsWritten);

  Record.AddTemplateArgumentList(&D->getTemplateArgs());
  Record.AddSourceLocation(D->getPointOfInstantiation());
  Record.push_back(D->getSpecializationKind());
  Record.push_back(D->IsCompleteDefinition);

  VisitVarDecl(D);

  Record.push_back(D->isCanonicalDecl());

  if (D->isCanonicalDecl()) {
    // When reading, we'll add it to the folding set of the following template.
    Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
  }

  Code = serialization::DECL_VAR_TEMPLATE_SPECIALIZATION;
}

void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
    VarTemplatePartialSpecializationDecl *D) {
  Record.AddTemplateParameterList(D->getTemplateParameters());

  VisitVarTemplateSpecializationDecl(D);

  // These are read/set from/to the first declaration.
  if (D->getPreviousDecl() == nullptr) {
    Record.AddDeclRef(D->getInstantiatedFromMember());
    Record.push_back(D->isMemberSpecialization());
  }

  Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
}

void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
  VisitRedeclarableTemplateDecl(D);

  if (D->isFirstDecl())
    AddTemplateSpecializations(D);
  Code = serialization::DECL_FUNCTION_TEMPLATE;
}

void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
  Record.push_back(D->hasTypeConstraint());
  VisitTypeDecl(D);

  Record.push_back(D->wasDeclaredWithTypename());

  const TypeConstraint *TC = D->getTypeConstraint();
  if (D->hasTypeConstraint())
    Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr);
  if (TC) {
    auto *CR = TC->getConceptReference();
    Record.push_back(CR != nullptr);
    if (CR)
      Record.AddConceptReference(CR);
    Record.AddStmt(TC->getImmediatelyDeclaredConstraint());
    Record.push_back(D->isExpandedParameterPack());
    if (D->isExpandedParameterPack())
      Record.push_back(D->getNumExpansionParameters());
  }

  bool OwnsDefaultArg = D->hasDefaultArgument() &&
                        !D->defaultArgumentWasInherited();
  Record.push_back(OwnsDefaultArg);
  if (OwnsDefaultArg)
    Record.AddTemplateArgumentLoc(D->getDefaultArgument());

  if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
      D->getDeclContext() == D->getLexicalDeclContext() &&
      !D->isInvalidDecl() && !D->hasAttrs() &&
      !D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&
      D->getDeclName().getNameKind() == DeclarationName::Identifier)
    AbbrevToUse = Writer.getDeclTemplateTypeParmAbbrev();

  Code = serialization::DECL_TEMPLATE_TYPE_PARM;
}

void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
  // For an expanded parameter pack, record the number of expansion types here
  // so that it's easier for deserialization to allocate the right amount of
  // memory.
  Expr *TypeConstraint = D->getPlaceholderTypeConstraint();
  Record.push_back(!!TypeConstraint);
  if (D->isExpandedParameterPack())
    Record.push_back(D->getNumExpansionTypes());

  VisitDeclaratorDecl(D);
  // TemplateParmPosition.
  Record.push_back(D->getDepth());
  Record.push_back(D->getPosition());
  if (TypeConstraint)
    Record.AddStmt(TypeConstraint);

  if (D->isExpandedParameterPack()) {
    for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
      Record.AddTypeRef(D->getExpansionType(I));
      Record.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I));
    }

    Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
  } else {
    // Rest of NonTypeTemplateParmDecl.
    Record.push_back(D->isParameterPack());
    bool OwnsDefaultArg = D->hasDefaultArgument() &&
                          !D->defaultArgumentWasInherited();
    Record.push_back(OwnsDefaultArg);
    if (OwnsDefaultArg)
      Record.AddTemplateArgumentLoc(D->getDefaultArgument());
    Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM;
  }
}

void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
  // For an expanded parameter pack, record the number of expansion types here
  // so that it's easier for deserialization to allocate the right amount of
  // memory.
  if (D->isExpandedParameterPack())
    Record.push_back(D->getNumExpansionTemplateParameters());

  VisitTemplateDecl(D);
  Record.push_back(D->wasDeclaredWithTypename());
  // TemplateParmPosition.
  Record.push_back(D->getDepth());
  Record.push_back(D->getPosition());

  if (D->isExpandedParameterPack()) {
    for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
         I != N; ++I)
      Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I));
    Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
  } else {
    // Rest of TemplateTemplateParmDecl.
    Record.push_back(D->isParameterPack());
    bool OwnsDefaultArg = D->hasDefaultArgument() &&
                          !D->defaultArgumentWasInherited();
    Record.push_back(OwnsDefaultArg);
    if (OwnsDefaultArg)
      Record.AddTemplateArgumentLoc(D->getDefaultArgument());
    Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM;
  }
}

void ASTDeclWriter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
  VisitRedeclarableTemplateDecl(D);
  Code = serialization::DECL_TYPE_ALIAS_TEMPLATE;
}

void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
  VisitDecl(D);
  Record.AddStmt(D->getAssertExpr());
  Record.push_back(D->isFailed());
  Record.AddStmt(D->getMessage());
  Record.AddSourceLocation(D->getRParenLoc());
  Code = serialization::DECL_STATIC_ASSERT;
}

/// Emit the DeclContext part of a declaration context decl.
void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
  static_assert(DeclContext::NumDeclContextBits == 13,
                "You need to update the serializer after you change the "
                "DeclContextBits");

  uint64_t LexicalOffset = 0;
  uint64_t VisibleOffset = 0;

  if (Writer.isGeneratingReducedBMI() && isa<NamespaceDecl>(DC) &&
      cast<NamespaceDecl>(DC)->isFromExplicitGlobalModule()) {
    // In reduced BMI, delay writing lexical and visible block for namespace
    // in the global module fragment. See the comments of DelayedNamespace for
    // details.
    Writer.DelayedNamespace.push_back(cast<NamespaceDecl>(DC));
  } else {
    LexicalOffset =
        Writer.WriteDeclContextLexicalBlock(Record.getASTContext(), DC);
    VisibleOffset =
        Writer.WriteDeclContextVisibleBlock(Record.getASTContext(), DC);
  }

  Record.AddOffset(LexicalOffset);
  Record.AddOffset(VisibleOffset);
}

const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) {
  assert(IsLocalDecl(D) && "expected a local declaration");

  const Decl *Canon = D->getCanonicalDecl();
  if (IsLocalDecl(Canon))
    return Canon;

  const Decl *&CacheEntry = FirstLocalDeclCache[Canon];
  if (CacheEntry)
    return CacheEntry;

  for (const Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl())
    if (IsLocalDecl(Redecl))
      D = Redecl;
  return CacheEntry = D;
}

template <typename T>
void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
  T *First = D->getFirstDecl();
  T *MostRecent = First->getMostRecentDecl();
  T *DAsT = static_cast<T *>(D);
  if (MostRecent != First) {
    assert(isRedeclarableDeclKind(DAsT->getKind()) &&
           "Not considered redeclarable?");

    Record.AddDeclRef(First);

    // Write out a list of local redeclarations of this declaration if it's the
    // first local declaration in the chain.
    const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT);
    if (DAsT == FirstLocal) {
      // Emit a list of all imported first declarations so that we can be sure
      // that all redeclarations visible to this module are before D in the
      // redecl chain.
      unsigned I = Record.size();
      Record.push_back(0);
      if (Writer.Chain)
        AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false);
      // This is the number of imported first declarations + 1.
      Record[I] = Record.size() - I;

      // Collect the set of local redeclarations of this declaration, from
      // newest to oldest.
      ASTWriter::RecordData LocalRedecls;
      ASTRecordWriter LocalRedeclWriter(Record, LocalRedecls);
      for (const Decl *Prev = FirstLocal->getMostRecentDecl();
           Prev != FirstLocal; Prev = Prev->getPreviousDecl())
        if (!Prev->isFromASTFile())
          LocalRedeclWriter.AddDeclRef(Prev);

      // If we have any redecls, write them now as a separate record preceding
      // the declaration itself.
      if (LocalRedecls.empty())
        Record.push_back(0);
      else
        Record.AddOffset(LocalRedeclWriter.Emit(LOCAL_REDECLARATIONS));
    } else {
      Record.push_back(0);
      Record.AddDeclRef(FirstLocal);
    }

    // Make sure that we serialize both the previous and the most-recent
    // declarations, which (transitively) ensures that all declarations in the
    // chain get serialized.
    //
    // FIXME: This is not correct; when we reach an imported declaration we
    // won't emit its previous declaration.
    (void)Writer.GetDeclRef(D->getPreviousDecl());
    (void)Writer.GetDeclRef(MostRecent);
  } else {
    // We use the sentinel value 0 to indicate an only declaration.
    Record.push_back(0);
  }
}

void ASTDeclWriter::VisitHLSLBufferDecl(HLSLBufferDecl *D) {
  VisitNamedDecl(D);
  VisitDeclContext(D);
  Record.push_back(D->isCBuffer());
  Record.AddSourceLocation(D->getLocStart());
  Record.AddSourceLocation(D->getLBraceLoc());
  Record.AddSourceLocation(D->getRBraceLoc());

  Code = serialization::DECL_HLSL_BUFFER;
}

void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
  Record.writeOMPChildren(D->Data);
  VisitDecl(D);
  Code = serialization::DECL_OMP_THREADPRIVATE;
}

void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
  Record.writeOMPChildren(D->Data);
  VisitDecl(D);
  Code = serialization::DECL_OMP_ALLOCATE;
}

void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
  Record.writeOMPChildren(D->Data);
  VisitDecl(D);
  Code = serialization::DECL_OMP_REQUIRES;
}

void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
  static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 15,
                "You need to update the serializer after you change the "
                "NumOMPDeclareReductionDeclBits");

  VisitValueDecl(D);
  Record.AddSourceLocation(D->getBeginLoc());
  Record.AddStmt(D->getCombinerIn());
  Record.AddStmt(D->getCombinerOut());
  Record.AddStmt(D->getCombiner());
  Record.AddStmt(D->getInitOrig());
  Record.AddStmt(D->getInitPriv());
  Record.AddStmt(D->getInitializer());
  Record.push_back(llvm::to_underlying(D->getInitializerKind()));
  Record.AddDeclRef(D->getPrevDeclInScope());
  Code = serialization::DECL_OMP_DECLARE_REDUCTION;
}

void ASTDeclWriter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
  Record.writeOMPChildren(D->Data);
  VisitValueDecl(D);
  Record.AddDeclarationName(D->getVarName());
  Record.AddDeclRef(D->getPrevDeclInScope());
  Code = serialization::DECL_OMP_DECLARE_MAPPER;
}

void ASTDeclWriter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
  VisitVarDecl(D);
  Code = serialization::DECL_OMP_CAPTUREDEXPR;
}

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

namespace {
template <FunctionDecl::TemplatedKind Kind>
std::shared_ptr<llvm::BitCodeAbbrev>
getFunctionDeclAbbrev(serialization::DeclCode Code) {
  using namespace llvm;

  auto Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(Code));
  // RedeclarableDecl
  Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl
  Abv->Add(BitCodeAbbrevOp(Kind));
  if constexpr (Kind == FunctionDecl::TK_NonTemplate) {

  } else if constexpr (Kind == FunctionDecl::TK_FunctionTemplate) {
    // DescribedFunctionTemplate
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
  } else if constexpr (Kind == FunctionDecl::TK_DependentNonTemplate) {
    // Instantiated From Decl
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
  } else if constexpr (Kind == FunctionDecl::TK_MemberSpecialization) {
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedFrom
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                             3)); // TemplateSpecializationKind
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Specialized Location
  } else if constexpr (Kind ==
                       FunctionDecl::TK_FunctionTemplateSpecialization) {
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                             3)); // TemplateSpecializationKind
    Abv->Add(BitCodeAbbrevOp(1)); // Template Argument Size
    Abv->Add(BitCodeAbbrevOp(TemplateArgument::Type)); // Template Argument Kind
    Abv->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted
    Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
    Abv->Add(BitCodeAbbrevOp(0));
    Abv->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Canonical Decl of template
  } else if constexpr (Kind == FunctionDecl::
                                   TK_DependentFunctionTemplateSpecialization) {
    // Candidates of specialization
    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
    Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten
  } else {
    llvm_unreachable("Unknown templated kind?");
  }
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           8)); // Packed DeclBits: ModuleOwnershipKind,
                                // isUsed, isReferenced,  AccessSpecifier,
                                // isImplicit
                                //
                                // The following bits should be 0:
                                // HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer,
                                // isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));     // Identifier
  Abv->Add(BitCodeAbbrevOp(0));                           // AnonDeclNumber
  // ValueDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclaratorDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart
  Abv->Add(BitCodeAbbrevOp(0));                       // HasExtInfo
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
  // FunctionDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      28)); // Packed Function Bits: StorageClass, Inline, InlineSpecified,
            // VirtualAsWritten, Pure, HasInheritedProto, HasWrittenProto,
            // Deleted, Trivial, TrivialForCall, Defaulted, ExplicitlyDefaulted,
            // IsIneligibleOrNotSelected, ImplicitReturnZero, Constexpr,
            // UsesSEHTry, SkippedBody, MultiVersion, LateParsed,
            // FriendConstraintRefersToEnclosingTemplate, Linkage,
            // ShouldSkipCheckingODR
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // LocEnd
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash
  // This Array slurps the rest of the record. Fortunately we want to encode
  // (nearly) all the remaining (variable number of) fields in the same way.
  //
  // This is:
  //         NumParams and Params[] from FunctionDecl, and
  //         NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl.
  //
  //  Add an AbbrevOp for 'size then elements' and use it here.
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
  return Abv;
}

template <FunctionDecl::TemplatedKind Kind>
std::shared_ptr<llvm::BitCodeAbbrev> getCXXMethodAbbrev() {
  return getFunctionDeclAbbrev<Kind>(serialization::DECL_CXX_METHOD);
}
} // namespace

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

  std::shared_ptr<BitCodeAbbrev> Abv;

  // Abbreviation for DECL_FIELD
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD));
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           7)); // Packed DeclBits: ModuleOwnershipKind,
                                // isUsed, isReferenced,  AccessSpecifier,
                                //
                                // The following bits should be 0:
                                // isImplicit, HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer,
                                // isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // ValueDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclaratorDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
  // FieldDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
  Abv->Add(BitCodeAbbrevOp(0));                       // StorageKind
  // Type Source Info
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
  DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_OBJC_IVAR
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR));
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           12)); // Packed DeclBits: HasStandaloneLexicalDC,
                                 // isInvalidDecl, HasAttrs, isImplicit, isUsed,
                                 // isReferenced, TopLevelDeclInObjCContainer,
                                 // AccessSpecifier, ModuleOwnershipKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // ValueDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclaratorDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
  // FieldDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable
  Abv->Add(BitCodeAbbrevOp(0));                       // InitStyle
  // ObjC Ivar
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize
  // Type Source Info
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
  DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_ENUM
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           7)); // Packed DeclBits: ModuleOwnershipKind,
                                // isUsed, isReferenced,  AccessSpecifier,
                                //
                                // The following bits should be 0:
                                // isImplicit, HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer,
                                // isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // TypeDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
  // TagDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition,
           // EmbeddedInDeclarator, IsFreeStanding,
           // isCompleteDefinitionRequired, ExtInfoKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation
  // EnumDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // AddTypeRef
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IntegerType
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getPromotionType
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 20)); // Enum Decl Bits
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // InstantiatedMembEnum
  // DC
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset
  DeclEnumAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_RECORD
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           7)); // Packed DeclBits: ModuleOwnershipKind,
                                // isUsed, isReferenced,  AccessSpecifier,
                                //
                                // The following bits should be 0:
                                // isImplicit, HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer,
                                // isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // TypeDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
  // TagDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition,
           // EmbeddedInDeclarator, IsFreeStanding,
           // isCompleteDefinitionRequired, ExtInfoKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation
  // RecordDecl
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      13)); // Packed Record Decl Bits: FlexibleArrayMember,
            // AnonymousStructUnion, hasObjectMember, hasVolatileMember,
            // isNonTrivialToPrimitiveDefaultInitialize,
            // isNonTrivialToPrimitiveCopy, isNonTrivialToPrimitiveDestroy,
            // hasNonTrivialToPrimitiveDefaultInitializeCUnion,
            // hasNonTrivialToPrimitiveDestructCUnion,
            // hasNonTrivialToPrimitiveCopyCUnion, isParamDestroyedInCallee,
            // getArgPassingRestrictions
  // ODRHash
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 26));

  // DC
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset
  DeclRecordAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_PARM_VAR
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           8)); // Packed DeclBits: ModuleOwnershipKind, isUsed,
                                // isReferenced, AccessSpecifier,
                                // HasStandaloneLexicalDC, HasAttrs, isImplicit,
                                // TopLevelDeclInObjCContainer,
                                // isInvalidDecl,
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // ValueDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclaratorDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
  // VarDecl
  Abv->Add(
      BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                      12)); // Packed Var Decl bits: SClass, TSCSpec, InitStyle,
                            // isARCPseudoStrong, Linkage, ModulesCodegen
  Abv->Add(BitCodeAbbrevOp(0));                          // VarKind (local enum)
  // ParmVarDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      19)); // Packed Parm Var Decl bits: IsObjCMethodParameter, ScopeDepth,
            // ObjCDeclQualifier, KNRPromoted,
            // HasInheritedDefaultArg, HasUninstantiatedDefaultArg
  // Type Source Info
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
  DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_TYPEDEF
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           7)); // Packed DeclBits: ModuleOwnershipKind,
                                // isReferenced, isUsed, AccessSpecifier. Other
                                // higher bits should be 0: isImplicit,
                                // HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer, isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // TypeDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
  // TypedefDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
  DeclTypedefAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_VAR
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           12)); // Packed DeclBits: HasStandaloneLexicalDC,
                                 // isInvalidDecl, HasAttrs, isImplicit, isUsed,
                                 // isReferenced, TopLevelDeclInObjCContainer,
                                 // AccessSpecifier, ModuleOwnershipKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber
  // ValueDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclaratorDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc
  Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType
  // VarDecl
  Abv->Add(BitCodeAbbrevOp(
      BitCodeAbbrevOp::Fixed,
      21)); // Packed Var Decl bits:  Linkage, ModulesCodegen,
            // SClass, TSCSpec, InitStyle,
            // isARCPseudoStrong, IsThisDeclarationADemotedDefinition,
            // isExceptionVariable, isNRVOVariable, isCXXForRangeDecl,
            // isInline, isInlineSpecified, isConstexpr,
            // isInitCapture, isPrevDeclInSameScope,
            // EscapingByref, HasDeducedType, ImplicitParamKind, isObjCForDecl
  Abv->Add(BitCodeAbbrevOp(0));                         // VarKind (local enum)
  // Type Source Info
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc
  DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_CXX_METHOD
  DeclCXXMethodAbbrev =
      Stream.EmitAbbrev(getCXXMethodAbbrev<FunctionDecl::TK_NonTemplate>());
  DeclTemplateCXXMethodAbbrev = Stream.EmitAbbrev(
      getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplate>());
  DeclDependentNonTemplateCXXMethodAbbrev = Stream.EmitAbbrev(
      getCXXMethodAbbrev<FunctionDecl::TK_DependentNonTemplate>());
  DeclMemberSpecializedCXXMethodAbbrev = Stream.EmitAbbrev(
      getCXXMethodAbbrev<FunctionDecl::TK_MemberSpecialization>());
  DeclTemplateSpecializedCXXMethodAbbrev = Stream.EmitAbbrev(
      getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplateSpecialization>());
  DeclDependentSpecializationCXXMethodAbbrev = Stream.EmitAbbrev(
      getCXXMethodAbbrev<
          FunctionDecl::TK_DependentFunctionTemplateSpecialization>());

  // Abbreviation for DECL_TEMPLATE_TYPE_PARM
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_TEMPLATE_TYPE_PARM));
  Abv->Add(BitCodeAbbrevOp(0)); // hasTypeConstraint
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           7)); // Packed DeclBits: ModuleOwnershipKind,
                                // isReferenced, isUsed, AccessSpecifier. Other
                                // higher bits should be 0: isImplicit,
                                // HasStandaloneLexicalDC, HasAttrs,
                                // TopLevelDeclInObjCContainer, isInvalidDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));
  // TypeDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref
  // TemplateTypeParmDecl
  Abv->Add(
      BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename
  Abv->Add(BitCodeAbbrevOp(0));                    // OwnsDefaultArg
  DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for DECL_USING_SHADOW
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_USING_SHADOW));
  // Redeclarable
  Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration
  // Decl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                           12)); // Packed DeclBits: HasStandaloneLexicalDC,
                                 // isInvalidDecl, HasAttrs, isImplicit, isUsed,
                                 // isReferenced, TopLevelDeclInObjCContainer,
                                 // AccessSpecifier, ModuleOwnershipKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID
  // NamedDecl
  Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name
  Abv->Add(BitCodeAbbrevOp(0));
  // UsingShadowDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // TargetDecl
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // UsingOrNextShadow
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR,
                           6)); // InstantiatedFromUsingShadowDecl
  DeclUsingShadowAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_DECL_REF
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF));
  // Stmt
  //  Expr
  //  PackingBits: DependenceKind, ValueKind. ObjectKind should be 0.
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // DeclRefExpr
  // Packing Bits: , HadMultipleCandidates, RefersToEnclosingVariableOrCapture,
  // IsImmediateEscalating, NonOdrUseReason.
  // GetDeclFound, HasQualifier and ExplicitTemplateArgs should be 0.
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
  DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_INTEGER_LITERAL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL));
  //Stmt
  // Expr
  // DependenceKind, ValueKind, ObjectKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // Integer Literal
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
  Abv->Add(BitCodeAbbrevOp(32));                      // Bit Width
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Value
  IntegerLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_CHARACTER_LITERAL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL));
  //Stmt
  // Expr
  // DependenceKind, ValueKind, ObjectKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // Character Literal
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind
  CharacterLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_IMPLICIT_CAST
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind, ValueKind, ObjectKind,
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // CastExpr
  Abv->Add(BitCodeAbbrevOp(0)); // PathSize
  // Packing Bits: CastKind, StoredFPFeatures, isPartOfExplicitCast
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 9));
  // ImplicitCastExpr
  ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_BINARY_OPERATOR
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_BINARY_OPERATOR));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind. ValueKind and ObjectKind should
  // be 0 in this case.
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // BinaryOperator
  Abv->Add(
      BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  BinaryOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_COMPOUND_ASSIGN_OPERATOR
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_COMPOUND_ASSIGN_OPERATOR));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind. ValueKind and ObjectKind should
  // be 0 in this case.
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // BinaryOperator
  // Packing Bits: OpCode. The HasFPFeatures bit should be 0
  Abv->Add(
      BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  // CompoundAssignOperator
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHSType
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Result Type
  CompoundAssignOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_CALL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CALL));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind, ValueKind, ObjectKind,
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // CallExpr
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs
  Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  CallExprAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_CXX_OPERATOR_CALL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_OPERATOR_CALL));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind, ValueKind, ObjectKind,
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // CallExpr
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs
  Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  // CXXOperatorCallExpr
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Operator Kind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  CXXOperatorCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for EXPR_CXX_MEMBER_CALL
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_MEMBER_CALL));
  // Stmt
  // Expr
  // Packing Bits: DependenceKind, ValueKind, ObjectKind,
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type
  // CallExpr
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs
  Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  // CXXMemberCallExpr
  CXXMemberCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv));

  // Abbreviation for STMT_COMPOUND
  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::STMT_COMPOUND));
  // Stmt
  // CompoundStmt
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Num Stmts
  Abv->Add(BitCodeAbbrevOp(0));                       // hasStoredFPFeatures
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location
  CompoundStmtAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  DeclContextLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_SPECIALIZATIONS));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  DeclSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv));

  Abv = std::make_shared<BitCodeAbbrev>();
  Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARTIAL_SPECIALIZATIONS));
  Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
  DeclPartialSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv));
}

/// isRequiredDecl - Check if this is a "required" Decl, which must be seen by
/// consumers of the AST.
///
/// Such decls will always be deserialized from the AST file, so we would like
/// this to be as restrictive as possible. Currently the predicate is driven by
/// code generation requirements, if other clients have a different notion of
/// what is "required" then we may have to consider an alternate scheme where
/// clients can iterate over the top-level decls and get information on them,
/// without necessary deserializing them. We could explicitly require such
/// clients to use a separate API call to "realize" the decl. This should be
/// relatively painless since they would presumably only do it for top-level
/// decls.
static bool isRequiredDecl(const Decl *D, ASTContext &Context,
                           Module *WritingModule) {
  // Named modules have different semantics than header modules. Every named
  // module units owns a translation unit. So the importer of named modules
  // doesn't need to deserilize everything ahead of time.
  if (WritingModule && WritingModule->isNamedModule()) {
    // The PragmaCommentDecl and PragmaDetectMismatchDecl are MSVC's extension.
    // And the behavior of MSVC for such cases will leak this to the module
    // users. Given pragma is not a standard thing, the compiler has the space
    // to do their own decision. Let's follow MSVC here.
    if (isa<PragmaCommentDecl, PragmaDetectMismatchDecl>(D))
      return true;
    return false;
  }

  // An ObjCMethodDecl is never considered as "required" because its
  // implementation container always is.

  // File scoped assembly or obj-c or OMP declare target implementation must be
  // seen.
  if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCImplDecl>(D))
    return true;

  if (WritingModule && isPartOfPerModuleInitializer(D)) {
    // These declarations are part of the module initializer, and are emitted
    // if and when the module is imported, rather than being emitted eagerly.
    return false;
  }

  return Context.DeclMustBeEmitted(D);
}

void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
  PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(),
                                      "serializing");

  // Determine the ID for this declaration.
  LocalDeclID ID;
  assert(!D->isFromASTFile() && "should not be emitting imported decl");
  LocalDeclID &IDR = DeclIDs[D];
  if (IDR.isInvalid())
    IDR = NextDeclID++;

  ID = IDR;

  assert(ID >= FirstDeclID && "invalid decl ID");

  RecordData Record;
  ASTDeclWriter W(*this, Context, Record, GeneratingReducedBMI);

  // Build a record for this declaration
  W.Visit(D);

  // Emit this declaration to the bitstream.
  uint64_t Offset = W.Emit(D);

  // Record the offset for this declaration
  SourceLocation Loc = D->getLocation();
  SourceLocationEncoding::RawLocEncoding RawLoc =
      getRawSourceLocationEncoding(getAdjustedLocation(Loc));

  unsigned Index = ID.getRawValue() - FirstDeclID.getRawValue();
  if (DeclOffsets.size() == Index)
    DeclOffsets.emplace_back(RawLoc, Offset, DeclTypesBlockStartOffset);
  else if (DeclOffsets.size() < Index) {
    // FIXME: Can/should this happen?
    DeclOffsets.resize(Index+1);
    DeclOffsets[Index].setRawLoc(RawLoc);
    DeclOffsets[Index].setBitOffset(Offset, DeclTypesBlockStartOffset);
  } else {
    llvm_unreachable("declarations should be emitted in ID order");
  }

  SourceManager &SM = Context.getSourceManager();
  if (Loc.isValid() && SM.isLocalSourceLocation(Loc))
    associateDeclWithFile(D, ID);

  // Note declarations that should be deserialized eagerly so that we can add
  // them to a record in the AST file later.
  if (isRequiredDecl(D, Context, WritingModule))
    AddDeclRef(D, EagerlyDeserializedDecls);
}

void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
  // Switch case IDs are per function body.
  Writer->ClearSwitchCaseIDs();

  assert(FD->doesThisDeclarationHaveABody());
  bool ModulesCodegen = false;
  if (!FD->isDependentContext()) {
    std::optional<GVALinkage> Linkage;
    if (Writer->WritingModule &&
        Writer->WritingModule->isInterfaceOrPartition()) {
      // When building a C++20 module interface unit or a partition unit, a
      // strong definition in the module interface is provided by the
      // compilation of that unit, not by its users. (Inline functions are still
      // emitted in module users.)
      Linkage = getASTContext().GetGVALinkageForFunction(FD);
      ModulesCodegen = *Linkage >= GVA_StrongExternal;
    }
    if (Writer->getLangOpts().ModulesCodegen ||
        (FD->hasAttr<DLLExportAttr>() &&
         Writer->getLangOpts().BuildingPCHWithObjectFile)) {

      // Under -fmodules-codegen, codegen is performed for all non-internal,
      // non-always_inline functions, unless they are available elsewhere.
      if (!FD->hasAttr<AlwaysInlineAttr>()) {
        if (!Linkage)
          Linkage = getASTContext().GetGVALinkageForFunction(FD);
        ModulesCodegen =
            *Linkage != GVA_Internal && *Linkage != GVA_AvailableExternally;
      }
    }
  }
  Record->push_back(ModulesCodegen);
  if (ModulesCodegen)
    Writer->AddDeclRef(FD, Writer->ModularCodegenDecls);
  if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
    Record->push_back(CD->getNumCtorInitializers());
    if (CD->getNumCtorInitializers())
      AddCXXCtorInitializers(llvm::ArrayRef(CD->init_begin(), CD->init_end()));
  }
  AddStmt(FD->getBody());
}
