//===- ASTReaderDecl.cpp - Decl Deserialization ---------------------------===//
//
// 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 the ASTReader::ReadDeclRecord method, which is the
// entrypoint for loading a decl.
//
//===----------------------------------------------------------------------===//

#include "ASTCommon.h"
#include "ASTReaderInternals.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Lambda.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Serialization/ASTBitCodes.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ContinuousRangeMap.h"
#include "clang/Serialization/Module.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <string>
#include <utility>

using namespace clang;
using namespace serialization;

//===----------------------------------------------------------------------===//
// Declaration deserialization
//===----------------------------------------------------------------------===//

namespace clang {

  class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> {
    ASTReader &Reader;
    ASTRecordReader &Record;
    ASTReader::RecordLocation Loc;
    const DeclID ThisDeclID;
    const SourceLocation ThisDeclLoc;

    using RecordData = ASTReader::RecordData;

    TypeID DeferredTypeID = 0;
    unsigned AnonymousDeclNumber;
    GlobalDeclID NamedDeclForTagDecl = 0;
    IdentifierInfo *TypedefNameForLinkage = nullptr;

    bool HasPendingBody = false;

    ///A flag to carry the information for a decl from the entity is
    /// used. We use it to delay the marking of the canonical decl as used until
    /// the entire declaration is deserialized and merged.
    bool IsDeclMarkedUsed = false;

    uint64_t GetCurrentCursorOffset();

    uint64_t ReadLocalOffset() {
      uint64_t LocalOffset = Record.readInt();
      assert(LocalOffset < Loc.Offset && "offset point after current record");
      return LocalOffset ? Loc.Offset - LocalOffset : 0;
    }

    uint64_t ReadGlobalOffset() {
      uint64_t Local = ReadLocalOffset();
      return Local ? Record.getGlobalBitOffset(Local) : 0;
    }

    SourceLocation ReadSourceLocation() {
      return Record.readSourceLocation();
    }

    SourceRange ReadSourceRange() {
      return Record.readSourceRange();
    }

    TypeSourceInfo *GetTypeSourceInfo() {
      return Record.getTypeSourceInfo();
    }

    serialization::DeclID ReadDeclID() {
      return Record.readDeclID();
    }

    std::string ReadString() {
      return Record.readString();
    }

    void ReadDeclIDList(SmallVectorImpl<DeclID> &IDs) {
      for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I)
        IDs.push_back(ReadDeclID());
    }

    Decl *ReadDecl() {
      return Record.readDecl();
    }

    template<typename T>
    T *ReadDeclAs() {
      return Record.readDeclAs<T>();
    }

    void ReadQualifierInfo(QualifierInfo &Info) {
      Record.readQualifierInfo(Info);
    }

    void ReadDeclarationNameLoc(DeclarationNameLoc &DNLoc, DeclarationName Name) {
      Record.readDeclarationNameLoc(DNLoc, Name);
    }

    serialization::SubmoduleID readSubmoduleID() {
      if (Record.getIdx() == Record.size())
        return 0;

      return Record.getGlobalSubmoduleID(Record.readInt());
    }

    Module *readModule() {
      return Record.getSubmodule(readSubmoduleID());
    }

    void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
    void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
                               const CXXRecordDecl *D);
    void MergeDefinitionData(CXXRecordDecl *D,
                             struct CXXRecordDecl::DefinitionData &&NewDD);
    void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
    void MergeDefinitionData(ObjCInterfaceDecl *D,
                             struct ObjCInterfaceDecl::DefinitionData &&NewDD);
    void ReadObjCDefinitionData(struct ObjCProtocolDecl::DefinitionData &Data);
    void MergeDefinitionData(ObjCProtocolDecl *D,
                             struct ObjCProtocolDecl::DefinitionData &&NewDD);

    static DeclContext *getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC);

    static NamedDecl *getAnonymousDeclForMerging(ASTReader &Reader,
                                                 DeclContext *DC,
                                                 unsigned Index);
    static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC,
                                           unsigned Index, NamedDecl *D);

    /// Results from loading a RedeclarableDecl.
    class RedeclarableResult {
      Decl *MergeWith;
      GlobalDeclID FirstID;
      bool IsKeyDecl;

    public:
      RedeclarableResult(Decl *MergeWith, GlobalDeclID FirstID, bool IsKeyDecl)
          : MergeWith(MergeWith), FirstID(FirstID), IsKeyDecl(IsKeyDecl) {}

      /// Retrieve the first ID.
      GlobalDeclID getFirstID() const { return FirstID; }

      /// Is this declaration a key declaration?
      bool isKeyDecl() const { return IsKeyDecl; }

      /// Get a known declaration that this should be merged with, if
      /// any.
      Decl *getKnownMergeTarget() const { return MergeWith; }
    };

    /// Class used to capture the result of searching for an existing
    /// declaration of a specific kind and name, along with the ability
    /// to update the place where this result was found (the declaration
    /// chain hanging off an identifier or the DeclContext we searched in)
    /// if requested.
    class FindExistingResult {
      ASTReader &Reader;
      NamedDecl *New = nullptr;
      NamedDecl *Existing = nullptr;
      bool AddResult = false;
      unsigned AnonymousDeclNumber = 0;
      IdentifierInfo *TypedefNameForLinkage = nullptr;

    public:
      FindExistingResult(ASTReader &Reader) : Reader(Reader) {}

      FindExistingResult(ASTReader &Reader, NamedDecl *New, NamedDecl *Existing,
                         unsigned AnonymousDeclNumber,
                         IdentifierInfo *TypedefNameForLinkage)
          : Reader(Reader), New(New), Existing(Existing), AddResult(true),
            AnonymousDeclNumber(AnonymousDeclNumber),
            TypedefNameForLinkage(TypedefNameForLinkage) {}

      FindExistingResult(FindExistingResult &&Other)
          : Reader(Other.Reader), New(Other.New), Existing(Other.Existing),
            AddResult(Other.AddResult),
            AnonymousDeclNumber(Other.AnonymousDeclNumber),
            TypedefNameForLinkage(Other.TypedefNameForLinkage) {
        Other.AddResult = false;
      }

      FindExistingResult &operator=(FindExistingResult &&) = delete;
      ~FindExistingResult();

      /// Suppress the addition of this result into the known set of
      /// names.
      void suppress() { AddResult = false; }

      operator NamedDecl*() const { return Existing; }

      template<typename T>
      operator T*() const { return dyn_cast_or_null<T>(Existing); }
    };

    static DeclContext *getPrimaryContextForMerging(ASTReader &Reader,
                                                    DeclContext *DC);
    FindExistingResult findExisting(NamedDecl *D);

  public:
    ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record,
                  ASTReader::RecordLocation Loc,
                  DeclID thisDeclID, SourceLocation ThisDeclLoc)
        : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID),
          ThisDeclLoc(ThisDeclLoc) {}

    template <typename T> static
    void AddLazySpecializations(T *D,
                                SmallVectorImpl<serialization::DeclID>& IDs) {
      if (IDs.empty())
        return;

      // FIXME: We should avoid this pattern of getting the ASTContext.
      ASTContext &C = D->getASTContext();

      auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations;

      if (auto &Old = LazySpecializations) {
        IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]);
        llvm::sort(IDs);
        IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end());
      }

      auto *Result = new (C) serialization::DeclID[1 + IDs.size()];
      *Result = IDs.size();
      std::copy(IDs.begin(), IDs.end(), Result + 1);

      LazySpecializations = Result;
    }

    template <typename DeclT>
    static Decl *getMostRecentDeclImpl(Redeclarable<DeclT> *D);
    static Decl *getMostRecentDeclImpl(...);
    static Decl *getMostRecentDecl(Decl *D);

    template <typename DeclT>
    static void attachPreviousDeclImpl(ASTReader &Reader,
                                       Redeclarable<DeclT> *D, Decl *Previous,
                                       Decl *Canon);
    static void attachPreviousDeclImpl(ASTReader &Reader, ...);
    static void attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous,
                                   Decl *Canon);

    template <typename DeclT>
    static void attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest);
    static void attachLatestDeclImpl(...);
    static void attachLatestDecl(Decl *D, Decl *latest);

    template <typename DeclT>
    static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D);
    static void markIncompleteDeclChainImpl(...);

    /// Determine whether this declaration has a pending body.
    bool hasPendingBody() const { return HasPendingBody; }

    void ReadFunctionDefinition(FunctionDecl *FD);
    void Visit(Decl *D);

    void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &);

    static void setNextObjCCategory(ObjCCategoryDecl *Cat,
                                    ObjCCategoryDecl *Next) {
      Cat->NextClassCategory = Next;
    }

    void VisitDecl(Decl *D);
    void VisitPragmaCommentDecl(PragmaCommentDecl *D);
    void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D);
    void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
    void VisitNamedDecl(NamedDecl *ND);
    void VisitLabelDecl(LabelDecl *LD);
    void VisitNamespaceDecl(NamespaceDecl *D);
    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
    void VisitTypeDecl(TypeDecl *TD);
    RedeclarableResult VisitTypedefNameDecl(TypedefNameDecl *TD);
    void VisitTypedefDecl(TypedefDecl *TD);
    void VisitTypeAliasDecl(TypeAliasDecl *TD);
    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
    RedeclarableResult VisitTagDecl(TagDecl *TD);
    void VisitEnumDecl(EnumDecl *ED);
    RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD);
    void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); }
    RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D);
    void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); }
    RedeclarableResult VisitClassTemplateSpecializationDeclImpl(
                                            ClassTemplateSpecializationDecl *D);

    void VisitClassTemplateSpecializationDecl(
        ClassTemplateSpecializationDecl *D) {
      VisitClassTemplateSpecializationDeclImpl(D);
    }

    void VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *D);
    void VisitClassScopeFunctionSpecializationDecl(
                                       ClassScopeFunctionSpecializationDecl *D);
    RedeclarableResult
    VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);

    void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
      VisitVarTemplateSpecializationDeclImpl(D);
    }

    void VisitVarTemplatePartialSpecializationDecl(
        VarTemplatePartialSpecializationDecl *D);
    void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
    void VisitValueDecl(ValueDecl *VD);
    void VisitEnumConstantDecl(EnumConstantDecl *ECD);
    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
    void VisitDeclaratorDecl(DeclaratorDecl *DD);
    void VisitFunctionDecl(FunctionDecl *FD);
    void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *GD);
    void VisitCXXMethodDecl(CXXMethodDecl *D);
    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
    void VisitCXXConversionDecl(CXXConversionDecl *D);
    void VisitFieldDecl(FieldDecl *FD);
    void VisitMSPropertyDecl(MSPropertyDecl *FD);
    void VisitIndirectFieldDecl(IndirectFieldDecl *FD);
    RedeclarableResult VisitVarDeclImpl(VarDecl *D);
    void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); }
    void VisitImplicitParamDecl(ImplicitParamDecl *PD);
    void VisitParmVarDecl(ParmVarDecl *PD);
    void VisitDecompositionDecl(DecompositionDecl *DD);
    void VisitBindingDecl(BindingDecl *BD);
    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
    DeclID VisitTemplateDecl(TemplateDecl *D);
    RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
    void VisitClassTemplateDecl(ClassTemplateDecl *D);
    void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
    void VisitVarTemplateDecl(VarTemplateDecl *D);
    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
    void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
    void VisitUsingDecl(UsingDecl *D);
    void VisitUsingPackDecl(UsingPackDecl *D);
    void VisitUsingShadowDecl(UsingShadowDecl *D);
    void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D);
    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
    void VisitExportDecl(ExportDecl *D);
    void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
    void VisitImportDecl(ImportDecl *D);
    void VisitAccessSpecDecl(AccessSpecDecl *D);
    void VisitFriendDecl(FriendDecl *D);
    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
    void VisitStaticAssertDecl(StaticAssertDecl *D);
    void VisitBlockDecl(BlockDecl *BD);
    void VisitCapturedDecl(CapturedDecl *CD);
    void VisitEmptyDecl(EmptyDecl *D);

    std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);

    template<typename T>
    RedeclarableResult VisitRedeclarable(Redeclarable<T> *D);

    template<typename T>
    void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl,
                           DeclID TemplatePatternID = 0);

    template<typename T>
    void mergeRedeclarable(Redeclarable<T> *D, T *Existing,
                           RedeclarableResult &Redecl,
                           DeclID TemplatePatternID = 0);

    template<typename T>
    void mergeMergeable(Mergeable<T> *D);

    void mergeTemplatePattern(RedeclarableTemplateDecl *D,
                              RedeclarableTemplateDecl *Existing,
                              DeclID DsID, bool IsKeyDecl);

    ObjCTypeParamList *ReadObjCTypeParamList();

    // FIXME: Reorder according to 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 VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D);
    void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D);
    void VisitOMPRequiresDecl(OMPRequiresDecl *D);
    void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D);
  };

} // namespace clang

namespace {

/// Iterator over the redeclarations of a declaration that have already
/// been merged into the same redeclaration chain.
template<typename DeclT>
class MergedRedeclIterator {
  DeclT *Start;
  DeclT *Canonical = nullptr;
  DeclT *Current = nullptr;

public:
  MergedRedeclIterator() = default;
  MergedRedeclIterator(DeclT *Start) : Start(Start), Current(Start) {}

  DeclT *operator*() { return Current; }

  MergedRedeclIterator &operator++() {
    if (Current->isFirstDecl()) {
      Canonical = Current;
      Current = Current->getMostRecentDecl();
    } else
      Current = Current->getPreviousDecl();

    // If we started in the merged portion, we'll reach our start position
    // eventually. Otherwise, we'll never reach it, but the second declaration
    // we reached was the canonical declaration, so stop when we see that one
    // again.
    if (Current == Start || Current == Canonical)
      Current = nullptr;
    return *this;
  }

  friend bool operator!=(const MergedRedeclIterator &A,
                         const MergedRedeclIterator &B) {
    return A.Current != B.Current;
  }
};

} // namespace

template <typename DeclT>
static llvm::iterator_range<MergedRedeclIterator<DeclT>>
merged_redecls(DeclT *D) {
  return llvm::make_range(MergedRedeclIterator<DeclT>(D),
                          MergedRedeclIterator<DeclT>());
}

uint64_t ASTDeclReader::GetCurrentCursorOffset() {
  return Loc.F->DeclsCursor.GetCurrentBitNo() + Loc.F->GlobalBitOffset;
}

void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
  if (Record.readInt())
    Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
  if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
    CD->setNumCtorInitializers(Record.readInt());
    if (CD->getNumCtorInitializers())
      CD->CtorInitializers = ReadGlobalOffset();
  }
  // Store the offset of the body so we can lazily load it later.
  Reader.PendingBodies[FD] = GetCurrentCursorOffset();
  HasPendingBody = true;
}

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

  // At this point we have deserialized and merged the decl and it is safe to
  // update its canonical decl to signal that the entire entity is used.
  D->getCanonicalDecl()->Used |= IsDeclMarkedUsed;
  IsDeclMarkedUsed = false;

  if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
    if (auto *TInfo = DD->getTypeSourceInfo())
      Record.readTypeLoc(TInfo->getTypeLoc());
  }

  if (auto *TD = dyn_cast<TypeDecl>(D)) {
    // We have a fully initialized TypeDecl. Read its type now.
    TD->setTypeForDecl(Reader.GetType(DeferredTypeID).getTypePtrOrNull());

    // If this is a tag declaration with a typedef name for linkage, it's safe
    // to load that typedef now.
    if (NamedDeclForTagDecl)
      cast<TagDecl>(D)->TypedefNameDeclOrQualifier =
          cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl));
  } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
    // if we have a fully initialized TypeDecl, we can safely read its type now.
    ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull();
  } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
    // FunctionDecl's body was written last after all other Stmts/Exprs.
    // We only read it if FD doesn't already have a body (e.g., from another
    // module).
    // FIXME: Can we diagnose ODR violations somehow?
    if (Record.readInt())
      ReadFunctionDefinition(FD);
  }
}

void ASTDeclReader::VisitDecl(Decl *D) {
  if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
      isa<ParmVarDecl>(D)) {
    // We don't want to deserialize the DeclContext of a template
    // parameter or of a parameter of a function template immediately.   These
    // entities might be used in the formulation of its DeclContext (for
    // example, a function parameter can be used in decltype() in trailing
    // return type of the function).  Use the translation unit DeclContext as a
    // placeholder.
    GlobalDeclID SemaDCIDForTemplateParmDecl = ReadDeclID();
    GlobalDeclID LexicalDCIDForTemplateParmDecl = ReadDeclID();
    if (!LexicalDCIDForTemplateParmDecl)
      LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
    Reader.addPendingDeclContextInfo(D,
                                     SemaDCIDForTemplateParmDecl,
                                     LexicalDCIDForTemplateParmDecl);
    D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
  } else {
    auto *SemaDC = ReadDeclAs<DeclContext>();
    auto *LexicalDC = ReadDeclAs<DeclContext>();
    if (!LexicalDC)
      LexicalDC = SemaDC;
    DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC);
    // Avoid calling setLexicalDeclContext() directly because it uses
    // Decl::getASTContext() internally which is unsafe during derialization.
    D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC,
                           Reader.getContext());
  }
  D->setLocation(ThisDeclLoc);
  D->setInvalidDecl(Record.readInt());
  if (Record.readInt()) { // hasAttrs
    AttrVec Attrs;
    Record.readAttributes(Attrs);
    // Avoid calling setAttrs() directly because it uses Decl::getASTContext()
    // internally which is unsafe during derialization.
    D->setAttrsImpl(Attrs, Reader.getContext());
  }
  D->setImplicit(Record.readInt());
  D->Used = Record.readInt();
  IsDeclMarkedUsed |= D->Used;
  D->setReferenced(Record.readInt());
  D->setTopLevelDeclInObjCContainer(Record.readInt());
  D->setAccess((AccessSpecifier)Record.readInt());
  D->FromASTFile = true;
  bool ModulePrivate = Record.readInt();

  // Determine whether this declaration is part of a (sub)module. If so, it
  // may not yet be visible.
  if (unsigned SubmoduleID = readSubmoduleID()) {
    // Store the owning submodule ID in the declaration.
    D->setModuleOwnershipKind(
        ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate
                      : Decl::ModuleOwnershipKind::VisibleWhenImported);
    D->setOwningModuleID(SubmoduleID);

    if (ModulePrivate) {
      // Module-private declarations are never visible, so there is no work to
      // do.
    } else if (Reader.getContext().getLangOpts().ModulesLocalVisibility) {
      // If local visibility is being tracked, this declaration will become
      // hidden and visible as the owning module does.
    } else if (Module *Owner = Reader.getSubmodule(SubmoduleID)) {
      // Mark the declaration as visible when its owning module becomes visible.
      if (Owner->NameVisibility == Module::AllVisible)
        D->setVisibleDespiteOwningModule();
      else
        Reader.HiddenNamesMap[Owner].push_back(D);
    }
  } else if (ModulePrivate) {
    D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ModulePrivate);
  }
}

void ASTDeclReader::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
  VisitDecl(D);
  D->setLocation(ReadSourceLocation());
  D->CommentKind = (PragmaMSCommentKind)Record.readInt();
  std::string Arg = ReadString();
  memcpy(D->getTrailingObjects<char>(), Arg.data(), Arg.size());
  D->getTrailingObjects<char>()[Arg.size()] = '\0';
}

