//===- ASTReaderDecl.cpp - Decl Deserialization ---------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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/Sema/SemaDiagnostic.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 VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *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->setExplicitSpecified(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->setConstexpr(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]);
    FunctionTemplateSpecializationInfo *FTInfo
        = FunctionTemplateSpecializationInfo::Create(C, FD, Template, TSK,
                                                     TemplArgList,
                             HasTemplateArgumentsAsWritten ? &TemplArgsInfo
                                                           : nullptr,
                                                     POI);
    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->Function, 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>());
}

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();
  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.ARCPseudoStrong = 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();
  }
  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>();
}

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());

  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) {
  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.
  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) {
  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>();
}

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::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::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); }

  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 (isa<ImportDecl>(D) || isa<VarDecl>(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))
    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.

  // Return false if any of the enable_if expressions of A and B are different.
  llvm::FoldingSetNodeID Cand1ID, Cand2ID;
  auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>();
  auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>();
  auto AEnableIf = AEnableIfAttrs.begin();
  auto BEnableIf = BEnableIfAttrs.begin();
  for (; AEnableIf != AEnableIfAttrs.end() && BEnableIf != BEnableIfAttrs.end();
       ++BEnableIf, ++AEnableIf) {
    Cand1ID.clear();
    Cand2ID.clear();

    AEnableIf->getCond()->Profile(Cand1ID, A->getASTContext(), true);
    BEnableIf->getCond()->Profile(Cand2ID, B->getASTContext(), true);
    if (Cand1ID != Cand2ID)
      return false;
  }

  // Return false if the number of enable_if attributes was different.
  return AEnableIf == AEnableIfAttrs.end() && BEnableIf == BEnableIfAttrs.end();
}

/// 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, false);
    break;
  case DECL_CXX_INHERITED_CONSTRUCTOR:
    D = CXXConstructorDecl::CreateDeserialized(Context, ID, true);
    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_REQUIRES:
    D = OMPRequiresDecl::CreateDeserialized(Context, ID, Record.readInt());
    break;
  case DECL_OMP_DECLARE_REDUCTION:
    D = OMPDeclareReductionDecl::CreateDeserialized(Context, ID);
    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_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;
    }
  }
}