void ASTDeclReader::VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D) {
  VisitDecl(D);
  D->setLocation(ReadSourceLocation());
  std::string Name = ReadString();
  memcpy(D->getTrailingObjects<char>(), Name.data(), Name.size());
  D->getTrailingObjects<char>()[Name.size()] = '\0';

  D->ValueStart = Name.size() + 1;
  std::string Value = ReadString();
  memcpy(D->getTrailingObjects<char>() + D->ValueStart, Value.data(),
         Value.size());
  D->getTrailingObjects<char>()[D->ValueStart + Value.size()] = '\0';
}

void ASTDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
  llvm_unreachable("Translation units are not serialized");
}

void ASTDeclReader::VisitNamedDecl(NamedDecl *ND) {
  VisitDecl(ND);
  ND->setDeclName(Record.readDeclarationName());
  AnonymousDeclNumber = Record.readInt();
}

void ASTDeclReader::VisitTypeDecl(TypeDecl *TD) {
  VisitNamedDecl(TD);
  TD->setLocStart(ReadSourceLocation());
  // Delay type reading until after we have fully initialized the decl.
  DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
}

ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitTypedefNameDecl(TypedefNameDecl *TD) {
  RedeclarableResult Redecl = VisitRedeclarable(TD);
  VisitTypeDecl(TD);
  TypeSourceInfo *TInfo = GetTypeSourceInfo();
  if (Record.readInt()) { // isModed
    QualType modedT = Record.readType();
    TD->setModedTypeSourceInfo(TInfo, modedT);
  } else
    TD->setTypeSourceInfo(TInfo);
  // Read and discard the declaration for which this is a typedef name for
  // linkage, if it exists. We cannot rely on our type to pull in this decl,
  // because it might have been merged with a type from another module and
  // thus might not refer to our version of the declaration.
  ReadDecl();
  return Redecl;
}

void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
  RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
  mergeRedeclarable(TD, Redecl);
}

void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) {
  RedeclarableResult Redecl = VisitTypedefNameDecl(TD);
  if (auto *Template = ReadDeclAs<TypeAliasTemplateDecl>())
    // Merged when we merge the template.
    TD->setDescribedAliasTemplate(Template);
  else
    mergeRedeclarable(TD, Redecl);
}

ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) {
  RedeclarableResult Redecl = VisitRedeclarable(TD);
  VisitTypeDecl(TD);

  TD->IdentifierNamespace = Record.readInt();
  TD->setTagKind((TagDecl::TagKind)Record.readInt());
  if (!isa<CXXRecordDecl>(TD))
    TD->setCompleteDefinition(Record.readInt());
  TD->setEmbeddedInDeclarator(Record.readInt());
  TD->setFreeStanding(Record.readInt());
  TD->setCompleteDefinitionRequired(Record.readInt());
  TD->setBraceRange(ReadSourceRange());

  switch (Record.readInt()) {
  case 0:
    break;
  case 1: { // ExtInfo
    auto *Info = new (Reader.getContext()) TagDecl::ExtInfo();
    ReadQualifierInfo(*Info);
    TD->TypedefNameDeclOrQualifier = Info;
    break;
  }
  case 2: // TypedefNameForAnonDecl
    NamedDeclForTagDecl = ReadDeclID();
    TypedefNameForLinkage = Record.getIdentifierInfo();
    break;
  default:
    llvm_unreachable("unexpected tag info kind");
  }

  if (!isa<CXXRecordDecl>(TD))
    mergeRedeclarable(TD, Redecl);
  return Redecl;
}

void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
  VisitTagDecl(ED);
  if (TypeSourceInfo *TI = GetTypeSourceInfo())
    ED->setIntegerTypeSourceInfo(TI);
  else
    ED->setIntegerType(Record.readType());
  ED->setPromotionType(Record.readType());
  ED->setNumPositiveBits(Record.readInt());
  ED->setNumNegativeBits(Record.readInt());
  ED->setScoped(Record.readInt());
  ED->setScopedUsingClassTag(Record.readInt());
  ED->setFixed(Record.readInt());

  ED->setHasODRHash(true);
  ED->ODRHash = Record.readInt();

  // If this is a definition subject to the ODR, and we already have a
  // definition, merge this one into it.
  if (ED->isCompleteDefinition() &&
      Reader.getContext().getLangOpts().Modules &&
      Reader.getContext().getLangOpts().CPlusPlus) {
    EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
    if (!OldDef) {
      // This is the first time we've seen an imported definition. Look for a
      // local definition before deciding that we are the first definition.
      for (auto *D : merged_redecls(ED->getCanonicalDecl())) {
        if (!D->isFromASTFile() && D->isCompleteDefinition()) {
          OldDef = D;
          break;
        }
      }
    }
    if (OldDef) {
      Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
      ED->setCompleteDefinition(false);
      Reader.mergeDefinitionVisibility(OldDef, ED);
      if (OldDef->getODRHash() != ED->getODRHash())
        Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
    } else {
      OldDef = ED;
    }
  }

  if (auto *InstED = ReadDeclAs<EnumDecl>()) {
    auto TSK = (TemplateSpecializationKind)Record.readInt();
    SourceLocation POI = ReadSourceLocation();
    ED->setInstantiationOfMemberEnum(Reader.getContext(), InstED, TSK);
    ED->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
  }
}

ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) {
  RedeclarableResult Redecl = VisitTagDecl(RD);
  RD->setHasFlexibleArrayMember(Record.readInt());
  RD->setAnonymousStructOrUnion(Record.readInt());
  RD->setHasObjectMember(Record.readInt());
  RD->setHasVolatileMember(Record.readInt());
  RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt());
  RD->setNonTrivialToPrimitiveCopy(Record.readInt());
  RD->setNonTrivialToPrimitiveDestroy(Record.readInt());
  RD->setParamDestroyedInCallee(Record.readInt());
  RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt());
  return Redecl;
}

void ASTDeclReader::VisitValueDecl(ValueDecl *VD) {
  VisitNamedDecl(VD);
  // For function declarations, defer reading the type in case the function has
  // a deduced return type that references an entity declared within the
  // function.
  if (isa<FunctionDecl>(VD))
    DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
  else
    VD->setType(Record.readType());
}

void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
  VisitValueDecl(ECD);
  if (Record.readInt())
    ECD->setInitExpr(Record.readExpr());
  ECD->setInitVal(Record.readAPSInt());
  mergeMergeable(ECD);
}

void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
  VisitValueDecl(DD);
  DD->setInnerLocStart(ReadSourceLocation());
  if (Record.readInt()) { // hasExtInfo
    auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo();
    ReadQualifierInfo(*Info);
    DD->DeclInfo = Info;
  }
  QualType TSIType = Record.readType();
  DD->setTypeSourceInfo(
      TSIType.isNull() ? nullptr
                       : Reader.getContext().CreateTypeSourceInfo(TSIType));
}

void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
  RedeclarableResult Redecl = VisitRedeclarable(FD);
  VisitDeclaratorDecl(FD);

  // Attach a type to this function. Use the real type if possible, but fall
  // back to the type as written if it involves a deduced return type.
  if (FD->getTypeSourceInfo() &&
      FD->getTypeSourceInfo()->getType()->castAs<FunctionType>()
                             ->getReturnType()->getContainedAutoType()) {
    // We'll set up the real type in Visit, once we've finished loading the
    // function.
    FD->setType(FD->getTypeSourceInfo()->getType());
    Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID});
  } else {
    FD->setType(Reader.GetType(DeferredTypeID));
  }
  DeferredTypeID = 0;

  ReadDeclarationNameLoc(FD->DNLoc, FD->getDeclName());
  FD->IdentifierNamespace = Record.readInt();

  // FunctionDecl's body is handled last at ASTDeclReader::Visit,
  // after everything else is read.

  FD->setStorageClass(static_cast<StorageClass>(Record.readInt()));
  FD->setInlineSpecified(Record.readInt());
  FD->setImplicitlyInline(Record.readInt());
  FD->setVirtualAsWritten(Record.readInt());
  FD->setPure(Record.readInt());
  FD->setHasInheritedPrototype(Record.readInt());
  FD->setHasWrittenPrototype(Record.readInt());
  FD->setDeletedAsWritten(Record.readInt());
  FD->setTrivial(Record.readInt());
  FD->setTrivialForCall(Record.readInt());
  FD->setDefaulted(Record.readInt());
  FD->setExplicitlyDefaulted(Record.readInt());
  FD->setHasImplicitReturnZero(Record.readInt());
  FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt()));
  FD->setUsesSEHTry(Record.readInt());
  FD->setHasSkippedBody(Record.readInt());
  FD->setIsMultiVersion(Record.readInt());
  FD->setLateTemplateParsed(Record.readInt());

  FD->setCachedLinkage(static_cast<Linkage>(Record.readInt()));
  FD->EndRangeLoc = ReadSourceLocation();

  FD->ODRHash = Record.readInt();
  FD->setHasODRHash(true);

  switch ((FunctionDecl::TemplatedKind)Record.readInt()) {
  case FunctionDecl::TK_NonTemplate:
    mergeRedeclarable(FD, Redecl);
    break;
  case FunctionDecl::TK_FunctionTemplate:
    // Merged when we merge the template.
    FD->setDescribedFunctionTemplate(ReadDeclAs<FunctionTemplateDecl>());
    break;
  case FunctionDecl::TK_MemberSpecialization: {
    auto *InstFD = ReadDeclAs<FunctionDecl>();
    auto TSK = (TemplateSpecializationKind)Record.readInt();
    SourceLocation POI = ReadSourceLocation();
    FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK);
    FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
    mergeRedeclarable(FD, Redecl);
    break;
  }
  case FunctionDecl::TK_FunctionTemplateSpecialization: {
    auto *Template = ReadDeclAs<FunctionTemplateDecl>();
    auto TSK = (TemplateSpecializationKind)Record.readInt();

    // Template arguments.
    SmallVector<TemplateArgument, 8> TemplArgs;
    Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);

    // Template args as written.
    SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
    SourceLocation LAngleLoc, RAngleLoc;
    bool HasTemplateArgumentsAsWritten = Record.readInt();
    if (HasTemplateArgumentsAsWritten) {
      unsigned NumTemplateArgLocs = Record.readInt();
      TemplArgLocs.reserve(NumTemplateArgLocs);
      for (unsigned i = 0; i != NumTemplateArgLocs; ++i)
        TemplArgLocs.push_back(Record.readTemplateArgumentLoc());

      LAngleLoc = ReadSourceLocation();
      RAngleLoc = ReadSourceLocation();
    }

    SourceLocation POI = ReadSourceLocation();

    ASTContext &C = Reader.getContext();
    TemplateArgumentList *TemplArgList
      = TemplateArgumentList::CreateCopy(C, TemplArgs);
    TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
    for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i)
      TemplArgsInfo.addArgument(TemplArgLocs[i]);

    MemberSpecializationInfo *MSInfo = nullptr;
    if (Record.readInt()) {
      auto *FD = ReadDeclAs<FunctionDecl>();
      auto TSK = (TemplateSpecializationKind)Record.readInt();
      SourceLocation POI = ReadSourceLocation();

      MSInfo = new (C) MemberSpecializationInfo(FD, TSK);
      MSInfo->setPointOfInstantiation(POI);
    }

    FunctionTemplateSpecializationInfo *FTInfo =
        FunctionTemplateSpecializationInfo::Create(
            C, FD, Template, TSK, TemplArgList,
            HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI,
            MSInfo);
    FD->TemplateOrSpecialization = FTInfo;

    if (FD->isCanonicalDecl()) { // if canonical add to template's set.
      // The template that contains the specializations set. It's not safe to
      // use getCanonicalDecl on Template since it may still be initializing.
      auto *CanonTemplate = ReadDeclAs<FunctionTemplateDecl>();
      // Get the InsertPos by FindNodeOrInsertPos() instead of calling
      // InsertNode(FTInfo) directly to avoid the getASTContext() call in
      // FunctionTemplateSpecializationInfo's Profile().
      // We avoid getASTContext because a decl in the parent hierarchy may
      // be initializing.
      llvm::FoldingSetNodeID ID;
      FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs, C);
      void *InsertPos = nullptr;
      FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
      FunctionTemplateSpecializationInfo *ExistingInfo =
          CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
      if (InsertPos)
        CommonPtr->Specializations.InsertNode(FTInfo, InsertPos);
      else {
        assert(Reader.getContext().getLangOpts().Modules &&
               "already deserialized this template specialization");
        mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl);
      }
    }
    break;
  }
  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
    // Templates.
    UnresolvedSet<8> TemplDecls;
    unsigned NumTemplates = Record.readInt();
    while (NumTemplates--)
      TemplDecls.addDecl(ReadDeclAs<NamedDecl>());

    // Templates args.
    TemplateArgumentListInfo TemplArgs;
    unsigned NumArgs = Record.readInt();
    while (NumArgs--)
      TemplArgs.addArgument(Record.readTemplateArgumentLoc());
    TemplArgs.setLAngleLoc(ReadSourceLocation());
    TemplArgs.setRAngleLoc(ReadSourceLocation());

    FD->setDependentTemplateSpecialization(Reader.getContext(),
                                           TemplDecls, TemplArgs);
    // These are not merged; we don't need to merge redeclarations of dependent
    // template friends.
    break;
  }
  }

  // Read in the parameters.
  unsigned NumParams = Record.readInt();
  SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(ReadDeclAs<ParmVarDecl>());
  FD->setParams(Reader.getContext(), Params);
}

void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
  VisitNamedDecl(MD);
  if (Record.readInt()) {
    // Load the body on-demand. Most clients won't care, because method
    // definitions rarely show up in headers.
    Reader.PendingBodies[MD] = GetCurrentCursorOffset();
    HasPendingBody = true;
    MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>());
    MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>());
  }
  MD->setInstanceMethod(Record.readInt());
  MD->setVariadic(Record.readInt());
  MD->setPropertyAccessor(Record.readInt());
  MD->setDefined(Record.readInt());
  MD->setOverriding(Record.readInt());
  MD->setHasSkippedBody(Record.readInt());

  MD->setIsRedeclaration(Record.readInt());
  MD->setHasRedeclaration(Record.readInt());
  if (MD->hasRedeclaration())
    Reader.getContext().setObjCMethodRedeclaration(MD,
                                       ReadDeclAs<ObjCMethodDecl>());

  MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt());
  MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt());
  MD->setRelatedResultType(Record.readInt());
  MD->setReturnType(Record.readType());
  MD->setReturnTypeSourceInfo(GetTypeSourceInfo());
  MD->DeclEndLoc = ReadSourceLocation();
  unsigned NumParams = Record.readInt();
  SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(ReadDeclAs<ParmVarDecl>());

  MD->setSelLocsKind((SelectorLocationsKind)Record.readInt());
  unsigned NumStoredSelLocs = Record.readInt();
  SmallVector<SourceLocation, 16> SelLocs;
  SelLocs.reserve(NumStoredSelLocs);
  for (unsigned i = 0; i != NumStoredSelLocs; ++i)
    SelLocs.push_back(ReadSourceLocation());

  MD->setParamsAndSelLocs(Reader.getContext(), Params, SelLocs);
}

void ASTDeclReader::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) {
  VisitTypedefNameDecl(D);

  D->Variance = Record.readInt();
  D->Index = Record.readInt();
  D->VarianceLoc = ReadSourceLocation();
  D->ColonLoc = ReadSourceLocation();
}

void ASTDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
  VisitNamedDecl(CD);
  CD->setAtStartLoc(ReadSourceLocation());
  CD->setAtEndRange(ReadSourceRange());
}

ObjCTypeParamList *ASTDeclReader::ReadObjCTypeParamList() {
  unsigned numParams = Record.readInt();
  if (numParams == 0)
    return nullptr;

  SmallVector<ObjCTypeParamDecl *, 4> typeParams;
  typeParams.reserve(numParams);
  for (unsigned i = 0; i != numParams; ++i) {
    auto *typeParam = ReadDeclAs<ObjCTypeParamDecl>();
    if (!typeParam)
      return nullptr;

    typeParams.push_back(typeParam);
  }

  SourceLocation lAngleLoc = ReadSourceLocation();
  SourceLocation rAngleLoc = ReadSourceLocation();

  return ObjCTypeParamList::create(Reader.getContext(), lAngleLoc,
                                   typeParams, rAngleLoc);
}

void ASTDeclReader::ReadObjCDefinitionData(
         struct ObjCInterfaceDecl::DefinitionData &Data) {
  // Read the superclass.
  Data.SuperClassTInfo = GetTypeSourceInfo();

  Data.EndLoc = ReadSourceLocation();
  Data.HasDesignatedInitializers = Record.readInt();

  // Read the directly referenced protocols and their SourceLocations.
  unsigned NumProtocols = Record.readInt();
  SmallVector<ObjCProtocolDecl *, 16> Protocols;
  Protocols.reserve(NumProtocols);
  for (unsigned I = 0; I != NumProtocols; ++I)
    Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>());
  SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtocols);
  for (unsigned I = 0; I != NumProtocols; ++I)
    ProtoLocs.push_back(ReadSourceLocation());
  Data.ReferencedProtocols.set(Protocols.data(), NumProtocols, ProtoLocs.data(),
                               Reader.getContext());

  // Read the transitive closure of protocols referenced by this class.
  NumProtocols = Record.readInt();
  Protocols.clear();
  Protocols.reserve(NumProtocols);
  for (unsigned I = 0; I != NumProtocols; ++I)
    Protocols.push_back(ReadDeclAs<ObjCProtocolDecl>());
  Data.AllReferencedProtocols.set(Protocols.data(), NumProtocols,
                                  Reader.getContext());
}

void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D,
         struct ObjCInterfaceDecl::DefinitionData &&NewDD) {
  // FIXME: odr checking?
}

void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
  RedeclarableResult Redecl = VisitRedeclarable(ID);
  VisitObjCContainerDecl(ID);
  DeferredTypeID = Record.getGlobalTypeID(Record.readInt());
  mergeRedeclarable(ID, Redecl);

  ID->TypeParamList = ReadObjCTypeParamList();
  if (Record.readInt()) {
    // Read the definition.
    ID->allocateDefinitionData();

    ReadObjCDefinitionData(ID->data());
    ObjCInterfaceDecl *Canon = ID->getCanonicalDecl();
    if (Canon->Data.getPointer()) {
      // If we already have a definition, keep the definition invariant and
      // merge the data.
      MergeDefinitionData(Canon, std::move(ID->data()));
      ID->Data = Canon->Data;
    } else {
      // Set the definition data of the canonical declaration, so other
      // redeclarations will see it.
      ID->getCanonicalDecl()->Data = ID->Data;

      // We will rebuild this list lazily.
      ID->setIvarList(nullptr);
    }

    // Note that we have deserialized a definition.
    Reader.PendingDefinitions.insert(ID);

    // Note that we've loaded this Objective-C class.
    Reader.ObjCClassesLoaded.push_back(ID);
  } else {
    ID->Data = ID->getCanonicalDecl()->Data;
  }
}

void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
  VisitFieldDecl(IVD);
  IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record.readInt());
  // This field will be built lazily.
  IVD->setNextIvar(nullptr);
  bool synth = Record.readInt();
  IVD->setSynthesize(synth);
}

void ASTDeclReader::ReadObjCDefinitionData(
         struct ObjCProtocolDecl::DefinitionData &Data) {
    unsigned NumProtoRefs = Record.readInt();
    SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
    ProtoRefs.reserve(NumProtoRefs);
    for (unsigned I = 0; I != NumProtoRefs; ++I)
      ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>());
    SmallVector<SourceLocation, 16> ProtoLocs;
    ProtoLocs.reserve(NumProtoRefs);
    for (unsigned I = 0; I != NumProtoRefs; ++I)
      ProtoLocs.push_back(ReadSourceLocation());
    Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs,
                                 ProtoLocs.data(), Reader.getContext());
}

void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D,
         struct ObjCProtocolDecl::DefinitionData &&NewDD) {
  // FIXME: odr checking?
}

void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
  RedeclarableResult Redecl = VisitRedeclarable(PD);
  VisitObjCContainerDecl(PD);
  mergeRedeclarable(PD, Redecl);

  if (Record.readInt()) {
    // Read the definition.
    PD->allocateDefinitionData();

    ReadObjCDefinitionData(PD->data());

    ObjCProtocolDecl *Canon = PD->getCanonicalDecl();
    if (Canon->Data.getPointer()) {
      // If we already have a definition, keep the definition invariant and
      // merge the data.
      MergeDefinitionData(Canon, std::move(PD->data()));
      PD->Data = Canon->Data;
    } else {
      // Set the definition data of the canonical declaration, so other
      // redeclarations will see it.
      PD->getCanonicalDecl()->Data = PD->Data;
    }
    // Note that we have deserialized a definition.
    Reader.PendingDefinitions.insert(PD);
  } else {
    PD->Data = PD->getCanonicalDecl()->Data;
  }
}

void ASTDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
  VisitFieldDecl(FD);
}

void ASTDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
  VisitObjCContainerDecl(CD);
  CD->setCategoryNameLoc(ReadSourceLocation());
  CD->setIvarLBraceLoc(ReadSourceLocation());
  CD->setIvarRBraceLoc(ReadSourceLocation());

  // Note that this category has been deserialized. We do this before
  // deserializing the interface declaration, so that it will consider this
  /// category.
  Reader.CategoriesDeserialized.insert(CD);

  CD->ClassInterface = ReadDeclAs<ObjCInterfaceDecl>();
  CD->TypeParamList = ReadObjCTypeParamList();
  unsigned NumProtoRefs = Record.readInt();
  SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
  ProtoRefs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoRefs.push_back(ReadDeclAs<ObjCProtocolDecl>());
  SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoLocs.push_back(ReadSourceLocation());
  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                      Reader.getContext());

  // Protocols in the class extension belong to the class.
  if (NumProtoRefs > 0 && CD->ClassInterface && CD->IsClassExtension())
    CD->ClassInterface->mergeClassExtensionProtocolList(
        (ObjCProtocolDecl *const *)ProtoRefs.data(), NumProtoRefs,
        Reader.getContext());
}

void ASTDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
  VisitNamedDecl(CAD);
  CAD->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>());
  CAD->setClassInterfaceLoc(ReadSourceLocation());
  CAD->setAtLoc(ReadSourceLocation());
}

void ASTDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
  VisitNamedDecl(D);
  D->setAtLoc(ReadSourceLocation());
  D->setLParenLoc(ReadSourceLocation());
  QualType T = Record.readType();
  TypeSourceInfo *TSI = GetTypeSourceInfo();
  D->setType(T, TSI);
  D->setPropertyAttributes(
      (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt());
  D->setPropertyAttributesAsWritten(
      (ObjCPropertyDecl::PropertyAttributeKind)Record.readInt());
  D->setPropertyImplementation(
      (ObjCPropertyDecl::PropertyControl)Record.readInt());
  DeclarationName GetterName = Record.readDeclarationName();
  SourceLocation GetterLoc = ReadSourceLocation();
  D->setGetterName(GetterName.getObjCSelector(), GetterLoc);
  DeclarationName SetterName = Record.readDeclarationName();
  SourceLocation SetterLoc = ReadSourceLocation();
  D->setSetterName(SetterName.getObjCSelector(), SetterLoc);
  D->setGetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
  D->setSetterMethodDecl(ReadDeclAs<ObjCMethodDecl>());
  D->setPropertyIvarDecl(ReadDeclAs<ObjCIvarDecl>());
}

void ASTDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
  VisitObjCContainerDecl(D);
  D->setClassInterface(ReadDeclAs<ObjCInterfaceDecl>());
}

void ASTDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
  VisitObjCImplDecl(D);
  D->CategoryNameLoc = ReadSourceLocation();
}

void ASTDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
  VisitObjCImplDecl(D);
  D->setSuperClass(ReadDeclAs<ObjCInterfaceDecl>());
  D->SuperLoc = ReadSourceLocation();
  D->setIvarLBraceLoc(ReadSourceLocation());
  D->setIvarRBraceLoc(ReadSourceLocation());
  D->setHasNonZeroConstructors(Record.readInt());
  D->setHasDestructors(Record.readInt());
  D->NumIvarInitializers = Record.readInt();
  if (D->NumIvarInitializers)
    D->IvarInitializers = ReadGlobalOffset();
}

void ASTDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
  VisitDecl(D);
  D->setAtLoc(ReadSourceLocation());
  D->setPropertyDecl(ReadDeclAs<ObjCPropertyDecl>());
  D->PropertyIvarDecl = ReadDeclAs<ObjCIvarDecl>();
  D->IvarLoc = ReadSourceLocation();
  D->setGetterCXXConstructor(Record.readExpr());
  D->setSetterCXXAssignment(Record.readExpr());
}

void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) {
  VisitDeclaratorDecl(FD);
  FD->Mutable = Record.readInt();

  if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) {
    FD->InitStorage.setInt(ISK);
    FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType
                                   ? Record.readType().getAsOpaquePtr()
                                   : Record.readExpr());
  }

  if (auto *BW = Record.readExpr())
    FD->setBitWidth(BW);

  if (!FD->getDeclName()) {
    if (auto *Tmpl = ReadDeclAs<FieldDecl>())
      Reader.getContext().setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
  }
  mergeMergeable(FD);
}

void ASTDeclReader::VisitMSPropertyDecl(MSPropertyDecl *PD) {
  VisitDeclaratorDecl(PD);
  PD->GetterId = Record.getIdentifierInfo();
  PD->SetterId = Record.getIdentifierInfo();
}

void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {
  VisitValueDecl(FD);

  FD->ChainingSize = Record.readInt();
  assert(FD->ChainingSize >= 2 && "Anonymous chaining must be >= 2");
  FD->Chaining = new (Reader.getContext())NamedDecl*[FD->ChainingSize];

  for (unsigned I = 0; I != FD->ChainingSize; ++I)
    FD->Chaining[I] = ReadDeclAs<NamedDecl>();

  mergeMergeable(FD);
}

ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
  RedeclarableResult Redecl = VisitRedeclarable(VD);
  VisitDeclaratorDecl(VD);

  VD->VarDeclBits.SClass = (StorageClass)Record.readInt();
  VD->VarDeclBits.TSCSpec = Record.readInt();
  VD->VarDeclBits.InitStyle = Record.readInt();
  VD->VarDeclBits.ARCPseudoStrong = Record.readInt();
  if (!isa<ParmVarDecl>(VD)) {
    VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition =
        Record.readInt();
    VD->NonParmVarDeclBits.ExceptionVar = Record.readInt();
    VD->NonParmVarDeclBits.NRVOVariable = Record.readInt();
    VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt();
    VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt();
    VD->NonParmVarDeclBits.IsInline = Record.readInt();
    VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
    VD->NonParmVarDeclBits.IsConstexpr = Record.readInt();
    VD->NonParmVarDeclBits.IsInitCapture = Record.readInt();
    VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt();
    VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt();
    VD->NonParmVarDeclBits.EscapingByref = Record.readInt();
  }
  auto VarLinkage = Linkage(Record.readInt());
  VD->setCachedLinkage(VarLinkage);

  // Reconstruct the one piece of the IdentifierNamespace that we need.
  if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage &&
      VD->getLexicalDeclContext()->isFunctionOrMethod())
    VD->setLocalExternDecl();

  if (uint64_t Val = Record.readInt()) {
    VD->setInit(Record.readExpr());
    if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3
      EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
      Eval->CheckedICE = true;
      Eval->IsICE = Val == 3;
    }
  }

  if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) {
    Expr *CopyExpr = Record.readExpr();
    if (CopyExpr)
      Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt());
  }

  if (VD->getStorageDuration() == SD_Static && Record.readInt())
    Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile;

  enum VarKind {
    VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization
  };
  switch ((VarKind)Record.readInt()) {
  case VarNotTemplate:
    // Only true variables (not parameters or implicit parameters) can be
    // merged; the other kinds are not really redeclarable at all.
    if (!isa<ParmVarDecl>(VD) && !isa<ImplicitParamDecl>(VD) &&
        !isa<VarTemplateSpecializationDecl>(VD))
      mergeRedeclarable(VD, Redecl);
    break;
  case VarTemplate:
    // Merged when we merge the template.
    VD->setDescribedVarTemplate(ReadDeclAs<VarTemplateDecl>());
    break;
  case StaticDataMemberSpecialization: { // HasMemberSpecializationInfo.
    auto *Tmpl = ReadDeclAs<VarDecl>();
    auto TSK = (TemplateSpecializationKind)Record.readInt();
    SourceLocation POI = ReadSourceLocation();
    Reader.getContext().setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
    mergeRedeclarable(VD, Redecl);
    break;
  }
  }

  return Redecl;
}

void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) {
  VisitVarDecl(PD);
}

void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
  VisitVarDecl(PD);
  unsigned isObjCMethodParam = Record.readInt();
  unsigned scopeDepth = Record.readInt();
  unsigned scopeIndex = Record.readInt();
  unsigned declQualifier = Record.readInt();
  if (isObjCMethodParam) {
    assert(scopeDepth == 0);
    PD->setObjCMethodScopeInfo(scopeIndex);
    PD->ParmVarDeclBits.ScopeDepthOrObjCQuals = declQualifier;
  } else {
    PD->setScopeInfo(scopeDepth, scopeIndex);
  }
  PD->ParmVarDeclBits.IsKNRPromoted = Record.readInt();
  PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt();
  if (Record.readInt()) // hasUninstantiatedDefaultArg.
    PD->setUninstantiatedDefaultArg(Record.readExpr());

  // FIXME: If this is a redeclaration of a function from another module, handle
  // inheritance of default arguments.
}

void ASTDeclReader::VisitDecompositionDecl(DecompositionDecl *DD) {
  VisitVarDecl(DD);
  auto **BDs = DD->getTrailingObjects<BindingDecl *>();
  for (unsigned I = 0; I != DD->NumBindings; ++I) {
    BDs[I] = ReadDeclAs<BindingDecl>();
    BDs[I]->setDecomposedDecl(DD);
  }
}

void ASTDeclReader::VisitBindingDecl(BindingDecl *BD) {
  VisitValueDecl(BD);
  BD->Binding = Record.readExpr();
}

void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
  VisitDecl(AD);
  AD->setAsmString(cast<StringLiteral>(Record.readExpr()));
  AD->setRParenLoc(ReadSourceLocation());
}

void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) {
  VisitDecl(BD);
  BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt()));
  BD->setSignatureAsWritten(GetTypeSourceInfo());
  unsigned NumParams = Record.readInt();
  SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(ReadDeclAs<ParmVarDecl>());
  BD->setParams(Params);

  BD->setIsVariadic(Record.readInt());
  BD->setBlockMissingReturnType(Record.readInt());
  BD->setIsConversionFromLambda(Record.readInt());
  BD->setDoesNotEscape(Record.readInt());
  BD->setCanAvoidCopyToHeap(Record.readInt());

  bool capturesCXXThis = Record.readInt();
  unsigned numCaptures = Record.readInt();
  SmallVector<BlockDecl::Capture, 16> captures;
  captures.reserve(numCaptures);
  for (unsigned i = 0; i != numCaptures; ++i) {
    auto *decl = ReadDeclAs<VarDecl>();
    unsigned flags = Record.readInt();
    bool byRef = (flags & 1);
    bool nested = (flags & 2);
    Expr *copyExpr = ((flags & 4) ? Record.readExpr() : nullptr);

    captures.push_back(BlockDecl::Capture(decl, byRef, nested, copyExpr));
  }
  BD->setCaptures(Reader.getContext(), captures, capturesCXXThis);
}

void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) {
  VisitDecl(CD);
  unsigned ContextParamPos = Record.readInt();
  CD->setNothrow(Record.readInt() != 0);
  // Body is set by VisitCapturedStmt.
  for (unsigned I = 0; I < CD->NumParams; ++I) {
    if (I != ContextParamPos)
      CD->setParam(I, ReadDeclAs<ImplicitParamDecl>());
    else
      CD->setContextParam(I, ReadDeclAs<ImplicitParamDecl>());
  }
}

void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
  VisitDecl(D);
  D->setLanguage((LinkageSpecDecl::LanguageIDs)Record.readInt());
  D->setExternLoc(ReadSourceLocation());
  D->setRBraceLoc(ReadSourceLocation());
}

void ASTDeclReader::VisitExportDecl(ExportDecl *D) {
  VisitDecl(D);
  D->RBraceLoc = ReadSourceLocation();
}

void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
  VisitNamedDecl(D);
  D->setLocStart(ReadSourceLocation());
}

void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarable(D);
  VisitNamedDecl(D);
  D->setInline(Record.readInt());
  D->LocStart = ReadSourceLocation();
  D->RBraceLoc = ReadSourceLocation();

  // Defer loading the anonymous namespace until we've finished merging
  // this namespace; loading it might load a later declaration of the
  // same namespace, and we have an invariant that older declarations
  // get merged before newer ones try to merge.
  GlobalDeclID AnonNamespace = 0;
  if (Redecl.getFirstID() == ThisDeclID) {
    AnonNamespace = ReadDeclID();
  } else {
    // Link this namespace back to the first declaration, which has already
    // been deserialized.
    D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
  }

  mergeRedeclarable(D, Redecl);

  if (AnonNamespace) {
    // Each module has its own anonymous namespace, which is disjoint from
    // any other module's anonymous namespaces, so don't attach the anonymous
    // namespace at all.
    auto *Anon = cast<NamespaceDecl>(Reader.GetDecl(AnonNamespace));
    if (!Record.isModule())
      D->setAnonymousNamespace(Anon);
  }
}

void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarable(D);
  VisitNamedDecl(D);
  D->NamespaceLoc = ReadSourceLocation();
  D->IdentLoc = ReadSourceLocation();
  D->QualifierLoc = Record.readNestedNameSpecifierLoc();
  D->Namespace = ReadDeclAs<NamedDecl>();
  mergeRedeclarable(D, Redecl);
}

void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
  VisitNamedDecl(D);
  D->setUsingLoc(ReadSourceLocation());
  D->QualifierLoc = Record.readNestedNameSpecifierLoc();
  ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
  D->FirstUsingShadow.setPointer(ReadDeclAs<UsingShadowDecl>());
  D->setTypename(Record.readInt());
  if (auto *Pattern = ReadDeclAs<NamedDecl>())
    Reader.getContext().setInstantiatedFromUsingDecl(D, Pattern);
  mergeMergeable(D);
}

void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) {
  VisitNamedDecl(D);
  D->InstantiatedFrom = ReadDeclAs<NamedDecl>();
  auto **Expansions = D->getTrailingObjects<NamedDecl *>();
  for (unsigned I = 0; I != D->NumExpansions; ++I)
    Expansions[I] = ReadDeclAs<NamedDecl>();
  mergeMergeable(D);
}

void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarable(D);
  VisitNamedDecl(D);
  D->Underlying = ReadDeclAs<NamedDecl>();
  D->IdentifierNamespace = Record.readInt();
  D->UsingOrNextShadow = ReadDeclAs<NamedDecl>();
  auto *Pattern = ReadDeclAs<UsingShadowDecl>();
  if (Pattern)
    Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
  mergeRedeclarable(D, Redecl);
}

void ASTDeclReader::VisitConstructorUsingShadowDecl(
    ConstructorUsingShadowDecl *D) {
  VisitUsingShadowDecl(D);
  D->NominatedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>();
  D->ConstructedBaseClassShadowDecl = ReadDeclAs<ConstructorUsingShadowDecl>();
  D->IsVirtual = Record.readInt();
}

void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
  VisitNamedDecl(D);
  D->UsingLoc = ReadSourceLocation();
  D->NamespaceLoc = ReadSourceLocation();
  D->QualifierLoc = Record.readNestedNameSpecifierLoc();
  D->NominatedNamespace = ReadDeclAs<NamedDecl>();
  D->CommonAncestor = ReadDeclAs<DeclContext>();
}

void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
  VisitValueDecl(D);
  D->setUsingLoc(ReadSourceLocation());
  D->QualifierLoc = Record.readNestedNameSpecifierLoc();
  ReadDeclarationNameLoc(D->DNLoc, D->getDeclName());
  D->EllipsisLoc = ReadSourceLocation();
  mergeMergeable(D);
}

void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
                                               UnresolvedUsingTypenameDecl *D) {
  VisitTypeDecl(D);
  D->TypenameLocation = ReadSourceLocation();
  D->QualifierLoc = Record.readNestedNameSpecifierLoc();
  D->EllipsisLoc = ReadSourceLocation();
  mergeMergeable(D);
}

void ASTDeclReader::ReadCXXDefinitionData(
    struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) {
  // Note: the caller has deserialized the IsLambda bit already.
  Data.UserDeclaredConstructor = Record.readInt();
  Data.UserDeclaredSpecialMembers = Record.readInt();
  Data.Aggregate = Record.readInt();
  Data.PlainOldData = Record.readInt();
  Data.Empty = Record.readInt();
  Data.Polymorphic = Record.readInt();
  Data.Abstract = Record.readInt();
  Data.IsStandardLayout = Record.readInt();
  Data.IsCXX11StandardLayout = Record.readInt();
  Data.HasBasesWithFields = Record.readInt();
  Data.HasBasesWithNonStaticDataMembers = Record.readInt();
  Data.HasPrivateFields = Record.readInt();
  Data.HasProtectedFields = Record.readInt();
  Data.HasPublicFields = Record.readInt();
  Data.HasMutableFields = Record.readInt();
  Data.HasVariantMembers = Record.readInt();
  Data.HasOnlyCMembers = Record.readInt();
  Data.HasInClassInitializer = Record.readInt();
  Data.HasUninitializedReferenceMember = Record.readInt();
  Data.HasUninitializedFields = Record.readInt();
  Data.HasInheritedConstructor = Record.readInt();
  Data.HasInheritedAssignment = Record.readInt();
  Data.NeedOverloadResolutionForCopyConstructor = Record.readInt();
  Data.NeedOverloadResolutionForMoveConstructor = Record.readInt();
  Data.NeedOverloadResolutionForMoveAssignment = Record.readInt();
  Data.NeedOverloadResolutionForDestructor = Record.readInt();
  Data.DefaultedCopyConstructorIsDeleted = Record.readInt();
  Data.DefaultedMoveConstructorIsDeleted = Record.readInt();
  Data.DefaultedMoveAssignmentIsDeleted = Record.readInt();
  Data.DefaultedDestructorIsDeleted = Record.readInt();
  Data.HasTrivialSpecialMembers = Record.readInt();
  Data.HasTrivialSpecialMembersForCall = Record.readInt();
  Data.DeclaredNonTrivialSpecialMembers = Record.readInt();
  Data.DeclaredNonTrivialSpecialMembersForCall = Record.readInt();
  Data.HasIrrelevantDestructor = Record.readInt();
  Data.HasConstexprNonCopyMoveConstructor = Record.readInt();
  Data.HasDefaultedDefaultConstructor = Record.readInt();
  Data.DefaultedDefaultConstructorIsConstexpr = Record.readInt();
  Data.HasConstexprDefaultConstructor = Record.readInt();
  Data.HasNonLiteralTypeFieldsOrBases = Record.readInt();
  Data.ComputedVisibleConversions = Record.readInt();
  Data.UserProvidedDefaultConstructor = Record.readInt();
  Data.DeclaredSpecialMembers = Record.readInt();
  Data.ImplicitCopyConstructorCanHaveConstParamForVBase = Record.readInt();
  Data.ImplicitCopyConstructorCanHaveConstParamForNonVBase = Record.readInt();
  Data.ImplicitCopyAssignmentHasConstParam = Record.readInt();
  Data.HasDeclaredCopyConstructorWithConstParam = Record.readInt();
  Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt();
  Data.ODRHash = Record.readInt();
  Data.HasODRHash = true;

  if (Record.readInt())
    Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile;

  Data.NumBases = Record.readInt();
  if (Data.NumBases)
    Data.Bases = ReadGlobalOffset();
  Data.NumVBases = Record.readInt();
  if (Data.NumVBases)
    Data.VBases = ReadGlobalOffset();

  Record.readUnresolvedSet(Data.Conversions);
  Record.readUnresolvedSet(Data.VisibleConversions);
  assert(Data.Definition && "Data.Definition should be already set!");
  Data.FirstFriend = ReadDeclID();

  if (Data.IsLambda) {
    using Capture = LambdaCapture;

    auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data);
    Lambda.Dependent = Record.readInt();
    Lambda.IsGenericLambda = Record.readInt();
    Lambda.CaptureDefault = Record.readInt();
    Lambda.NumCaptures = Record.readInt();
    Lambda.NumExplicitCaptures = Record.readInt();
    Lambda.ManglingNumber = Record.readInt();
    Lambda.ContextDecl = ReadDeclID();
    Lambda.Captures = (Capture *)Reader.getContext().Allocate(
        sizeof(Capture) * Lambda.NumCaptures);
    Capture *ToCapture = Lambda.Captures;
    Lambda.MethodTyInfo = GetTypeSourceInfo();
    for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
      SourceLocation Loc = ReadSourceLocation();
      bool IsImplicit = Record.readInt();
      auto Kind = static_cast<LambdaCaptureKind>(Record.readInt());
      switch (Kind) {
      case LCK_StarThis:
      case LCK_This:
      case LCK_VLAType:
        *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
        break;
      case LCK_ByCopy:
      case LCK_ByRef:
        auto *Var = ReadDeclAs<VarDecl>();
        SourceLocation EllipsisLoc = ReadSourceLocation();
        *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
        break;
      }
    }
  }
}

void ASTDeclReader::MergeDefinitionData(
    CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&MergeDD) {
  assert(D->DefinitionData &&
         "merging class definition into non-definition");
  auto &DD = *D->DefinitionData;

  if (DD.Definition != MergeDD.Definition) {
    // Track that we merged the definitions.
    Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
                                                    DD.Definition));
    Reader.PendingDefinitions.erase(MergeDD.Definition);
    MergeDD.Definition->setCompleteDefinition(false);
    Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
    assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
           "already loaded pending lookups for merged definition");
  }

  auto PFDI = Reader.PendingFakeDefinitionData.find(&DD);
  if (PFDI != Reader.PendingFakeDefinitionData.end() &&
      PFDI->second == ASTReader::PendingFakeDefinitionKind::Fake) {
    // We faked up this definition data because we found a class for which we'd
    // not yet loaded the definition. Replace it with the real thing now.
    assert(!DD.IsLambda && !MergeDD.IsLambda && "faked up lambda definition?");
    PFDI->second = ASTReader::PendingFakeDefinitionKind::FakeLoaded;

    // Don't change which declaration is the definition; that is required
    // to be invariant once we select it.
    auto *Def = DD.Definition;
    DD = std::move(MergeDD);
    DD.Definition = Def;
    return;
  }

  // FIXME: Move this out into a .def file?
  bool DetectedOdrViolation = false;
#define OR_FIELD(Field) DD.Field |= MergeDD.Field;
#define MATCH_FIELD(Field) \
    DetectedOdrViolation |= DD.Field != MergeDD.Field; \
    OR_FIELD(Field)
  MATCH_FIELD(UserDeclaredConstructor)
  MATCH_FIELD(UserDeclaredSpecialMembers)
  MATCH_FIELD(Aggregate)
  MATCH_FIELD(PlainOldData)
  MATCH_FIELD(Empty)
  MATCH_FIELD(Polymorphic)
  MATCH_FIELD(Abstract)
  MATCH_FIELD(IsStandardLayout)
  MATCH_FIELD(IsCXX11StandardLayout)
  MATCH_FIELD(HasBasesWithFields)
  MATCH_FIELD(HasBasesWithNonStaticDataMembers)
  MATCH_FIELD(HasPrivateFields)
  MATCH_FIELD(HasProtectedFields)
  MATCH_FIELD(HasPublicFields)
  MATCH_FIELD(HasMutableFields)
  MATCH_FIELD(HasVariantMembers)
  MATCH_FIELD(HasOnlyCMembers)
  MATCH_FIELD(HasInClassInitializer)
  MATCH_FIELD(HasUninitializedReferenceMember)
  MATCH_FIELD(HasUninitializedFields)
  MATCH_FIELD(HasInheritedConstructor)
  MATCH_FIELD(HasInheritedAssignment)
  MATCH_FIELD(NeedOverloadResolutionForCopyConstructor)
  MATCH_FIELD(NeedOverloadResolutionForMoveConstructor)
  MATCH_FIELD(NeedOverloadResolutionForMoveAssignment)
  MATCH_FIELD(NeedOverloadResolutionForDestructor)
  MATCH_FIELD(DefaultedCopyConstructorIsDeleted)
  MATCH_FIELD(DefaultedMoveConstructorIsDeleted)
  MATCH_FIELD(DefaultedMoveAssignmentIsDeleted)
  MATCH_FIELD(DefaultedDestructorIsDeleted)
  OR_FIELD(HasTrivialSpecialMembers)
  OR_FIELD(HasTrivialSpecialMembersForCall)
  OR_FIELD(DeclaredNonTrivialSpecialMembers)
  OR_FIELD(DeclaredNonTrivialSpecialMembersForCall)
  MATCH_FIELD(HasIrrelevantDestructor)
  OR_FIELD(HasConstexprNonCopyMoveConstructor)
  OR_FIELD(HasDefaultedDefaultConstructor)
  MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
  OR_FIELD(HasConstexprDefaultConstructor)
  MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
  // ComputedVisibleConversions is handled below.
  MATCH_FIELD(UserProvidedDefaultConstructor)
  OR_FIELD(DeclaredSpecialMembers)
  MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForVBase)
  MATCH_FIELD(ImplicitCopyConstructorCanHaveConstParamForNonVBase)
  MATCH_FIELD(ImplicitCopyAssignmentHasConstParam)
  OR_FIELD(HasDeclaredCopyConstructorWithConstParam)
  OR_FIELD(HasDeclaredCopyAssignmentWithConstParam)
  MATCH_FIELD(IsLambda)
#undef OR_FIELD
#undef MATCH_FIELD

  if (DD.NumBases != MergeDD.NumBases || DD.NumVBases != MergeDD.NumVBases)
    DetectedOdrViolation = true;
  // FIXME: Issue a diagnostic if the base classes don't match when we come
  // to lazily load them.

  // FIXME: Issue a diagnostic if the list of conversion functions doesn't
  // match when we come to lazily load them.
  if (MergeDD.ComputedVisibleConversions && !DD.ComputedVisibleConversions) {
    DD.VisibleConversions = std::move(MergeDD.VisibleConversions);
    DD.ComputedVisibleConversions = true;
  }

  // FIXME: Issue a diagnostic if FirstFriend doesn't match when we come to
  // lazily load it.

  if (DD.IsLambda) {
    // FIXME: ODR-checking for merging lambdas (this happens, for instance,
    // when they occur within the body of a function template specialization).
  }

  if (D->getODRHash() != MergeDD.ODRHash) {
    DetectedOdrViolation = true;
  }

  if (DetectedOdrViolation)
    Reader.PendingOdrMergeFailures[DD.Definition].push_back(
        {MergeDD.Definition, &MergeDD});
}

void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
  struct CXXRecordDecl::DefinitionData *DD;
  ASTContext &C = Reader.getContext();

  // Determine whether this is a lambda closure type, so that we can
  // allocate the appropriate DefinitionData structure.
  bool IsLambda = Record.readInt();
  if (IsLambda)
    DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false,
                                                     LCD_None);
  else
    DD = new (C) struct CXXRecordDecl::DefinitionData(D);

  CXXRecordDecl *Canon = D->getCanonicalDecl();
  // Set decl definition data before reading it, so that during deserialization
  // when we read CXXRecordDecl, it already has definition data and we don't
  // set fake one.
  if (!Canon->DefinitionData)
    Canon->DefinitionData = DD;
  D->DefinitionData = Canon->DefinitionData;
  ReadCXXDefinitionData(*DD, D);

  // We might already have a different definition for this record. This can
  // happen either because we're reading an update record, or because we've
  // already done some merging. Either way, just merge into it.
  if (Canon->DefinitionData != DD) {
    MergeDefinitionData(Canon, std::move(*DD));
    return;
  }

  // Mark this declaration as being a definition.
  D->setCompleteDefinition(true);

  // If this is not the first declaration or is an update record, we can have
  // other redeclarations already. Make a note that we need to propagate the
  // DefinitionData pointer onto them.
  if (Update || Canon != D)
    Reader.PendingDefinitions.insert(D);
}

ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
  RedeclarableResult Redecl = VisitRecordDeclImpl(D);

  ASTContext &C = Reader.getContext();

  enum CXXRecKind {
    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
  };
  switch ((CXXRecKind)Record.readInt()) {
  case CXXRecNotTemplate:
    // Merged when we merge the folding set entry in the primary template.
    if (!isa<ClassTemplateSpecializationDecl>(D))
      mergeRedeclarable(D, Redecl);
    break;
  case CXXRecTemplate: {
    // Merged when we merge the template.
    auto *Template = ReadDeclAs<ClassTemplateDecl>();
    D->TemplateOrInstantiation = Template;
    if (!Template->getTemplatedDecl()) {
      // We've not actually loaded the ClassTemplateDecl yet, because we're
      // currently being loaded as its pattern. Rely on it to set up our
      // TypeForDecl (see VisitClassTemplateDecl).
      //
      // Beware: we do not yet know our canonical declaration, and may still
      // get merged once the surrounding class template has got off the ground.
      DeferredTypeID = 0;
    }
    break;
  }
  case CXXRecMemberSpecialization: {
    auto *RD = ReadDeclAs<CXXRecordDecl>();
    auto TSK = (TemplateSpecializationKind)Record.readInt();
    SourceLocation POI = ReadSourceLocation();
    MemberSpecializationInfo *MSI = new (C) MemberSpecializationInfo(RD, TSK);
    MSI->setPointOfInstantiation(POI);
    D->TemplateOrInstantiation = MSI;
    mergeRedeclarable(D, Redecl);
    break;
  }
  }

  bool WasDefinition = Record.readInt();
  if (WasDefinition)
    ReadCXXRecordDefinition(D, /*Update*/false);
  else
    // Propagate DefinitionData pointer from the canonical declaration.
    D->DefinitionData = D->getCanonicalDecl()->DefinitionData;

  // Lazily load the key function to avoid deserializing every method so we can
  // compute it.
  if (WasDefinition) {
    DeclID KeyFn = ReadDeclID();
    if (KeyFn && D->isCompleteDefinition())
      // FIXME: This is wrong for the ARM ABI, where some other module may have
      // made this function no longer be a key function. We need an update
      // record or similar for that case.
      C.KeyFunctions[D] = KeyFn;
  }

  return Redecl;
}

void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
  D->setExplicitSpecifier(Record.readExplicitSpec());
  VisitFunctionDecl(D);
  D->setIsCopyDeductionCandidate(Record.readInt());
}

void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
  VisitFunctionDecl(D);

  unsigned NumOverridenMethods = Record.readInt();
  if (D->isCanonicalDecl()) {
    while (NumOverridenMethods--) {
      // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
      // MD may be initializing.
      if (auto *MD = ReadDeclAs<CXXMethodDecl>())
        Reader.getContext().addOverriddenMethod(D, MD->getCanonicalDecl());
    }
  } else {
    // We don't care about which declarations this used to override; we get
    // the relevant information from the canonical declaration.
    Record.skipInts(NumOverridenMethods);
  }
}

void ASTDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
  // We need the inherited constructor information to merge the declaration,
  // so we have to read it before we call VisitCXXMethodDecl.
  D->setExplicitSpecifier(Record.readExplicitSpec());
  if (D->isInheritingConstructor()) {
    auto *Shadow = ReadDeclAs<ConstructorUsingShadowDecl>();
    auto *Ctor = ReadDeclAs<CXXConstructorDecl>();
    *D->getTrailingObjects<InheritedConstructor>() =
        InheritedConstructor(Shadow, Ctor);
  }

  VisitCXXMethodDecl(D);
}

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

  if (auto *OperatorDelete = ReadDeclAs<FunctionDecl>()) {
    CXXDestructorDecl *Canon = D->getCanonicalDecl();
    auto *ThisArg = Record.readExpr();
    // FIXME: Check consistency if we have an old and new operator delete.
    if (!Canon->OperatorDelete) {
      Canon->OperatorDelete = OperatorDelete;
      Canon->OperatorDeleteThisArg = ThisArg;
    }
  }
}

void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
  D->setExplicitSpecifier(Record.readExplicitSpec());
  VisitCXXMethodDecl(D);
}

void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
  VisitDecl(D);
  D->ImportedAndComplete.setPointer(readModule());
  D->ImportedAndComplete.setInt(Record.readInt());
  auto *StoredLocs = D->getTrailingObjects<SourceLocation>();
  for (unsigned I = 0, N = Record.back(); I != N; ++I)
    StoredLocs[I] = ReadSourceLocation();
  Record.skipInts(1); // The number of stored source locations.
}

void ASTDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
  VisitDecl(D);
  D->setColonLoc(ReadSourceLocation());
}

void ASTDeclReader::VisitFriendDecl(FriendDecl *D) {
  VisitDecl(D);
  if (Record.readInt()) // hasFriendDecl
    D->Friend = ReadDeclAs<NamedDecl>();
  else
    D->Friend = GetTypeSourceInfo();
  for (unsigned i = 0; i != D->NumTPLists; ++i)
    D->getTrailingObjects<TemplateParameterList *>()[i] =
        Record.readTemplateParameterList();
  D->NextFriend = ReadDeclID();
  D->UnsupportedFriend = (Record.readInt() != 0);
  D->FriendLoc = ReadSourceLocation();
}

void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
  VisitDecl(D);
  unsigned NumParams = Record.readInt();
  D->NumParams = NumParams;
  D->Params = new TemplateParameterList*[NumParams];
  for (unsigned i = 0; i != NumParams; ++i)
    D->Params[i] = Record.readTemplateParameterList();
  if (Record.readInt()) // HasFriendDecl
    D->Friend = ReadDeclAs<NamedDecl>();
  else
    D->Friend = GetTypeSourceInfo();
  D->FriendLoc = ReadSourceLocation();
}

DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
  VisitNamedDecl(D);

  DeclID PatternID = ReadDeclID();
  auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
  TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
  // FIXME handle associated constraints
  D->init(TemplatedDecl, TemplateParams);

  return PatternID;
}

ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarable(D);

  // Make sure we've allocated the Common pointer first. We do this before
  // VisitTemplateDecl so that getCommonPtr() can be used during initialization.
  RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
  if (!CanonD->Common) {
    CanonD->Common = CanonD->newCommon(Reader.getContext());
    Reader.PendingDefinitions.insert(CanonD);
  }
  D->Common = CanonD->Common;

  // If this is the first declaration of the template, fill in the information
  // for the 'common' pointer.
  if (ThisDeclID == Redecl.getFirstID()) {
    if (auto *RTD = ReadDeclAs<RedeclarableTemplateDecl>()) {
      assert(RTD->getKind() == D->getKind() &&
             "InstantiatedFromMemberTemplate kind mismatch");
      D->setInstantiatedFromMemberTemplate(RTD);
      if (Record.readInt())
        D->setMemberSpecialization();
    }
  }

  DeclID PatternID = VisitTemplateDecl(D);
  D->IdentifierNamespace = Record.readInt();

  mergeRedeclarable(D, Redecl, PatternID);

  // If we merged the template with a prior declaration chain, merge the common
  // pointer.
  // FIXME: Actually merge here, don't just overwrite.
  D->Common = D->getCanonicalDecl()->Common;

  return Redecl;
}

void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);

  if (ThisDeclID == Redecl.getFirstID()) {
    // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
    // the specializations.
    SmallVector<serialization::DeclID, 32> SpecIDs;
    ReadDeclIDList(SpecIDs);
    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
  }

  if (D->getTemplatedDecl()->TemplateOrInstantiation) {
    // We were loaded before our templated declaration was. We've not set up
    // its corresponding type yet (see VisitCXXRecordDeclImpl), so reconstruct
    // it now.
    Reader.getContext().getInjectedClassNameType(
        D->getTemplatedDecl(), D->getInjectedClassNameSpecialization());
  }
}

void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
  llvm_unreachable("BuiltinTemplates are not serialized");
}

/// TODO: Unify with ClassTemplateDecl version?
///       May require unifying ClassTemplateDecl and
///        VarTemplateDecl beyond TemplateDecl...
void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);

  if (ThisDeclID == Redecl.getFirstID()) {
    // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of
    // the specializations.
    SmallVector<serialization::DeclID, 32> SpecIDs;
    ReadDeclIDList(SpecIDs);
    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
  }
}

ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
    ClassTemplateSpecializationDecl *D) {
  RedeclarableResult Redecl = VisitCXXRecordDeclImpl(D);

  ASTContext &C = Reader.getContext();
  if (Decl *InstD = ReadDecl()) {
    if (auto *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
      D->SpecializedTemplate = CTD;
    } else {
      SmallVector<TemplateArgument, 8> TemplArgs;
      Record.readTemplateArgumentList(TemplArgs);
      TemplateArgumentList *ArgList
        = TemplateArgumentList::CreateCopy(C, TemplArgs);
      auto *PS =
          new (C) ClassTemplateSpecializationDecl::
                                             SpecializedPartialSpecialization();
      PS->PartialSpecialization
          = cast<ClassTemplatePartialSpecializationDecl>(InstD);
      PS->TemplateArgs = ArgList;
      D->SpecializedTemplate = PS;
    }
  }

  SmallVector<TemplateArgument, 8> TemplArgs;
  Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
  D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
  D->PointOfInstantiation = ReadSourceLocation();
  D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();

  bool writtenAsCanonicalDecl = Record.readInt();
  if (writtenAsCanonicalDecl) {
    auto *CanonPattern = ReadDeclAs<ClassTemplateDecl>();
    if (D->isCanonicalDecl()) { // It's kept in the folding set.
      // Set this as, or find, the canonical declaration for this specialization
      ClassTemplateSpecializationDecl *CanonSpec;
      if (auto *Partial = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
        CanonSpec = CanonPattern->getCommonPtr()->PartialSpecializations
            .GetOrInsertNode(Partial);
      } else {
        CanonSpec =
            CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
      }
      // If there was already a canonical specialization, merge into it.
      if (CanonSpec != D) {
        mergeRedeclarable<TagDecl>(D, CanonSpec, Redecl);

        // This declaration might be a definition. Merge with any existing
        // definition.
        if (auto *DDD = D->DefinitionData) {
          if (CanonSpec->DefinitionData)
            MergeDefinitionData(CanonSpec, std::move(*DDD));
          else
            CanonSpec->DefinitionData = D->DefinitionData;
        }
        D->DefinitionData = CanonSpec->DefinitionData;
      }
    }
  }

  // Explicit info.
  if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
    auto *ExplicitInfo =
        new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo;
    ExplicitInfo->TypeAsWritten = TyInfo;
    ExplicitInfo->ExternLoc = ReadSourceLocation();
    ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation();
    D->ExplicitInfo = ExplicitInfo;
  }

  return Redecl;
}

void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
                                    ClassTemplatePartialSpecializationDecl *D) {
  RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);

  D->TemplateParams = Record.readTemplateParameterList();
  D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();

  // These are read/set from/to the first declaration.
  if (ThisDeclID == Redecl.getFirstID()) {
    D->InstantiatedFromMember.setPointer(
      ReadDeclAs<ClassTemplatePartialSpecializationDecl>());
    D->InstantiatedFromMember.setInt(Record.readInt());
  }
}

void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
                                    ClassScopeFunctionSpecializationDecl *D) {
  VisitDecl(D);
  D->Specialization = ReadDeclAs<CXXMethodDecl>();
  if (Record.readInt())
    D->TemplateArgs = Record.readASTTemplateArgumentListInfo();
}

void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);

  if (ThisDeclID == Redecl.getFirstID()) {
    // This FunctionTemplateDecl owns a CommonPtr; read it.
    SmallVector<serialization::DeclID, 32> SpecIDs;
    ReadDeclIDList(SpecIDs);
    ASTDeclReader::AddLazySpecializations(D, SpecIDs);
  }
}

/// TODO: Unify with ClassTemplateSpecializationDecl version?
///       May require unifying ClassTemplate(Partial)SpecializationDecl and
///        VarTemplate(Partial)SpecializationDecl with a new data
///        structure Template(Partial)SpecializationDecl, and
///        using Template(Partial)SpecializationDecl as input type.
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
    VarTemplateSpecializationDecl *D) {
  RedeclarableResult Redecl = VisitVarDeclImpl(D);

  ASTContext &C = Reader.getContext();
  if (Decl *InstD = ReadDecl()) {
    if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) {
      D->SpecializedTemplate = VTD;
    } else {
      SmallVector<TemplateArgument, 8> TemplArgs;
      Record.readTemplateArgumentList(TemplArgs);
      TemplateArgumentList *ArgList = TemplateArgumentList::CreateCopy(
          C, TemplArgs);
      auto *PS =
          new (C)
          VarTemplateSpecializationDecl::SpecializedPartialSpecialization();
      PS->PartialSpecialization =
          cast<VarTemplatePartialSpecializationDecl>(InstD);
      PS->TemplateArgs = ArgList;
      D->SpecializedTemplate = PS;
    }
  }

  // Explicit info.
  if (TypeSourceInfo *TyInfo = GetTypeSourceInfo()) {
    auto *ExplicitInfo =
        new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo;
    ExplicitInfo->TypeAsWritten = TyInfo;
    ExplicitInfo->ExternLoc = ReadSourceLocation();
    ExplicitInfo->TemplateKeywordLoc = ReadSourceLocation();
    D->ExplicitInfo = ExplicitInfo;
  }

  SmallVector<TemplateArgument, 8> TemplArgs;
  Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
  D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
  D->PointOfInstantiation = ReadSourceLocation();
  D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
  D->IsCompleteDefinition = Record.readInt();

  bool writtenAsCanonicalDecl = Record.readInt();
  if (writtenAsCanonicalDecl) {
    auto *CanonPattern = ReadDeclAs<VarTemplateDecl>();
    if (D->isCanonicalDecl()) { // It's kept in the folding set.
      // FIXME: If it's already present, merge it.
      if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) {
        CanonPattern->getCommonPtr()->PartialSpecializations
            .GetOrInsertNode(Partial);
      } else {
        CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D);
      }
    }
  }

  return Redecl;
}

/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
///       May require unifying ClassTemplate(Partial)SpecializationDecl and
///        VarTemplate(Partial)SpecializationDecl with a new data
///        structure Template(Partial)SpecializationDecl, and
///        using Template(Partial)SpecializationDecl as input type.
void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
    VarTemplatePartialSpecializationDecl *D) {
  RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);

  D->TemplateParams = Record.readTemplateParameterList();
  D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();

  // These are read/set from/to the first declaration.
  if (ThisDeclID == Redecl.getFirstID()) {
    D->InstantiatedFromMember.setPointer(
        ReadDeclAs<VarTemplatePartialSpecializationDecl>());
    D->InstantiatedFromMember.setInt(Record.readInt());
  }
}

void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
  VisitTypeDecl(D);

  D->setDeclaredWithTypename(Record.readInt());

  if (Record.readInt())
    D->setDefaultArgument(GetTypeSourceInfo());
}

void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
  VisitDeclaratorDecl(D);
  // TemplateParmPosition.
  D->setDepth(Record.readInt());
  D->setPosition(Record.readInt());
  if (D->isExpandedParameterPack()) {
    auto TypesAndInfos =
        D->getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
    for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) {
      new (&TypesAndInfos[I].first) QualType(Record.readType());
      TypesAndInfos[I].second = GetTypeSourceInfo();
    }
  } else {
    // Rest of NonTypeTemplateParmDecl.
    D->ParameterPack = Record.readInt();
    if (Record.readInt())
      D->setDefaultArgument(Record.readExpr());
  }
}

void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
  VisitTemplateDecl(D);
  // TemplateParmPosition.
  D->setDepth(Record.readInt());
  D->setPosition(Record.readInt());
  if (D->isExpandedParameterPack()) {
    auto **Data = D->getTrailingObjects<TemplateParameterList *>();
    for (unsigned I = 0, N = D->getNumExpansionTemplateParameters();
         I != N; ++I)
      Data[I] = Record.readTemplateParameterList();
  } else {
    // Rest of TemplateTemplateParmDecl.
    D->ParameterPack = Record.readInt();
    if (Record.readInt())
      D->setDefaultArgument(Reader.getContext(),
                            Record.readTemplateArgumentLoc());
  }
}

void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {
  VisitRedeclarableTemplateDecl(D);
}

void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
  VisitDecl(D);
  D->AssertExprAndFailed.setPointer(Record.readExpr());
  D->AssertExprAndFailed.setInt(Record.readInt());
  D->Message = cast_or_null<StringLiteral>(Record.readExpr());
  D->RParenLoc = ReadSourceLocation();
}

void ASTDeclReader::VisitEmptyDecl(EmptyDecl *D) {
  VisitDecl(D);
}

std::pair<uint64_t, uint64_t>
ASTDeclReader::VisitDeclContext(DeclContext *DC) {
  uint64_t LexicalOffset = ReadLocalOffset();
  uint64_t VisibleOffset = ReadLocalOffset();
  return std::make_pair(LexicalOffset, VisibleOffset);
}

template <typename T>
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
  DeclID FirstDeclID = ReadDeclID();
  Decl *MergeWith = nullptr;

  bool IsKeyDecl = ThisDeclID == FirstDeclID;
  bool IsFirstLocalDecl = false;

  uint64_t RedeclOffset = 0;

  // 0 indicates that this declaration was the only declaration of its entity,
  // and is used for space optimization.
  if (FirstDeclID == 0) {
    FirstDeclID = ThisDeclID;
    IsKeyDecl = true;
    IsFirstLocalDecl = true;
  } else if (unsigned N = Record.readInt()) {
    // This declaration was the first local declaration, but may have imported
    // other declarations.
    IsKeyDecl = N == 1;
    IsFirstLocalDecl = true;

    // We have some declarations that must be before us in our redeclaration
    // chain. Read them now, and remember that we ought to merge with one of
    // them.
    // FIXME: Provide a known merge target to the second and subsequent such
    // declaration.
    for (unsigned I = 0; I != N - 1; ++I)
      MergeWith = ReadDecl();

    RedeclOffset = ReadLocalOffset();
  } else {
    // This declaration was not the first local declaration. Read the first
    // local declaration now, to trigger the import of other redeclarations.
    (void)ReadDecl();
  }

  auto *FirstDecl = cast_or_null<T>(Reader.GetDecl(FirstDeclID));
  if (FirstDecl != D) {
    // We delay loading of the redeclaration chain to avoid deeply nested calls.
    // We temporarily set the first (canonical) declaration as the previous one
    // which is the one that matters and mark the real previous DeclID to be
    // loaded & attached later on.
    D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
    D->First = FirstDecl->getCanonicalDecl();
  }

  auto *DAsT = static_cast<T *>(D);

  // Note that we need to load local redeclarations of this decl and build a
  // decl chain for them. This must happen *after* we perform the preloading
  // above; this ensures that the redeclaration chain is built in the correct
  // order.
  if (IsFirstLocalDecl)
    Reader.PendingDeclChains.push_back(std::make_pair(DAsT, RedeclOffset));

  return RedeclarableResult(MergeWith, FirstDeclID, IsKeyDecl);
}

/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase,
                                      RedeclarableResult &Redecl,
                                      DeclID TemplatePatternID) {
  // If modules are not available, there is no reason to perform this merge.
  if (!Reader.getContext().getLangOpts().Modules)
    return;

  // If we're not the canonical declaration, we don't need to merge.
  if (!DBase->isFirstDecl())
    return;

  auto *D = static_cast<T *>(DBase);

  if (auto *Existing = Redecl.getKnownMergeTarget())
    // We already know of an existing declaration we should merge with.
    mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID);
  else if (FindExistingResult ExistingRes = findExisting(D))
    if (T *Existing = ExistingRes)
      mergeRedeclarable(D, Existing, Redecl, TemplatePatternID);
}

/// "Cast" to type T, asserting if we don't have an implicit conversion.
/// We use this to put code in a template that will only be valid for certain
/// instantiations.
template<typename T> static T assert_cast(T t) { return t; }
template<typename T> static T assert_cast(...) {
  llvm_unreachable("bad assert_cast");
}

/// Merge together the pattern declarations from two template
/// declarations.
void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D,
                                         RedeclarableTemplateDecl *Existing,
                                         DeclID DsID, bool IsKeyDecl) {
  auto *DPattern = D->getTemplatedDecl();
  auto *ExistingPattern = Existing->getTemplatedDecl();
  RedeclarableResult Result(/*MergeWith*/ ExistingPattern,
                            DPattern->getCanonicalDecl()->getGlobalID(),
                            IsKeyDecl);

  if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) {
    // Merge with any existing definition.
    // FIXME: This is duplicated in several places. Refactor.
    auto *ExistingClass =
        cast<CXXRecordDecl>(ExistingPattern)->getCanonicalDecl();
    if (auto *DDD = DClass->DefinitionData) {
      if (ExistingClass->DefinitionData) {
        MergeDefinitionData(ExistingClass, std::move(*DDD));
      } else {
        ExistingClass->DefinitionData = DClass->DefinitionData;
        // We may have skipped this before because we thought that DClass
        // was the canonical declaration.
        Reader.PendingDefinitions.insert(DClass);
      }
    }
    DClass->DefinitionData = ExistingClass->DefinitionData;

    return mergeRedeclarable(DClass, cast<TagDecl>(ExistingPattern),
                             Result);
  }
  if (auto *DFunction = dyn_cast<FunctionDecl>(DPattern))
    return mergeRedeclarable(DFunction, cast<FunctionDecl>(ExistingPattern),
                             Result);
  if (auto *DVar = dyn_cast<VarDecl>(DPattern))
    return mergeRedeclarable(DVar, cast<VarDecl>(ExistingPattern), Result);
  if (auto *DAlias = dyn_cast<TypeAliasDecl>(DPattern))
    return mergeRedeclarable(DAlias, cast<TypedefNameDecl>(ExistingPattern),
                             Result);
  llvm_unreachable("merged an unknown kind of redeclarable template");
}

/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity.
template<typename T>
void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
                                      RedeclarableResult &Redecl,
                                      DeclID TemplatePatternID) {
  auto *D = static_cast<T *>(DBase);
  T *ExistingCanon = Existing->getCanonicalDecl();
  T *DCanon = D->getCanonicalDecl();
  if (ExistingCanon != DCanon) {
    assert(DCanon->getGlobalID() == Redecl.getFirstID() &&
           "already merged this declaration");

    // Have our redeclaration link point back at the canonical declaration
    // of the existing declaration, so that this declaration has the
    // appropriate canonical declaration.
    D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
    D->First = ExistingCanon;
    ExistingCanon->Used |= D->Used;
    D->Used = false;

    // When we merge a namespace, update its pointer to the first namespace.
    // We cannot have loaded any redeclarations of this declaration yet, so
    // there's nothing else that needs to be updated.
    if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
      Namespace->AnonOrFirstNamespaceAndInline.setPointer(
          assert_cast<NamespaceDecl*>(ExistingCanon));

    // When we merge a template, merge its pattern.
    if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
      mergeTemplatePattern(
          DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon),
          TemplatePatternID, Redecl.isKeyDecl());

    // If this declaration is a key declaration, make a note of that.
    if (Redecl.isKeyDecl())
      Reader.KeyDecls[ExistingCanon].push_back(Redecl.getFirstID());
  }
}

/// ODR-like semantics for C/ObjC allow us to merge tag types and a structural
/// check in Sema guarantees the types can be merged (see C11 6.2.7/1 or C89
/// 6.1.2.6/1). Although most merging is done in Sema, we need to guarantee
/// that some types are mergeable during deserialization, otherwise name
/// lookup fails. This is the case for EnumConstantDecl.
static bool allowODRLikeMergeInC(NamedDecl *ND) {
  if (!ND)
    return false;
  // TODO: implement merge for other necessary decls.
  if (isa<EnumConstantDecl>(ND))
    return true;
  return false;
}

/// Attempts to merge the given declaration (D) with another declaration
/// of the same entity, for the case where the entity is not actually
/// redeclarable. This happens, for instance, when merging the fields of
/// identical class definitions from two different modules.
template<typename T>
void ASTDeclReader::mergeMergeable(Mergeable<T> *D) {
  // If modules are not available, there is no reason to perform this merge.
  if (!Reader.getContext().getLangOpts().Modules)
    return;

  // ODR-based merging is performed in C++ and in some cases (tag types) in C.
  // Note that C identically-named things in different translation units are
  // not redeclarations, but may still have compatible types, where ODR-like
  // semantics may apply.
  if (!Reader.getContext().getLangOpts().CPlusPlus &&
      !allowODRLikeMergeInC(dyn_cast<NamedDecl>(static_cast<T*>(D))))
    return;

  if (FindExistingResult ExistingRes = findExisting(static_cast<T*>(D)))
    if (T *Existing = ExistingRes)
      Reader.getContext().setPrimaryMergedDecl(static_cast<T *>(D),
                                               Existing->getCanonicalDecl());
}

void ASTDeclReader::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) {
  VisitDecl(D);
  unsigned NumVars = D->varlist_size();
  SmallVector<Expr *, 16> Vars;
  Vars.reserve(NumVars);
  for (unsigned i = 0; i != NumVars; ++i) {
    Vars.push_back(Record.readExpr());
  }
  D->setVars(Vars);
}

void ASTDeclReader::VisitOMPAllocateDecl(OMPAllocateDecl *D) {
  VisitDecl(D);
  unsigned NumVars = D->varlist_size();
  unsigned NumClauses = D->clauselist_size();
  SmallVector<Expr *, 16> Vars;
  Vars.reserve(NumVars);
  for (unsigned i = 0; i != NumVars; ++i) {
    Vars.push_back(Record.readExpr());
  }
  D->setVars(Vars);
  SmallVector<OMPClause *, 8> Clauses;
  Clauses.reserve(NumClauses);
  OMPClauseReader ClauseReader(Record);
  for (unsigned I = 0; I != NumClauses; ++I)
    Clauses.push_back(ClauseReader.readClause());
  D->setClauses(Clauses);
}

void ASTDeclReader::VisitOMPRequiresDecl(OMPRequiresDecl * D) {
  VisitDecl(D);
  unsigned NumClauses = D->clauselist_size();
  SmallVector<OMPClause *, 8> Clauses;
  Clauses.reserve(NumClauses);
  OMPClauseReader ClauseReader(Record);
  for (unsigned I = 0; I != NumClauses; ++I)
    Clauses.push_back(ClauseReader.readClause());
  D->setClauses(Clauses);
}

void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
  VisitValueDecl(D);
  D->setLocation(ReadSourceLocation());
  Expr *In = Record.readExpr();
  Expr *Out = Record.readExpr();
  D->setCombinerData(In, Out);
  Expr *Combiner = Record.readExpr();
  D->setCombiner(Combiner);
  Expr *Orig = Record.readExpr();
  Expr *Priv = Record.readExpr();
  D->setInitializerData(Orig, Priv);
  Expr *Init = Record.readExpr();
  auto IK = static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt());
  D->setInitializer(Init, IK);
  D->PrevDeclInScope = ReadDeclID();
}

void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
  VisitValueDecl(D);
  D->setLocation(ReadSourceLocation());
  Expr *MapperVarRefE = Record.readExpr();
  D->setMapperVarRef(MapperVarRefE);
  D->VarName = Record.readDeclarationName();
  D->PrevDeclInScope = ReadDeclID();
  unsigned NumClauses = D->clauselist_size();
  SmallVector<OMPClause *, 8> Clauses;
  Clauses.reserve(NumClauses);
  OMPClauseReader ClauseReader(Record);
  for (unsigned I = 0; I != NumClauses; ++I)
    Clauses.push_back(ClauseReader.readClause());
  D->setClauses(Clauses);
}

void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) {
  VisitVarDecl(D);
}

//===----------------------------------------------------------------------===//
// Attribute Reading
//===----------------------------------------------------------------------===//

namespace {
class AttrReader {
  ModuleFile *F;
  ASTReader *Reader;
  const ASTReader::RecordData &Record;
  unsigned &Idx;

public:
  AttrReader(ModuleFile &F, ASTReader &Reader,
             const ASTReader::RecordData &Record, unsigned &Idx)
      : F(&F), Reader(&Reader), Record(Record), Idx(Idx) {}

  const uint64_t &readInt() { return Record[Idx++]; }

  SourceRange readSourceRange() {
    return Reader->ReadSourceRange(*F, Record, Idx);
  }

  Expr *readExpr() { return Reader->ReadExpr(*F); }

  Attr *readAttr() { return Reader->ReadAttr(*F, Record, Idx); }

  std::string readString() {
    return Reader->ReadString(Record, Idx);
  }

  TypeSourceInfo *getTypeSourceInfo() {
    return Reader->GetTypeSourceInfo(*F, Record, Idx);
  }

  IdentifierInfo *getIdentifierInfo() {
    return Reader->GetIdentifierInfo(*F, Record, Idx);
  }

  VersionTuple readVersionTuple() {
    return ASTReader::ReadVersionTuple(Record, Idx);
  }

  template <typename T> T *GetLocalDeclAs(uint32_t LocalID) {
    return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
  }
};
}

Attr *ASTReader::ReadAttr(ModuleFile &M, const RecordData &Rec,
                          unsigned &Idx) {
  AttrReader Record(M, *this, Rec, Idx);
  auto V = Record.readInt();
  if (!V)
    return nullptr;

  Attr *New = nullptr;
  // Kind is stored as a 1-based integer because 0 is used to indicate a null
  // Attr pointer.
  auto Kind = static_cast<attr::Kind>(V - 1);
  SourceRange Range = Record.readSourceRange();
  ASTContext &Context = getContext();

#include "clang/Serialization/AttrPCHRead.inc"

  assert(New && "Unable to decode attribute?");
  return New;
}

/// Reads attributes from the current stream position.
void ASTReader::ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs) {
  for (unsigned I = 0, E = Record.readInt(); I != E; ++I)
    Attrs.push_back(Record.readAttr());
}

//===----------------------------------------------------------------------===//
// ASTReader Implementation
//===----------------------------------------------------------------------===//

/// Note that we have loaded the declaration with the given
/// Index.
///
/// This routine notes that this declaration has already been loaded,
/// so that future GetDecl calls will return this declaration rather
/// than trying to load a new declaration.
inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) {
  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
  DeclsLoaded[Index] = D;
}

/// Determine whether the consumer will be interested in seeing
/// this declaration (via HandleTopLevelDecl).
///
/// This routine should return true for anything that might affect
/// code generation, e.g., inline function definitions, Objective-C
/// declarations with metadata, etc.
static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
  // An ObjCMethodDecl is never considered as "interesting" because its
  // implementation container always is.

  // An ImportDecl or VarDecl imported from a module map module will get
  // emitted when we import the relevant module.
  if (isPartOfPerModuleInitializer(D)) {
    auto *M = D->getImportedOwningModule();
    if (M && M->Kind == Module::ModuleMapModule &&
        Ctx.DeclMustBeEmitted(D))
      return false;
  }

  if (isa<FileScopeAsmDecl>(D) ||
      isa<ObjCProtocolDecl>(D) ||
      isa<ObjCImplDecl>(D) ||
      isa<ImportDecl>(D) ||
      isa<PragmaCommentDecl>(D) ||
      isa<PragmaDetectMismatchDecl>(D))
    return true;
  if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) ||
      isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D))
    return !D->getDeclContext()->isFunctionOrMethod();
  if (const auto *Var = dyn_cast<VarDecl>(D))
    return Var->isFileVarDecl() &&
           (Var->isThisDeclarationADefinition() == VarDecl::Definition ||
            OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var));
  if (const auto *Func = dyn_cast<FunctionDecl>(D))
    return Func->doesThisDeclarationHaveABody() || HasBody;

  if (auto *ES = D->getASTContext().getExternalSource())
    if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
      return true;

  return false;
}

/// Get the correct cursor and offset for loading a declaration.
ASTReader::RecordLocation
ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) {
  GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID);
  assert(I != GlobalDeclMap.end() && "Corrupted global declaration map");
  ModuleFile *M = I->second;
  const DeclOffset &DOffs =
      M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS];
  Loc = TranslateSourceLocation(*M, DOffs.getLocation());
  return RecordLocation(M, DOffs.BitOffset);
}

ASTReader::RecordLocation ASTReader::getLocalBitOffset(uint64_t GlobalOffset) {
  auto I = GlobalBitOffsetsMap.find(GlobalOffset);

  assert(I != GlobalBitOffsetsMap.end() && "Corrupted global bit offsets map");
  return RecordLocation(I->second, GlobalOffset - I->second->GlobalBitOffset);
}

uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
  return LocalOffset + M.GlobalBitOffset;
}

static bool isSameTemplateParameterList(const TemplateParameterList *X,
                                        const TemplateParameterList *Y);

/// Determine whether two template parameters are similar enough
/// that they may be used in declarations of the same template.
static bool isSameTemplateParameter(const NamedDecl *X,
                                    const NamedDecl *Y) {
  if (X->getKind() != Y->getKind())
    return false;

  if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
    const auto *TY = cast<TemplateTypeParmDecl>(Y);
    return TX->isParameterPack() == TY->isParameterPack();
  }

  if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
    const auto *TY = cast<NonTypeTemplateParmDecl>(Y);
    return TX->isParameterPack() == TY->isParameterPack() &&
           TX->getASTContext().hasSameType(TX->getType(), TY->getType());
  }

  const auto *TX = cast<TemplateTemplateParmDecl>(X);
  const auto *TY = cast<TemplateTemplateParmDecl>(Y);
  return TX->isParameterPack() == TY->isParameterPack() &&
         isSameTemplateParameterList(TX->getTemplateParameters(),
                                     TY->getTemplateParameters());
}

static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) {
  if (auto *NS = X->getAsNamespace())
    return NS;
  if (auto *NAS = X->getAsNamespaceAlias())
    return NAS->getNamespace();
  return nullptr;
}

static bool isSameQualifier(const NestedNameSpecifier *X,
                            const NestedNameSpecifier *Y) {
  if (auto *NSX = getNamespace(X)) {
    auto *NSY = getNamespace(Y);
    if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl())
      return false;
  } else if (X->getKind() != Y->getKind())
    return false;

  // FIXME: For namespaces and types, we're permitted to check that the entity
  // is named via the same tokens. We should probably do so.
  switch (X->getKind()) {
  case NestedNameSpecifier::Identifier:
    if (X->getAsIdentifier() != Y->getAsIdentifier())
      return false;
    break;
  case NestedNameSpecifier::Namespace:
  case NestedNameSpecifier::NamespaceAlias:
    // We've already checked that we named the same namespace.
    break;
  case NestedNameSpecifier::TypeSpec:
  case NestedNameSpecifier::TypeSpecWithTemplate:
    if (X->getAsType()->getCanonicalTypeInternal() !=
        Y->getAsType()->getCanonicalTypeInternal())
      return false;
    break;
  case NestedNameSpecifier::Global:
  case NestedNameSpecifier::Super:
    return true;
  }

  // Recurse into earlier portion of NNS, if any.
  auto *PX = X->getPrefix();
  auto *PY = Y->getPrefix();
  if (PX && PY)
    return isSameQualifier(PX, PY);
  return !PX && !PY;
}

/// Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
static bool isSameTemplateParameterList(const TemplateParameterList *X,
                                        const TemplateParameterList *Y) {
  if (X->size() != Y->size())
    return false;

  for (unsigned I = 0, N = X->size(); I != N; ++I)
    if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
      return false;

  return true;
}

/// Determine whether the attributes we can overload on are identical for A and
/// B. Will ignore any overloadable attrs represented in the type of A and B.
static bool hasSameOverloadableAttrs(const FunctionDecl *A,
                                     const FunctionDecl *B) {
  // Note that pass_object_size attributes are represented in the function's
  // ExtParameterInfo, so we don't need to check them here.

  llvm::FoldingSetNodeID Cand1ID, Cand2ID;
  auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>();
  auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>();

  for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) {
    Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair);
    Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair);

    // Return false if the number of enable_if attributes is different.
    if (!Cand1A || !Cand2A)
      return false;

    Cand1ID.clear();
    Cand2ID.clear();

    (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true);
    (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true);

    // Return false if any of the enable_if expressions of A and B are
    // different.
    if (Cand1ID != Cand2ID)
      return false;
  }
  return true;
}

/// Determine whether the two declarations refer to the same entity.
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
  assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");

  if (X == Y)
    return true;

  // Must be in the same context.
  //
  // Note that we can't use DeclContext::Equals here, because the DeclContexts
  // could be two different declarations of the same function. (We will fix the
  // semantic DC to refer to the primary definition after merging.)
  if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()),
                          cast<Decl>(Y->getDeclContext()->getRedeclContext())))
    return false;

  // Two typedefs refer to the same entity if they have the same underlying
  // type.
  if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X))
    if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y))
      return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(),
                                            TypedefY->getUnderlyingType());

  // Must have the same kind.
  if (X->getKind() != Y->getKind())
    return false;

  // Objective-C classes and protocols with the same name always match.
  if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X))
    return true;

  if (isa<ClassTemplateSpecializationDecl>(X)) {
    // No need to handle these here: we merge them when adding them to the
    // template.
    return false;
  }

  // Compatible tags match.
  if (const auto *TagX = dyn_cast<TagDecl>(X)) {
    const auto *TagY = cast<TagDecl>(Y);
    return (TagX->getTagKind() == TagY->getTagKind()) ||
      ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class ||
        TagX->getTagKind() == TTK_Interface) &&
       (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class ||
        TagY->getTagKind() == TTK_Interface));
  }

  // Functions with the same type and linkage match.
  // FIXME: This needs to cope with merging of prototyped/non-prototyped
  // functions, etc.
  if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) {
    const auto *FuncY = cast<FunctionDecl>(Y);
    if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) {
      const auto *CtorY = cast<CXXConstructorDecl>(Y);
      if (CtorX->getInheritedConstructor() &&
          !isSameEntity(CtorX->getInheritedConstructor().getConstructor(),
                        CtorY->getInheritedConstructor().getConstructor()))
        return false;
    }

    if (FuncX->isMultiVersion() != FuncY->isMultiVersion())
      return false;

    // Multiversioned functions with different feature strings are represented
    // as separate declarations.
    if (FuncX->isMultiVersion()) {
      const auto *TAX = FuncX->getAttr<TargetAttr>();
      const auto *TAY = FuncY->getAttr<TargetAttr>();
      assert(TAX && TAY && "Multiversion Function without target attribute");

      if (TAX->getFeaturesStr() != TAY->getFeaturesStr())
        return false;
    }

    ASTContext &C = FuncX->getASTContext();
    auto GetTypeAsWritten = [](const FunctionDecl *FD) {
      // Map to the first declaration that we've already merged into this one.
      // The TSI of redeclarations might not match (due to calling conventions
      // being inherited onto the type but not the TSI), but the TSI type of
      // the first declaration of the function should match across modules.
      FD = FD->getCanonicalDecl();
      return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType()
                                     : FD->getType();
    };
    QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY);
    if (!C.hasSameType(XT, YT)) {
      // We can get functions with different types on the redecl chain in C++17
      // if they have differing exception specifications and at least one of
      // the excpetion specs is unresolved.
      auto *XFPT = XT->getAs<FunctionProtoType>();
      auto *YFPT = YT->getAs<FunctionProtoType>();
      if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT &&
          (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) ||
           isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) &&
          C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT))
        return true;
      return false;
    }
    return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
           hasSameOverloadableAttrs(FuncX, FuncY);
  }

  // Variables with the same type and linkage match.
  if (const auto *VarX = dyn_cast<VarDecl>(X)) {
    const auto *VarY = cast<VarDecl>(Y);
    if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) {
      ASTContext &C = VarX->getASTContext();
      if (C.hasSameType(VarX->getType(), VarY->getType()))
        return true;

      // We can get decls with different types on the redecl chain. Eg.
      // template <typename T> struct S { static T Var[]; }; // #1
      // template <typename T> T S<T>::Var[sizeof(T)]; // #2
      // Only? happens when completing an incomplete array type. In this case
      // when comparing #1 and #2 we should go through their element type.
      const ArrayType *VarXTy = C.getAsArrayType(VarX->getType());
      const ArrayType *VarYTy = C.getAsArrayType(VarY->getType());
      if (!VarXTy || !VarYTy)
        return false;
      if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType())
        return C.hasSameType(VarXTy->getElementType(), VarYTy->getElementType());
    }
    return false;
  }

  // Namespaces with the same name and inlinedness match.
  if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) {
    const auto *NamespaceY = cast<NamespaceDecl>(Y);
    return NamespaceX->isInline() == NamespaceY->isInline();
  }

  // Identical template names and kinds match if their template parameter lists
  // and patterns match.
  if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) {
    const auto *TemplateY = cast<TemplateDecl>(Y);
    return isSameEntity(TemplateX->getTemplatedDecl(),
                        TemplateY->getTemplatedDecl()) &&
           isSameTemplateParameterList(TemplateX->getTemplateParameters(),
                                       TemplateY->getTemplateParameters());
  }

  // Fields with the same name and the same type match.
  if (const auto *FDX = dyn_cast<FieldDecl>(X)) {
    const auto *FDY = cast<FieldDecl>(Y);
    // FIXME: Also check the bitwidth is odr-equivalent, if any.
    return X->getASTContext().hasSameType(FDX->getType(), FDY->getType());
  }

  // Indirect fields with the same target field match.
  if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) {
    const auto *IFDY = cast<IndirectFieldDecl>(Y);
    return IFDX->getAnonField()->getCanonicalDecl() ==
           IFDY->getAnonField()->getCanonicalDecl();
  }

  // Enumerators with the same name match.
  if (isa<EnumConstantDecl>(X))
    // FIXME: Also check the value is odr-equivalent.
    return true;

  // Using shadow declarations with the same target match.
  if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) {
    const auto *USY = cast<UsingShadowDecl>(Y);
    return USX->getTargetDecl() == USY->getTargetDecl();
  }

  // Using declarations with the same qualifier match. (We already know that
  // the name matches.)
  if (const auto *UX = dyn_cast<UsingDecl>(X)) {
    const auto *UY = cast<UsingDecl>(Y);
    return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
           UX->hasTypename() == UY->hasTypename() &&
           UX->isAccessDeclaration() == UY->isAccessDeclaration();
  }
  if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) {
    const auto *UY = cast<UnresolvedUsingValueDecl>(Y);
    return isSameQualifier(UX->getQualifier(), UY->getQualifier()) &&
           UX->isAccessDeclaration() == UY->isAccessDeclaration();
  }
  if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X))
    return isSameQualifier(
        UX->getQualifier(),
        cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier());

  // Namespace alias definitions with the same target match.
  if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) {
    const auto *NAY = cast<NamespaceAliasDecl>(Y);
    return NAX->getNamespace()->Equals(NAY->getNamespace());
  }

  return false;
}

/// Find the context in which we should search for previous declarations when
/// looking for declarations to merge.
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
                                                        DeclContext *DC) {
  if (auto *ND = dyn_cast<NamespaceDecl>(DC))
    return ND->getOriginalNamespace();

  if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
    // Try to dig out the definition.
    auto *DD = RD->DefinitionData;
    if (!DD)
      DD = RD->getCanonicalDecl()->DefinitionData;

    // If there's no definition yet, then DC's definition is added by an update
    // record, but we've not yet loaded that update record. In this case, we
    // commit to DC being the canonical definition now, and will fix this when
    // we load the update record.
    if (!DD) {
      DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
      RD->setCompleteDefinition(true);
      RD->DefinitionData = DD;
      RD->getCanonicalDecl()->DefinitionData = DD;

      // Track that we did this horrible thing so that we can fix it later.
      Reader.PendingFakeDefinitionData.insert(
          std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake));
    }

    return DD->Definition;
  }

  if (auto *ED = dyn_cast<EnumDecl>(DC))
    return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition()
                                                      : nullptr;

  // We can see the TU here only if we have no Sema object. In that case,
  // there's no TU scope to look in, so using the DC alone is sufficient.
  if (auto *TU = dyn_cast<TranslationUnitDecl>(DC))
    return TU;

  return nullptr;
}

ASTDeclReader::FindExistingResult::~FindExistingResult() {
  // Record that we had a typedef name for linkage whether or not we merge
  // with that declaration.
  if (TypedefNameForLinkage) {
    DeclContext *DC = New->getDeclContext()->getRedeclContext();
    Reader.ImportedTypedefNamesForLinkage.insert(
        std::make_pair(std::make_pair(DC, TypedefNameForLinkage), New));
    return;
  }

  if (!AddResult || Existing)
    return;

  DeclarationName Name = New->getDeclName();
  DeclContext *DC = New->getDeclContext()->getRedeclContext();
  if (needsAnonymousDeclarationNumber(New)) {
    setAnonymousDeclForMerging(Reader, New->getLexicalDeclContext(),
                               AnonymousDeclNumber, New);
  } else if (DC->isTranslationUnit() &&
             !Reader.getContext().getLangOpts().CPlusPlus) {
    if (Reader.getIdResolver().tryAddTopLevelDecl(New, Name))
      Reader.PendingFakeLookupResults[Name.getAsIdentifierInfo()]
            .push_back(New);
  } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
    // Add the declaration to its redeclaration context so later merging
    // lookups will find it.
    MergeDC->makeDeclVisibleInContextImpl(New, /*Internal*/true);
  }
}

/// Find the declaration that should be merged into, given the declaration found
/// by name lookup. If we're merging an anonymous declaration within a typedef,
/// we need a matching typedef, and we merge with the type inside it.
static NamedDecl *getDeclForMerging(NamedDecl *Found,
                                    bool IsTypedefNameForLinkage) {
  if (!IsTypedefNameForLinkage)
    return Found;

  // If we found a typedef declaration that gives a name to some other
  // declaration, then we want that inner declaration. Declarations from
  // AST files are handled via ImportedTypedefNamesForLinkage.
  if (Found->isFromASTFile())
    return nullptr;

  if (auto *TND = dyn_cast<TypedefNameDecl>(Found))
    return TND->getAnonDeclWithTypedefName(/*AnyRedecl*/true);

  return nullptr;
}

/// Find the declaration to use to populate the anonymous declaration table
/// for the given lexical DeclContext. We only care about finding local
/// definitions of the context; we'll merge imported ones as we go.
DeclContext *
ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) {
  // For classes, we track the definition as we merge.
  if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) {
    auto *DD = RD->getCanonicalDecl()->DefinitionData;
    return DD ? DD->Definition : nullptr;
  }

  // For anything else, walk its merged redeclarations looking for a definition.
  // Note that we can't just call getDefinition here because the redeclaration
  // chain isn't wired up.
  for (auto *D : merged_redecls(cast<Decl>(LexicalDC))) {
    if (auto *FD = dyn_cast<FunctionDecl>(D))
      if (FD->isThisDeclarationADefinition())
        return FD;
    if (auto *MD = dyn_cast<ObjCMethodDecl>(D))
      if (MD->isThisDeclarationADefinition())
        return MD;
  }

  // No merged definition yet.
  return nullptr;
}

NamedDecl *ASTDeclReader::getAnonymousDeclForMerging(ASTReader &Reader,
                                                     DeclContext *DC,
                                                     unsigned Index) {
  // If the lexical context has been merged, look into the now-canonical
  // definition.
  auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl();

  // If we've seen this before, return the canonical declaration.
  auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC];
  if (Index < Previous.size() && Previous[Index])
    return Previous[Index];

  // If this is the first time, but we have parsed a declaration of the context,
  // build the anonymous declaration list from the parsed declaration.
  auto *PrimaryDC = getPrimaryDCForAnonymousDecl(DC);
  if (PrimaryDC && !cast<Decl>(PrimaryDC)->isFromASTFile()) {
    numberAnonymousDeclsWithin(PrimaryDC, [&](NamedDecl *ND, unsigned Number) {
      if (Previous.size() == Number)
        Previous.push_back(cast<NamedDecl>(ND->getCanonicalDecl()));
      else
        Previous[Number] = cast<NamedDecl>(ND->getCanonicalDecl());
    });
  }

  return Index < Previous.size() ? Previous[Index] : nullptr;
}

void ASTDeclReader::setAnonymousDeclForMerging(ASTReader &Reader,
                                               DeclContext *DC, unsigned Index,
                                               NamedDecl *D) {
  auto *CanonDC = cast<Decl>(DC)->getCanonicalDecl();

  auto &Previous = Reader.AnonymousDeclarationsForMerging[CanonDC];
  if (Index >= Previous.size())
    Previous.resize(Index + 1);
  if (!Previous[Index])
    Previous[Index] = D;
}

ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) {
  DeclarationName Name = TypedefNameForLinkage ? TypedefNameForLinkage
                                               : D->getDeclName();

  if (!Name && !needsAnonymousDeclarationNumber(D)) {
    // Don't bother trying to find unnamed declarations that are in
    // unmergeable contexts.
    FindExistingResult Result(Reader, D, /*Existing=*/nullptr,
                              AnonymousDeclNumber, TypedefNameForLinkage);
    Result.suppress();
    return Result;
  }

  DeclContext *DC = D->getDeclContext()->getRedeclContext();
  if (TypedefNameForLinkage) {
    auto It = Reader.ImportedTypedefNamesForLinkage.find(
        std::make_pair(DC, TypedefNameForLinkage));
    if (It != Reader.ImportedTypedefNamesForLinkage.end())
      if (isSameEntity(It->second, D))
        return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber,
                                  TypedefNameForLinkage);
    // Go on to check in other places in case an existing typedef name
    // was not imported.
  }

  if (needsAnonymousDeclarationNumber(D)) {
    // This is an anonymous declaration that we may need to merge. Look it up
    // in its context by number.
    if (auto *Existing = getAnonymousDeclForMerging(
            Reader, D->getLexicalDeclContext(), AnonymousDeclNumber))
      if (isSameEntity(Existing, D))
        return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
                                  TypedefNameForLinkage);
  } else if (DC->isTranslationUnit() &&
             !Reader.getContext().getLangOpts().CPlusPlus) {
    IdentifierResolver &IdResolver = Reader.getIdResolver();

    // Temporarily consider the identifier to be up-to-date. We don't want to
    // cause additional lookups here.
    class UpToDateIdentifierRAII {
      IdentifierInfo *II;
      bool WasOutToDate = false;

    public:
      explicit UpToDateIdentifierRAII(IdentifierInfo *II) : II(II) {
        if (II) {
          WasOutToDate = II->isOutOfDate();
          if (WasOutToDate)
            II->setOutOfDate(false);
        }
      }

      ~UpToDateIdentifierRAII() {
        if (WasOutToDate)
          II->setOutOfDate(true);
      }
    } UpToDate(Name.getAsIdentifierInfo());

    for (IdentifierResolver::iterator I = IdResolver.begin(Name),
                                   IEnd = IdResolver.end();
         I != IEnd; ++I) {
      if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
        if (isSameEntity(Existing, D))
          return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
                                    TypedefNameForLinkage);
    }
  } else if (DeclContext *MergeDC = getPrimaryContextForMerging(Reader, DC)) {
    DeclContext::lookup_result R = MergeDC->noload_lookup(Name);
    for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
      if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage))
        if (isSameEntity(Existing, D))
          return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber,
                                    TypedefNameForLinkage);
    }
  } else {
    // Not in a mergeable context.
    return FindExistingResult(Reader);
  }

  // If this declaration is from a merged context, make a note that we need to
  // check that the canonical definition of that context contains the decl.
  //
  // FIXME: We should do something similar if we merge two definitions of the
  // same template specialization into the same CXXRecordDecl.
  auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext());
  if (MergedDCIt != Reader.MergedDeclContexts.end() &&
      MergedDCIt->second == D->getDeclContext())
    Reader.PendingOdrMergeChecks.push_back(D);

  return FindExistingResult(Reader, D, /*Existing=*/nullptr,
                            AnonymousDeclNumber, TypedefNameForLinkage);
}

template<typename DeclT>
Decl *ASTDeclReader::getMostRecentDeclImpl(Redeclarable<DeclT> *D) {
  return D->RedeclLink.getLatestNotUpdated();
}

Decl *ASTDeclReader::getMostRecentDeclImpl(...) {
  llvm_unreachable("getMostRecentDecl on non-redeclarable declaration");
}

Decl *ASTDeclReader::getMostRecentDecl(Decl *D) {
  assert(D);

  switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
#define DECL(TYPE, BASE)                               \
  case Decl::TYPE:                                     \
    return getMostRecentDeclImpl(cast<TYPE##Decl>(D));
#include "clang/AST/DeclNodes.inc"
  }
  llvm_unreachable("unknown decl kind");
}

Decl *ASTReader::getMostRecentExistingDecl(Decl *D) {
  return ASTDeclReader::getMostRecentDecl(D->getCanonicalDecl());
}

template<typename DeclT>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
                                           Redeclarable<DeclT> *D,
                                           Decl *Previous, Decl *Canon) {
  D->RedeclLink.setPrevious(cast<DeclT>(Previous));
  D->First = cast<DeclT>(Previous)->First;
}

namespace clang {

template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
                                           Redeclarable<VarDecl> *D,
                                           Decl *Previous, Decl *Canon) {
  auto *VD = static_cast<VarDecl *>(D);
  auto *PrevVD = cast<VarDecl>(Previous);
  D->RedeclLink.setPrevious(PrevVD);
  D->First = PrevVD->First;

  // We should keep at most one definition on the chain.
  // FIXME: Cache the definition once we've found it. Building a chain with
  // N definitions currently takes O(N^2) time here.
  if (VD->isThisDeclarationADefinition() == VarDecl::Definition) {
    for (VarDecl *CurD = PrevVD; CurD; CurD = CurD->getPreviousDecl()) {
      if (CurD->isThisDeclarationADefinition() == VarDecl::Definition) {
        Reader.mergeDefinitionVisibility(CurD, VD);
        VD->demoteThisDefinitionToDeclaration();
        break;
      }
    }
  }
}

static bool isUndeducedReturnType(QualType T) {
  auto *DT = T->getContainedDeducedType();
  return DT && !DT->isDeduced();
}

template<>
void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
                                           Redeclarable<FunctionDecl> *D,
                                           Decl *Previous, Decl *Canon) {
  auto *FD = static_cast<FunctionDecl *>(D);
  auto *PrevFD = cast<FunctionDecl>(Previous);

  FD->RedeclLink.setPrevious(PrevFD);
  FD->First = PrevFD->First;

  // If the previous declaration is an inline function declaration, then this
  // declaration is too.
  if (PrevFD->isInlined() != FD->isInlined()) {
    // FIXME: [dcl.fct.spec]p4:
    //   If a function with external linkage is declared inline in one
    //   translation unit, it shall be declared inline in all translation
    //   units in which it appears.
    //
    // Be careful of this case:
    //
    // module A:
    //   template<typename T> struct X { void f(); };
    //   template<typename T> inline void X<T>::f() {}
    //
    // module B instantiates the declaration of X<int>::f
    // module C instantiates the definition of X<int>::f
    //
    // If module B and C are merged, we do not have a violation of this rule.
    FD->setImplicitlyInline(true);
  }

  auto *FPT = FD->getType()->getAs<FunctionProtoType>();
  auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
  if (FPT && PrevFPT) {
    // If we need to propagate an exception specification along the redecl
    // chain, make a note of that so that we can do so later.
    bool IsUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
    bool WasUnresolved =
        isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
    if (IsUnresolved != WasUnresolved)
      Reader.PendingExceptionSpecUpdates.insert(
          {Canon, IsUnresolved ? PrevFD : FD});

    // If we need to propagate a deduced return type along the redecl chain,
    // make a note of that so that we can do it later.
    bool IsUndeduced = isUndeducedReturnType(FPT->getReturnType());
    bool WasUndeduced = isUndeducedReturnType(PrevFPT->getReturnType());
    if (IsUndeduced != WasUndeduced)
      Reader.PendingDeducedTypeUpdates.insert(
          {cast<FunctionDecl>(Canon),
           (IsUndeduced ? PrevFPT : FPT)->getReturnType()});
  }
}

} // namespace clang

void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) {
  llvm_unreachable("attachPreviousDecl on non-redeclarable declaration");
}

/// Inherit the default template argument from \p From to \p To. Returns
/// \c false if there is no default template for \p From.
template <typename ParmDecl>
static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From,
                                           Decl *ToD) {
  auto *To = cast<ParmDecl>(ToD);
  if (!From->hasDefaultArgument())
    return false;
  To->setInheritedDefaultArgument(Context, From);
  return true;
}

static void inheritDefaultTemplateArguments(ASTContext &Context,
                                            TemplateDecl *From,
                                            TemplateDecl *To) {
  auto *FromTP = From->getTemplateParameters();
  auto *ToTP = To->getTemplateParameters();
  assert(FromTP->size() == ToTP->size() && "merged mismatched templates?");

  for (unsigned I = 0, N = FromTP->size(); I != N; ++I) {
    NamedDecl *FromParam = FromTP->getParam(I);
    NamedDecl *ToParam = ToTP->getParam(I);

    if (auto *FTTP = dyn_cast<TemplateTypeParmDecl>(FromParam))
      inheritDefaultTemplateArgument(Context, FTTP, ToParam);
    else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam))
      inheritDefaultTemplateArgument(Context, FNTTP, ToParam);
    else
      inheritDefaultTemplateArgument(
              Context, cast<TemplateTemplateParmDecl>(FromParam), ToParam);
  }
}

void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
                                       Decl *Previous, Decl *Canon) {
  assert(D && Previous);

  switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
#define DECL(TYPE, BASE)                                                  \
  case Decl::TYPE:                                                        \
    attachPreviousDeclImpl(Reader, cast<TYPE##Decl>(D), Previous, Canon); \
    break;
#include "clang/AST/DeclNodes.inc"
  }

  // If the declaration was visible in one module, a redeclaration of it in
  // another module remains visible even if it wouldn't be visible by itself.
  //
  // FIXME: In this case, the declaration should only be visible if a module
  //        that makes it visible has been imported.
  D->IdentifierNamespace |=
      Previous->IdentifierNamespace &
      (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);

  // If the declaration declares a template, it may inherit default arguments
  // from the previous declaration.
  if (auto *TD = dyn_cast<TemplateDecl>(D))
    inheritDefaultTemplateArguments(Reader.getContext(),
                                    cast<TemplateDecl>(Previous), TD);
}

template<typename DeclT>
void ASTDeclReader::attachLatestDeclImpl(Redeclarable<DeclT> *D, Decl *Latest) {
  D->RedeclLink.setLatest(cast<DeclT>(Latest));
}

void ASTDeclReader::attachLatestDeclImpl(...) {
  llvm_unreachable("attachLatestDecl on non-redeclarable declaration");
}

void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
  assert(D && Latest);

  switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
#define DECL(TYPE, BASE)                                  \
  case Decl::TYPE:                                        \
    attachLatestDeclImpl(cast<TYPE##Decl>(D), Latest); \
    break;
#include "clang/AST/DeclNodes.inc"
  }
}

template<typename DeclT>
void ASTDeclReader::markIncompleteDeclChainImpl(Redeclarable<DeclT> *D) {
  D->RedeclLink.markIncomplete();
}

void ASTDeclReader::markIncompleteDeclChainImpl(...) {
  llvm_unreachable("markIncompleteDeclChain on non-redeclarable declaration");
}

void ASTReader::markIncompleteDeclChain(Decl *D) {
  switch (D->getKind()) {
#define ABSTRACT_DECL(TYPE)
#define DECL(TYPE, BASE)                                             \
  case Decl::TYPE:                                                   \
    ASTDeclReader::markIncompleteDeclChainImpl(cast<TYPE##Decl>(D)); \
    break;
#include "clang/AST/DeclNodes.inc"
  }
}

/// Read the declaration at the given offset from the AST file.
Decl *ASTReader::ReadDeclRecord(DeclID ID) {
  unsigned Index = ID - NUM_PREDEF_DECL_IDS;
  SourceLocation DeclLoc;
  RecordLocation Loc = DeclCursorForID(ID, DeclLoc);
  llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor;
  // Keep track of where we are in the stream, then jump back there
  // after reading this declaration.
  SavedStreamPosition SavedPosition(DeclsCursor);

  ReadingKindTracker ReadingKind(Read_Decl, *this);

  // Note that we are loading a declaration record.
  Deserializing ADecl(this);

  DeclsCursor.JumpToBit(Loc.Offset);
  ASTRecordReader Record(*this, *Loc.F);
  ASTDeclReader Reader(*this, Record, Loc, ID, DeclLoc);
  unsigned Code = DeclsCursor.ReadCode();

  ASTContext &Context = getContext();
  Decl *D = nullptr;
  switch ((DeclCode)Record.readRecord(DeclsCursor, Code)) {
  case DECL_CONTEXT_LEXICAL:
  case DECL_CONTEXT_VISIBLE:
    llvm_unreachable("Record cannot be de-serialized with ReadDeclRecord");
  case DECL_TYPEDEF:
    D = TypedefDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_TYPEALIAS:
    D = TypeAliasDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_ENUM:
    D = EnumDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_RECORD:
    D = RecordDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_ENUM_CONSTANT:
    D = EnumConstantDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_FUNCTION:
    D = FunctionDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_LINKAGE_SPEC:
    D = LinkageSpecDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_EXPORT:
    D = ExportDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_LABEL:
    D = LabelDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_NAMESPACE:
    D = NamespaceDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_NAMESPACE_ALIAS:
    D = NamespaceAliasDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_USING:
    D = UsingDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_USING_PACK:
    D = UsingPackDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_USING_SHADOW:
    D = UsingShadowDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CONSTRUCTOR_USING_SHADOW:
    D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_USING_DIRECTIVE:
    D = UsingDirectiveDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_UNRESOLVED_USING_VALUE:
    D = UnresolvedUsingValueDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_UNRESOLVED_USING_TYPENAME:
    D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CXX_RECORD:
    D = CXXRecordDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CXX_DEDUCTION_GUIDE:
    D = CXXDeductionGuideDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CXX_METHOD:
    D = CXXMethodDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CXX_CONSTRUCTOR:
    D = CXXConstructorDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_CXX_DESTRUCTOR:
    D = CXXDestructorDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CXX_CONVERSION:
    D = CXXConversionDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_ACCESS_SPEC:
    D = AccessSpecDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_FRIEND:
    D = FriendDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_FRIEND_TEMPLATE:
    D = FriendTemplateDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CLASS_TEMPLATE:
    D = ClassTemplateDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CLASS_TEMPLATE_SPECIALIZATION:
    D = ClassTemplateSpecializationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
    D = ClassTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_VAR_TEMPLATE:
    D = VarTemplateDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_VAR_TEMPLATE_SPECIALIZATION:
    D = VarTemplateSpecializationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
    D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
    D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_FUNCTION_TEMPLATE:
    D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_TEMPLATE_TYPE_PARM:
    D = TemplateTypeParmDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_NON_TYPE_TEMPLATE_PARM:
    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK:
    D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID,
                                                    Record.readInt());
    break;
  case DECL_TEMPLATE_TEMPLATE_PARM:
    D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK:
    D = TemplateTemplateParmDecl::CreateDeserialized(Context, ID,
                                                     Record.readInt());
    break;
  case DECL_TYPE_ALIAS_TEMPLATE:
    D = TypeAliasTemplateDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_STATIC_ASSERT:
    D = StaticAssertDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_METHOD:
    D = ObjCMethodDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_INTERFACE:
    D = ObjCInterfaceDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_IVAR:
    D = ObjCIvarDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_PROTOCOL:
    D = ObjCProtocolDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_AT_DEFS_FIELD:
    D = ObjCAtDefsFieldDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_CATEGORY:
    D = ObjCCategoryDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_CATEGORY_IMPL:
    D = ObjCCategoryImplDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_IMPLEMENTATION:
    D = ObjCImplementationDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_COMPATIBLE_ALIAS:
    D = ObjCCompatibleAliasDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_PROPERTY:
    D = ObjCPropertyDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_PROPERTY_IMPL:
    D = ObjCPropertyImplDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_FIELD:
    D = FieldDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_INDIRECTFIELD:
    D = IndirectFieldDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_VAR:
    D = VarDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_IMPLICIT_PARAM:
    D = ImplicitParamDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_PARM_VAR:
    D = ParmVarDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_DECOMPOSITION:
    D = DecompositionDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_BINDING:
    D = BindingDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_FILE_SCOPE_ASM:
    D = FileScopeAsmDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_BLOCK:
    D = BlockDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_MS_PROPERTY:
    D = MSPropertyDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_CAPTURED:
    D = CapturedDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_CXX_BASE_SPECIFIERS:
    Error("attempt to read a C++ base-specifier record as a declaration");
    return nullptr;
  case DECL_CXX_CTOR_INITIALIZERS:
    Error("attempt to read a C++ ctor initializer record as a declaration");
    return nullptr;
  case DECL_IMPORT:
    // Note: last entry of the ImportDecl record is the number of stored source
    // locations.
    D = ImportDecl::CreateDeserialized(Context, ID, Record.back());
    break;
  case DECL_OMP_THREADPRIVATE:
    D = OMPThreadPrivateDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_OMP_ALLOCATE: {
    unsigned NumVars = Record.readInt();
    unsigned NumClauses = Record.readInt();
    D = OMPAllocateDecl::CreateDeserialized(Context, ID, NumVars, NumClauses);
    break;
  }
  case DECL_OMP_REQUIRES:
    D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_OMP_DECLARE_REDUCTION:
    D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OMP_DECLARE_MAPPER:
    D = OMPDeclareMapperDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_OMP_CAPTUREDEXPR:
    D = OMPCapturedExprDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_PRAGMA_COMMENT:
    D = PragmaCommentDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_PRAGMA_DETECT_MISMATCH:
    D = PragmaDetectMismatchDecl::CreateDeserialized(Context, ID,
                                                     Record.readInt());
    break;
  case DECL_EMPTY:
    D = EmptyDecl::CreateDeserialized(Context, ID);
    break;
  case DECL_OBJC_TYPE_PARAM:
    D = ObjCTypeParamDecl::CreateDeserialized(Context, ID);
    break;
  }

  assert(D && "Unknown declaration reading AST file");
  LoadedDecl(Index, D);
  // Set the DeclContext before doing any deserialization, to make sure internal
  // calls to Decl::getASTContext() by Decl's methods will find the
  // TranslationUnitDecl without crashing.
  D->setDeclContext(Context.getTranslationUnitDecl());
  Reader.Visit(D);

  // If this declaration is also a declaration context, get the
  // offsets for its tables of lexical and visible declarations.
  if (auto *DC = dyn_cast<DeclContext>(D)) {
    std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
    if (Offsets.first &&
        ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC))
      return nullptr;
    if (Offsets.second &&
        ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, Offsets.second, ID))
      return nullptr;
  }
  assert(Record.getIdx() == Record.size());

  // Load any relevant update records.
  PendingUpdateRecords.push_back(
      PendingUpdateRecord(ID, D, /*JustLoaded=*/true));

  // Load the categories after recursive loading is finished.
  if (auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
    // If we already have a definition when deserializing the ObjCInterfaceDecl,
    // we put the Decl in PendingDefinitions so we can pull the categories here.
    if (Class->isThisDeclarationADefinition() ||
        PendingDefinitions.count(Class))
      loadObjCCategories(ID, Class);

  // If we have deserialized a declaration that has a definition the
  // AST consumer might need to know about, queue it.
  // We don't pass it to the consumer immediately because we may be in recursive
  // loading, and some declarations may still be initializing.
  PotentiallyInterestingDecls.push_back(
      InterestingDecl(D, Reader.hasPendingBody()));

  return D;
}

void ASTReader::PassInterestingDeclsToConsumer() {
  assert(Consumer);

  if (PassingDeclsToConsumer)
    return;

  // Guard variable to avoid recursively redoing the process of passing
  // decls to consumer.
  SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer,
                                                   true);

  // Ensure that we've loaded all potentially-interesting declarations
  // that need to be eagerly loaded.
  for (auto ID : EagerlyDeserializedDecls)
    GetDecl(ID);
  EagerlyDeserializedDecls.clear();

  while (!PotentiallyInterestingDecls.empty()) {
    InterestingDecl D = PotentiallyInterestingDecls.front();
    PotentiallyInterestingDecls.pop_front();
    if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody()))
      PassInterestingDeclToConsumer(D.getDecl());
  }
}

void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) {
  // The declaration may have been modified by files later in the chain.
  // If this is the case, read the record containing the updates from each file
  // and pass it to ASTDeclReader to make the modifications.
  serialization::GlobalDeclID ID = Record.ID;
  Decl *D = Record.D;
  ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
  DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID);

  SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs;

  if (UpdI != DeclUpdateOffsets.end()) {
    auto UpdateOffsets = std::move(UpdI->second);
    DeclUpdateOffsets.erase(UpdI);

    // Check if this decl was interesting to the consumer. If we just loaded
    // the declaration, then we know it was interesting and we skip the call
    // to isConsumerInterestedIn because it is unsafe to call in the
    // current ASTReader state.
    bool WasInteresting =
        Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false);
    for (auto &FileAndOffset : UpdateOffsets) {
      ModuleFile *F = FileAndOffset.first;
      uint64_t Offset = FileAndOffset.second;
      llvm::BitstreamCursor &Cursor = F->DeclsCursor;
      SavedStreamPosition SavedPosition(Cursor);
      Cursor.JumpToBit(Offset);
      unsigned Code = Cursor.ReadCode();
      ASTRecordReader Record(*this, *F);
      unsigned RecCode = Record.readRecord(Cursor, Code);
      (void)RecCode;
      assert(RecCode == DECL_UPDATES && "Expected DECL_UPDATES record!");

      ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID,
                           SourceLocation());
      Reader.UpdateDecl(D, PendingLazySpecializationIDs);

      // We might have made this declaration interesting. If so, remember that
      // we need to hand it off to the consumer.
      if (!WasInteresting &&
          isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) {
        PotentiallyInterestingDecls.push_back(
            InterestingDecl(D, Reader.hasPendingBody()));
        WasInteresting = true;
      }
    }
  }
  // Add the lazy specializations to the template.
  assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) ||
          isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) &&
         "Must not have pending specializations");
  if (auto *CTD = dyn_cast<ClassTemplateDecl>(D))
    ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs);
  else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
    ASTDeclReader::AddLazySpecializations(FTD, PendingLazySpecializationIDs);
  else if (auto *VTD = dyn_cast<VarTemplateDecl>(D))
    ASTDeclReader::AddLazySpecializations(VTD, PendingLazySpecializationIDs);
  PendingLazySpecializationIDs.clear();

  // Load the pending visible updates for this decl context, if it has any.
  auto I = PendingVisibleUpdates.find(ID);
  if (I != PendingVisibleUpdates.end()) {
    auto VisibleUpdates = std::move(I->second);
    PendingVisibleUpdates.erase(I);

    auto *DC = cast<DeclContext>(D)->getPrimaryContext();
    for (const auto &Update : VisibleUpdates)
      Lookups[DC].Table.add(
          Update.Mod, Update.Data,
          reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod));
    DC->setHasExternalVisibleStorage(true);
  }
}

void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) {
  // Attach FirstLocal to the end of the decl chain.
  Decl *CanonDecl = FirstLocal->getCanonicalDecl();
  if (FirstLocal != CanonDecl) {
    Decl *PrevMostRecent = ASTDeclReader::getMostRecentDecl(CanonDecl);
    ASTDeclReader::attachPreviousDecl(
        *this, FirstLocal, PrevMostRecent ? PrevMostRecent : CanonDecl,
        CanonDecl);
  }

  if (!LocalOffset) {
    ASTDeclReader::attachLatestDecl(CanonDecl, FirstLocal);
    return;
  }

  // Load the list of other redeclarations from this module file.
  ModuleFile *M = getOwningModuleFile(FirstLocal);
  assert(M && "imported decl from no module file");

  llvm::BitstreamCursor &Cursor = M->DeclsCursor;
  SavedStreamPosition SavedPosition(Cursor);
  Cursor.JumpToBit(LocalOffset);

  RecordData Record;
  unsigned Code = Cursor.ReadCode();
  unsigned RecCode = Cursor.readRecord(Code, Record);
  (void)RecCode;
  assert(RecCode == LOCAL_REDECLARATIONS && "expected LOCAL_REDECLARATIONS record!");

  // FIXME: We have several different dispatches on decl kind here; maybe
  // we should instead generate one loop per kind and dispatch up-front?
  Decl *MostRecent = FirstLocal;
  for (unsigned I = 0, N = Record.size(); I != N; ++I) {
    auto *D = GetLocalDecl(*M, Record[N - I - 1]);
    ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl);
    MostRecent = D;
  }
  ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent);
}

namespace {

  /// Given an ObjC interface, goes through the modules and links to the
  /// interface all the categories for it.
  class ObjCCategoriesVisitor {
    ASTReader &Reader;
    ObjCInterfaceDecl *Interface;
    llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized;
    ObjCCategoryDecl *Tail = nullptr;
    llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap;
    serialization::GlobalDeclID InterfaceID;
    unsigned PreviousGeneration;

    void add(ObjCCategoryDecl *Cat) {
      // Only process each category once.
      if (!Deserialized.erase(Cat))
        return;

      // Check for duplicate categories.
      if (Cat->getDeclName()) {
        ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()];
        if (Existing &&
            Reader.getOwningModuleFile(Existing)
                                          != Reader.getOwningModuleFile(Cat)) {
          // FIXME: We should not warn for duplicates in diamond:
          //
          //   MT     //
          //  /  \    //
          // ML  MR   //
          //  \  /    //
          //   MB     //
          //
          // If there are duplicates in ML/MR, there will be warning when
          // creating MB *and* when importing MB. We should not warn when
          // importing.
          Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def)
            << Interface->getDeclName() << Cat->getDeclName();
          Reader.Diag(Existing->getLocation(), diag::note_previous_definition);
        } else if (!Existing) {
          // Record this category.
          Existing = Cat;
        }
      }

      // Add this category to the end of the chain.
      if (Tail)
        ASTDeclReader::setNextObjCCategory(Tail, Cat);
      else
        Interface->setCategoryListRaw(Cat);
      Tail = Cat;
    }

  public:
    ObjCCategoriesVisitor(ASTReader &Reader,
                          ObjCInterfaceDecl *Interface,
                          llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized,
                          serialization::GlobalDeclID InterfaceID,
                          unsigned PreviousGeneration)
        : Reader(Reader), Interface(Interface), Deserialized(Deserialized),
          InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) {
      // Populate the name -> category map with the set of known categories.
      for (auto *Cat : Interface->known_categories()) {
        if (Cat->getDeclName())
          NameCategoryMap[Cat->getDeclName()] = Cat;

        // Keep track of the tail of the category list.
        Tail = Cat;
      }
    }

    bool operator()(ModuleFile &M) {
      // If we've loaded all of the category information we care about from
      // this module file, we're done.
      if (M.Generation <= PreviousGeneration)
        return true;

      // Map global ID of the definition down to the local ID used in this
      // module file. If there is no such mapping, we'll find nothing here
      // (or in any module it imports).
      DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID);
      if (!LocalID)
        return true;

      // Perform a binary search to find the local redeclarations for this
      // declaration (if any).
      const ObjCCategoriesInfo Compare = { LocalID, 0 };
      const ObjCCategoriesInfo *Result
        = std::lower_bound(M.ObjCCategoriesMap,
                           M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap,
                           Compare);
      if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap ||
          Result->DefinitionID != LocalID) {
        // We didn't find anything. If the class definition is in this module
        // file, then the module files it depends on cannot have any categories,
        // so suppress further lookup.
        return Reader.isDeclIDFromModule(InterfaceID, M);
      }

      // We found something. Dig out all of the categories.
      unsigned Offset = Result->Offset;
      unsigned N = M.ObjCCategories[Offset];
      M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again
      for (unsigned I = 0; I != N; ++I)
        add(cast_or_null<ObjCCategoryDecl>(
              Reader.GetLocalDecl(M, M.ObjCCategories[Offset++])));
      return true;
    }
  };

} // namespace

void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID,
                                   ObjCInterfaceDecl *D,
                                   unsigned PreviousGeneration) {
  ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID,
                                PreviousGeneration);
  ModuleMgr.visit(Visitor);
}

template<typename DeclT, typename Fn>
static void forAllLaterRedecls(DeclT *D, Fn F) {
  F(D);

  // Check whether we've already merged D into its redeclaration chain.
  // MostRecent may or may not be nullptr if D has not been merged. If
  // not, walk the merged redecl chain and see if it's there.
  auto *MostRecent = D->getMostRecentDecl();
  bool Found = false;
  for (auto *Redecl = MostRecent; Redecl && !Found;
       Redecl = Redecl->getPreviousDecl())
    Found = (Redecl == D);

  // If this declaration is merged, apply the functor to all later decls.
  if (Found) {
    for (auto *Redecl = MostRecent; Redecl != D;
         Redecl = Redecl->getPreviousDecl())
      F(Redecl);
  }
}

void ASTDeclReader::UpdateDecl(Decl *D,
   llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) {
  while (Record.getIdx() < Record.size()) {
    switch ((DeclUpdateKind)Record.readInt()) {
    case UPD_CXX_ADDED_IMPLICIT_MEMBER: {
      auto *RD = cast<CXXRecordDecl>(D);
      // FIXME: If we also have an update record for instantiating the
      // definition of D, we need that to happen before we get here.
      Decl *MD = Record.readDecl();
      assert(MD && "couldn't read decl from update record");
      // FIXME: We should call addHiddenDecl instead, to add the member
      // to its DeclContext.
      RD->addedMember(MD);
      break;
    }

    case UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION:
      // It will be added to the template's lazy specialization set.
      PendingLazySpecializationIDs.push_back(ReadDeclID());
      break;

    case UPD_CXX_ADDED_ANONYMOUS_NAMESPACE: {
      auto *Anon = ReadDeclAs<NamespaceDecl>();

      // Each module has its own anonymous namespace, which is disjoint from
      // any other module's anonymous namespaces, so don't attach the anonymous
      // namespace at all.
      if (!Record.isModule()) {
        if (auto *TU = dyn_cast<TranslationUnitDecl>(D))
          TU->setAnonymousNamespace(Anon);
        else
          cast<NamespaceDecl>(D)->setAnonymousNamespace(Anon);
      }
      break;
    }

    case UPD_CXX_ADDED_VAR_DEFINITION: {
      auto *VD = cast<VarDecl>(D);
      VD->NonParmVarDeclBits.IsInline = Record.readInt();
      VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt();
      uint64_t Val = Record.readInt();
      if (Val && !VD->getInit()) {
        VD->setInit(Record.readExpr());
        if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3
          EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
          Eval->CheckedICE = true;
          Eval->IsICE = Val == 3;
        }
      }
      break;
    }

    case UPD_CXX_POINT_OF_INSTANTIATION: {
      SourceLocation POI = Record.readSourceLocation();
      if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
        VTSD->setPointOfInstantiation(POI);
      } else if (auto *VD = dyn_cast<VarDecl>(D)) {
        VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
      } else {
        auto *FD = cast<FunctionDecl>(D);
        if (auto *FTSInfo = FD->TemplateOrSpecialization
                    .dyn_cast<FunctionTemplateSpecializationInfo *>())
          FTSInfo->setPointOfInstantiation(POI);
        else
          FD->TemplateOrSpecialization.get<MemberSpecializationInfo *>()
              ->setPointOfInstantiation(POI);
      }
      break;
    }

    case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: {
      auto *Param = cast<ParmVarDecl>(D);

      // We have to read the default argument regardless of whether we use it
      // so that hypothetical further update records aren't messed up.
      // TODO: Add a function to skip over the next expr record.
      auto *DefaultArg = Record.readExpr();

      // Only apply the update if the parameter still has an uninstantiated
      // default argument.
      if (Param->hasUninstantiatedDefaultArg())
        Param->setDefaultArg(DefaultArg);
      break;
    }

    case UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER: {
      auto *FD = cast<FieldDecl>(D);
      auto *DefaultInit = Record.readExpr();

      // Only apply the update if the field still has an uninstantiated
      // default member initializer.
      if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) {
        if (DefaultInit)
          FD->setInClassInitializer(DefaultInit);
        else
          // Instantiation failed. We can get here if we serialized an AST for
          // an invalid program.
          FD->removeInClassInitializer();
      }
      break;
    }

    case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
      auto *FD = cast<FunctionDecl>(D);
      if (Reader.PendingBodies[FD]) {
        // FIXME: Maybe check for ODR violations.
        // It's safe to stop now because this update record is always last.
        return;
      }

      if (Record.readInt()) {
        // Maintain AST consistency: any later redeclarations of this function
        // are inline if this one is. (We might have merged another declaration
        // into this one.)
        forAllLaterRedecls(FD, [](FunctionDecl *FD) {
          FD->setImplicitlyInline();
        });
      }
      FD->setInnerLocStart(ReadSourceLocation());
      ReadFunctionDefinition(FD);
      assert(Record.getIdx() == Record.size() && "lazy body must be last");
      break;
    }

    case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
      auto *RD = cast<CXXRecordDecl>(D);
      auto *OldDD = RD->getCanonicalDecl()->DefinitionData;
      bool HadRealDefinition =
          OldDD && (OldDD->Definition != RD ||
                    !Reader.PendingFakeDefinitionData.count(OldDD));
      RD->setParamDestroyedInCallee(Record.readInt());
      RD->setArgPassingRestrictions(
          (RecordDecl::ArgPassingKind)Record.readInt());
      ReadCXXRecordDefinition(RD, /*Update*/true);

      // Visible update is handled separately.
      uint64_t LexicalOffset = ReadLocalOffset();
      if (!HadRealDefinition && LexicalOffset) {
        Record.readLexicalDeclContextStorage(LexicalOffset, RD);
        Reader.PendingFakeDefinitionData.erase(OldDD);
      }

      auto TSK = (TemplateSpecializationKind)Record.readInt();
      SourceLocation POI = ReadSourceLocation();
      if (MemberSpecializationInfo *MSInfo =
              RD->getMemberSpecializationInfo()) {
        MSInfo->setTemplateSpecializationKind(TSK);
        MSInfo->setPointOfInstantiation(POI);
      } else {
        auto *Spec = cast<ClassTemplateSpecializationDecl>(RD);
        Spec->setTemplateSpecializationKind(TSK);
        Spec->setPointOfInstantiation(POI);

        if (Record.readInt()) {
          auto *PartialSpec =
              ReadDeclAs<ClassTemplatePartialSpecializationDecl>();
          SmallVector<TemplateArgument, 8> TemplArgs;
          Record.readTemplateArgumentList(TemplArgs);
          auto *TemplArgList = TemplateArgumentList::CreateCopy(
              Reader.getContext(), TemplArgs);

          // FIXME: If we already have a partial specialization set,
          // check that it matches.
          if (!Spec->getSpecializedTemplateOrPartial()
                   .is<ClassTemplatePartialSpecializationDecl *>())
            Spec->setInstantiationOf(PartialSpec, TemplArgList);
        }
      }

      RD->setTagKind((TagTypeKind)Record.readInt());
      RD->setLocation(ReadSourceLocation());
      RD->setLocStart(ReadSourceLocation());
      RD->setBraceRange(ReadSourceRange());

      if (Record.readInt()) {
        AttrVec Attrs;
        Record.readAttributes(Attrs);
        // If the declaration already has attributes, we assume that some other
        // AST file already loaded them.
        if (!D->hasAttrs())
          D->setAttrsImpl(Attrs, Reader.getContext());
      }
      break;
    }

    case UPD_CXX_RESOLVED_DTOR_DELETE: {
      // Set the 'operator delete' directly to avoid emitting another update
      // record.
      auto *Del = ReadDeclAs<FunctionDecl>();
      auto *First = cast<CXXDestructorDecl>(D->getCanonicalDecl());
      auto *ThisArg = Record.readExpr();
      // FIXME: Check consistency if we have an old and new operator delete.
      if (!First->OperatorDelete) {
        First->OperatorDelete = Del;
        First->OperatorDeleteThisArg = ThisArg;
      }
      break;
    }

    case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
      FunctionProtoType::ExceptionSpecInfo ESI;
      SmallVector<QualType, 8> ExceptionStorage;
      Record.readExceptionSpec(ExceptionStorage, ESI);

      // Update this declaration's exception specification, if needed.
      auto *FD = cast<FunctionDecl>(D);
      auto *FPT = FD->getType()->castAs<FunctionProtoType>();
      // FIXME: If the exception specification is already present, check that it
      // matches.
      if (isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) {
        FD->setType(Reader.getContext().getFunctionType(
            FPT->getReturnType(), FPT->getParamTypes(),
            FPT->getExtProtoInfo().withExceptionSpec(ESI)));

        // When we get to the end of deserializing, see if there are other decls
        // that we need to propagate this exception specification onto.
        Reader.PendingExceptionSpecUpdates.insert(
            std::make_pair(FD->getCanonicalDecl(), FD));
      }
      break;
    }

    case UPD_CXX_DEDUCED_RETURN_TYPE: {
      auto *FD = cast<FunctionDecl>(D);
      QualType DeducedResultType = Record.readType();
      Reader.PendingDeducedTypeUpdates.insert(
          {FD->getCanonicalDecl(), DeducedResultType});
      break;
    }

    case UPD_DECL_MARKED_USED:
      // Maintain AST consistency: any later redeclarations are used too.
      D->markUsed(Reader.getContext());
      break;

    case UPD_MANGLING_NUMBER:
      Reader.getContext().setManglingNumber(cast<NamedDecl>(D),
                                            Record.readInt());
      break;

    case UPD_STATIC_LOCAL_NUMBER:
      Reader.getContext().setStaticLocalNumber(cast<VarDecl>(D),
                                               Record.readInt());
      break;

    case UPD_DECL_MARKED_OPENMP_THREADPRIVATE:
      D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(),
                                                          ReadSourceRange()));
      break;

    case UPD_DECL_MARKED_OPENMP_ALLOCATE: {
      auto AllocatorKind =
          static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(Record.readInt());
      Expr *Allocator = Record.readExpr();
      SourceRange SR = ReadSourceRange();
      D->addAttr(OMPAllocateDeclAttr::CreateImplicit(
          Reader.getContext(), AllocatorKind, Allocator, SR));
      break;
    }

    case UPD_DECL_EXPORTED: {
      unsigned SubmoduleID = readSubmoduleID();
      auto *Exported = cast<NamedDecl>(D);
      Module *Owner = SubmoduleID ? Reader.getSubmodule(SubmoduleID) : nullptr;
      Reader.getContext().mergeDefinitionIntoModule(Exported, Owner);
      Reader.PendingMergedDefinitionsToDeduplicate.insert(Exported);
      break;
    }

    case UPD_DECL_MARKED_OPENMP_DECLARETARGET:
      D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit(
          Reader.getContext(),
          static_cast<OMPDeclareTargetDeclAttr::MapTypeTy>(Record.readInt()),
          ReadSourceRange()));
      break;

    case UPD_ADDED_ATTR_TO_RECORD:
      AttrVec Attrs;
      Record.readAttributes(Attrs);
      assert(Attrs.size() == 1);
      D->addAttr(Attrs[0]);
      break;
    }
  }
}
