//===--- PCHReaderDecl.cpp - Decl Deserialization ---------------*- C++ -*-===//
//
//                     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 PCHReader::ReadDeclRecord method, which is the
// entrypoint for loading a decl.
//
//===----------------------------------------------------------------------===//

#include "clang/Frontend/PCHReader.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
using namespace clang;


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

namespace clang {
  class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> {
    PCHReader &Reader;
    llvm::BitstreamCursor &Cursor;
    const pch::DeclID ThisDeclID;
    const PCHReader::RecordData &Record;
    unsigned &Idx;
    pch::TypeID TypeIDForTypeDecl;

    uint64_t GetCurrentCursorOffset();

  public:
    PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor,
                  pch::DeclID thisDeclID, const PCHReader::RecordData &Record,
                  unsigned &Idx)
      : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), Record(Record),
        Idx(Idx), TypeIDForTypeDecl(0) { }

    void Visit(Decl *D);

    void VisitDecl(Decl *D);
    void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
    void VisitNamedDecl(NamedDecl *ND);
    void VisitNamespaceDecl(NamespaceDecl *D);
    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
    void VisitTypeDecl(TypeDecl *TD);
    void VisitTypedefDecl(TypedefDecl *TD);
    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
    void VisitTagDecl(TagDecl *TD);
    void VisitEnumDecl(EnumDecl *ED);
    void VisitRecordDecl(RecordDecl *RD);
    void VisitCXXRecordDecl(CXXRecordDecl *D);
    void VisitClassTemplateSpecializationDecl(
                                            ClassTemplateSpecializationDecl *D);
    void VisitClassTemplatePartialSpecializationDecl(
                                     ClassTemplatePartialSpecializationDecl *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 VisitCXXMethodDecl(CXXMethodDecl *D);
    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
    void VisitCXXConversionDecl(CXXConversionDecl *D);
    void VisitFieldDecl(FieldDecl *FD);
    void VisitVarDecl(VarDecl *VD);
    void VisitImplicitParamDecl(ImplicitParamDecl *PD);
    void VisitParmVarDecl(ParmVarDecl *PD);
    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
    void VisitTemplateDecl(TemplateDecl *D);
    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
    void VisitClassTemplateDecl(ClassTemplateDecl *D);
    void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
    void VisitUsingDecl(UsingDecl *D);
    void VisitUsingShadowDecl(UsingShadowDecl *D);
    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
    void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
    void VisitAccessSpecDecl(AccessSpecDecl *D);
    void VisitFriendDecl(FriendDecl *D);
    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
    void VisitStaticAssertDecl(StaticAssertDecl *D);
    void VisitBlockDecl(BlockDecl *BD);

    std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);

    // FIXME: Reorder according to DeclNodes.td?
    void VisitObjCMethodDecl(ObjCMethodDecl *D);
    void VisitObjCContainerDecl(ObjCContainerDecl *D);
    void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
    void VisitObjCIvarDecl(ObjCIvarDecl *D);
    void VisitObjCProtocolDecl(ObjCProtocolDecl *D);
    void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D);
    void VisitObjCClassDecl(ObjCClassDecl *D);
    void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *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);
  };
}

uint64_t PCHDeclReader::GetCurrentCursorOffset() {
  uint64_t Off = 0;
  for (unsigned I = 0, N = Reader.Chain.size(); I != N; ++I) {
    PCHReader::PerFileData &F = *Reader.Chain[N - I - 1];
    if (&Cursor == &F.DeclsCursor) {
      Off += F.DeclsCursor.GetCurrentBitNo();
      break;
    }
    Off += F.SizeInBits;
  }
  return Off;
}

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

  if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
    // if we have a fully initialized TypeDecl, we can safely read its type now.
    TD->setTypeForDecl(Reader.GetType(TypeIDForTypeDecl).getTypePtr());
  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
    // FunctionDecl's body was written last after all other Stmts/Exprs.
    if (Record[Idx++])
      FD->setLazyBody(GetCurrentCursorOffset());
  }
}

void PCHDeclReader::VisitDecl(Decl *D) {
  D->setDeclContext(cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
  D->setLexicalDeclContext(
                     cast_or_null<DeclContext>(Reader.GetDecl(Record[Idx++])));
  D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++]));
  D->setInvalidDecl(Record[Idx++]);
  if (Record[Idx++])
    D->initAttrs(Reader.ReadAttributes(Cursor));
  D->setImplicit(Record[Idx++]);
  D->setUsed(Record[Idx++]);
  D->setAccess((AccessSpecifier)Record[Idx++]);
  D->setPCHLevel(Record[Idx++] + 1);
}

void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
  VisitDecl(TU);
  TU->setAnonymousNamespace(
                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
  VisitDecl(ND);
  ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
}

void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
  VisitNamedDecl(TD);
  // Delay type reading until after we have fully initialized the decl.
  TypeIDForTypeDecl = Record[Idx++];
}

void PCHDeclReader::VisitTypedefDecl(TypedefDecl *TD) {
  VisitTypeDecl(TD);
  TD->setTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
}

void PCHDeclReader::VisitTagDecl(TagDecl *TD) {
  VisitTypeDecl(TD);
  TD->IdentifierNamespace = Record[Idx++];
  VisitRedeclarable(TD);
  TD->setTagKind((TagDecl::TagKind)Record[Idx++]);
  TD->setDefinition(Record[Idx++]);
  TD->setEmbeddedInDeclarator(Record[Idx++]);
  TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  // FIXME: maybe read optional qualifier and its range.
  TD->setTypedefForAnonDecl(
                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) {
  VisitTagDecl(ED);
  ED->setIntegerType(Reader.GetType(Record[Idx++]));
  ED->setPromotionType(Reader.GetType(Record[Idx++]));
  ED->setNumPositiveBits(Record[Idx++]);
  ED->setNumNegativeBits(Record[Idx++]);
  ED->setInstantiationOfMemberEnum(
                         cast_or_null<EnumDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitRecordDecl(RecordDecl *RD) {
  VisitTagDecl(RD);
  RD->setHasFlexibleArrayMember(Record[Idx++]);
  RD->setAnonymousStructOrUnion(Record[Idx++]);
  RD->setHasObjectMember(Record[Idx++]);
}

void PCHDeclReader::VisitValueDecl(ValueDecl *VD) {
  VisitNamedDecl(VD);
  VD->setType(Reader.GetType(Record[Idx++]));
}

void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {
  VisitValueDecl(ECD);
  if (Record[Idx++])
    ECD->setInitExpr(Reader.ReadExpr(Cursor));
  ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));
}

void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
  VisitValueDecl(DD);
  TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
  if (TInfo)
    DD->setTypeSourceInfo(TInfo);
  // FIXME: read optional qualifier and its range.
}

void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
  VisitDeclaratorDecl(FD);

  FD->IdentifierNamespace = Record[Idx++];
  switch ((FunctionDecl::TemplatedKind)Record[Idx++]) {
  default: assert(false && "Unhandled TemplatedKind!");
    break;
  case FunctionDecl::TK_NonTemplate:
    break;
  case FunctionDecl::TK_FunctionTemplate:
    FD->setDescribedFunctionTemplate(
                     cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++])));
    break;
  case FunctionDecl::TK_MemberSpecialization: {
    FunctionDecl *InstFD = cast<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
    FD->setInstantiationOfMemberFunction(InstFD, TSK);
    FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
    break;
  }
  case FunctionDecl::TK_FunctionTemplateSpecialization: {
    FunctionTemplateDecl *Template
      = cast<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
    
    // Template arguments.
    llvm::SmallVector<TemplateArgument, 8> TemplArgs;
    Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
    
    // Template args as written.
    llvm::SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
    SourceLocation LAngleLoc, RAngleLoc;
    if (Record[Idx++]) {  // TemplateArgumentsAsWritten != 0
      unsigned NumTemplateArgLocs = Record[Idx++];
      TemplArgLocs.reserve(NumTemplateArgLocs);
      for (unsigned i=0; i != NumTemplateArgLocs; ++i)
        TemplArgLocs.push_back(
            Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
  
      LAngleLoc = Reader.ReadSourceLocation(Record, Idx);
      RAngleLoc = Reader.ReadSourceLocation(Record, Idx);
    }
    
    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);

    if (FD->isCanonicalDecl()) // if canonical add to template's set.
      FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(),
                                            TemplArgs.data(), TSK,
                                            TemplArgLocs.size(),
                                            TemplArgLocs.data(),
                                            LAngleLoc, RAngleLoc, POI);
    break;
  }
  case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
    // Templates.
    UnresolvedSet<8> TemplDecls;
    unsigned NumTemplates = Record[Idx++];
    while (NumTemplates--)
      TemplDecls.addDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
    
    // Templates args.
    TemplateArgumentListInfo TemplArgs;
    unsigned NumArgs = Record[Idx++];
    while (NumArgs--)
      TemplArgs.addArgument(Reader.ReadTemplateArgumentLoc(Cursor,Record, Idx));
    TemplArgs.setLAngleLoc(Reader.ReadSourceLocation(Record, Idx));
    TemplArgs.setRAngleLoc(Reader.ReadSourceLocation(Record, Idx));
    
    FD->setDependentTemplateSpecialization(*Reader.getContext(),
                                           TemplDecls, TemplArgs);
    break;
  }
  }

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

  VisitRedeclarable(FD);
  FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]);
  FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]);
  FD->setInlineSpecified(Record[Idx++]);
  FD->setVirtualAsWritten(Record[Idx++]);
  FD->setPure(Record[Idx++]);
  FD->setHasInheritedPrototype(Record[Idx++]);
  FD->setHasWrittenPrototype(Record[Idx++]);
  FD->setDeleted(Record[Idx++]);
  FD->setTrivial(Record[Idx++]);
  FD->setCopyAssignment(Record[Idx++]);
  FD->setHasImplicitReturnZero(Record[Idx++]);
  FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));

  // Read in the parameters.
  unsigned NumParams = Record[Idx++];
  llvm::SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
  FD->setParams(Params.data(), NumParams);
}

void PCHDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) {
  VisitNamedDecl(MD);
  if (Record[Idx++]) {
    // In practice, this won't be executed (since method definitions
    // don't occur in header files).
    MD->setBody(Reader.ReadStmt(Cursor));
    MD->setSelfDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
    MD->setCmdDecl(cast<ImplicitParamDecl>(Reader.GetDecl(Record[Idx++])));
  }
  MD->setInstanceMethod(Record[Idx++]);
  MD->setVariadic(Record[Idx++]);
  MD->setSynthesized(Record[Idx++]);
  MD->setDefined(Record[Idx++]);
  MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record[Idx++]);
  MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
  MD->setNumSelectorArgs(unsigned(Record[Idx++]));
  MD->setResultType(Reader.GetType(Record[Idx++]));
  MD->setResultTypeSourceInfo(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
  MD->setEndLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  unsigned NumParams = Record[Idx++];
  llvm::SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
  MD->setMethodParams(*Reader.getContext(), Params.data(), NumParams,
                      NumParams);
}

void PCHDeclReader::VisitObjCContainerDecl(ObjCContainerDecl *CD) {
  VisitNamedDecl(CD);
  SourceLocation A = SourceLocation::getFromRawEncoding(Record[Idx++]);
  SourceLocation B = SourceLocation::getFromRawEncoding(Record[Idx++]);
  CD->setAtEndRange(SourceRange(A, B));
}

void PCHDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
  VisitObjCContainerDecl(ID);
  ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
  ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
                       (Reader.GetDecl(Record[Idx++])));
  unsigned NumProtocols = Record[Idx++];
  llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
  Protocols.reserve(NumProtocols);
  for (unsigned I = 0; I != NumProtocols; ++I)
    Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtocols);
  for (unsigned I = 0; I != NumProtocols; ++I)
    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
  ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
                      *Reader.getContext());
  unsigned NumIvars = Record[Idx++];
  llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
  IVars.reserve(NumIvars);
  for (unsigned I = 0; I != NumIvars; ++I)
    IVars.push_back(cast<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
  ID->setCategoryList(
               cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
  ID->setForwardDecl(Record[Idx++]);
  ID->setImplicitInterfaceDecl(Record[Idx++]);
  ID->setClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  ID->setSuperClassLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  ID->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
}

void PCHDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) {
  VisitFieldDecl(IVD);
  IVD->setAccessControl((ObjCIvarDecl::AccessControl)Record[Idx++]);
  bool synth = Record[Idx++];
  IVD->setSynthesize(synth);
}

void PCHDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) {
  VisitObjCContainerDecl(PD);
  PD->setForwardDecl(Record[Idx++]);
  PD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
  unsigned NumProtoRefs = Record[Idx++];
  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
  ProtoRefs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                      *Reader.getContext());
}

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

void PCHDeclReader::VisitObjCClassDecl(ObjCClassDecl *CD) {
  VisitDecl(CD);
  unsigned NumClassRefs = Record[Idx++];
  llvm::SmallVector<ObjCInterfaceDecl *, 16> ClassRefs;
  ClassRefs.reserve(NumClassRefs);
  for (unsigned I = 0; I != NumClassRefs; ++I)
    ClassRefs.push_back(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
  llvm::SmallVector<SourceLocation, 16> SLocs;
  SLocs.reserve(NumClassRefs);
  for (unsigned I = 0; I != NumClassRefs; ++I)
    SLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
  CD->setClassList(*Reader.getContext(), ClassRefs.data(), SLocs.data(),
                   NumClassRefs);
}

void PCHDeclReader::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *FPD) {
  VisitDecl(FPD);
  unsigned NumProtoRefs = Record[Idx++];
  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
  ProtoRefs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                       *Reader.getContext());
}

void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
  VisitObjCContainerDecl(CD);
  CD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
  unsigned NumProtoRefs = Record[Idx++];
  llvm::SmallVector<ObjCProtocolDecl *, 16> ProtoRefs;
  ProtoRefs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
  ProtoLocs.reserve(NumProtoRefs);
  for (unsigned I = 0; I != NumProtoRefs; ++I)
    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
                      *Reader.getContext());
  CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
  CD->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  CD->setCategoryNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
}

void PCHDeclReader::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *CAD) {
  VisitNamedDecl(CAD);
  CAD->setClassInterface(cast<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
  VisitNamedDecl(D);
  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  D->setType(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
  // FIXME: stable encoding
  D->setPropertyAttributes(
                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
  D->setPropertyAttributesAsWritten(
                      (ObjCPropertyDecl::PropertyAttributeKind)Record[Idx++]);
  // FIXME: stable encoding
  D->setPropertyImplementation(
                            (ObjCPropertyDecl::PropertyControl)Record[Idx++]);
  D->setGetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
  D->setSetterName(Reader.ReadDeclarationName(Record, Idx).getObjCSelector());
  D->setGetterMethodDecl(
                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
  D->setSetterMethodDecl(
                 cast_or_null<ObjCMethodDecl>(Reader.GetDecl(Record[Idx++])));
  D->setPropertyIvarDecl(
                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitObjCImplDecl(ObjCImplDecl *D) {
  VisitObjCContainerDecl(D);
  D->setClassInterface(
              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
  VisitObjCImplDecl(D);
  D->setIdentifier(Reader.GetIdentifierInfo(Record, Idx));
}

void PCHDeclReader::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
  VisitObjCImplDecl(D);
  D->setSuperClass(
              cast_or_null<ObjCInterfaceDecl>(Reader.GetDecl(Record[Idx++])));
  // FIXME. Add reading of IvarInitializers and NumIvarInitializers.
}


void PCHDeclReader::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
  VisitDecl(D);
  D->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
  D->setPropertyDecl(
               cast_or_null<ObjCPropertyDecl>(Reader.GetDecl(Record[Idx++])));
  D->setPropertyIvarDecl(
                   cast_or_null<ObjCIvarDecl>(Reader.GetDecl(Record[Idx++])));
  // FIXME. read GetterCXXConstructor and SetterCXXAssignment
}

void PCHDeclReader::VisitFieldDecl(FieldDecl *FD) {
  VisitDeclaratorDecl(FD);
  FD->setMutable(Record[Idx++]);
  if (Record[Idx++])
    FD->setBitWidth(Reader.ReadExpr(Cursor));
  if (!FD->getDeclName()) {
    FieldDecl *Tmpl = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
    if (Tmpl)
      Reader.getContext()->setInstantiatedFromUnnamedFieldDecl(FD, Tmpl);
  }
}

void PCHDeclReader::VisitVarDecl(VarDecl *VD) {
  VisitDeclaratorDecl(VD);
  VD->setStorageClass((VarDecl::StorageClass)Record[Idx++]);
  VD->setStorageClassAsWritten((VarDecl::StorageClass)Record[Idx++]);
  VD->setThreadSpecified(Record[Idx++]);
  VD->setCXXDirectInitializer(Record[Idx++]);
  VD->setExceptionVariable(Record[Idx++]);
  VD->setNRVOVariable(Record[Idx++]);
  VisitRedeclarable(VD);
  if (Record[Idx++])
    VD->setInit(Reader.ReadExpr(Cursor));

  if (Record[Idx++]) { // HasMemberSpecializationInfo.
    VarDecl *Tmpl = cast<VarDecl>(Reader.GetDecl(Record[Idx++]));
    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
    Reader.getContext()->setInstantiatedFromStaticDataMember(VD, Tmpl, TSK,POI);
  }
}

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

void PCHDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
  VisitVarDecl(PD);
  PD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record[Idx++]);
  PD->setHasInheritedDefaultArg(Record[Idx++]);
  if (Record[Idx++]) // hasUninstantiatedDefaultArg.
    PD->setUninstantiatedDefaultArg(Reader.ReadExpr(Cursor));
}

void PCHDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
  VisitDecl(AD);
  AD->setAsmString(cast<StringLiteral>(Reader.ReadExpr(Cursor)));
}

void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
  VisitDecl(BD);
  BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadStmt(Cursor)));
  BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Cursor, Record, Idx));
  unsigned NumParams = Record[Idx++];
  llvm::SmallVector<ParmVarDecl *, 16> Params;
  Params.reserve(NumParams);
  for (unsigned I = 0; I != NumParams; ++I)
    Params.push_back(cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
  BD->setParams(Params.data(), NumParams);
}

void PCHDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
  VisitDecl(D);
  D->setLanguage((LinkageSpecDecl::LanguageIDs)Record[Idx++]);
  D->setHasBraces(Record[Idx++]);
}

void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
  VisitNamedDecl(D);
  D->setLBracLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setRBracLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setNextNamespace(
                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));

  bool IsOriginal = Record[Idx++];
  D->OrigOrAnonNamespace.setInt(IsOriginal);
  D->OrigOrAnonNamespace.setPointer(
                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
  VisitNamedDecl(D);

  D->setAliasLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
  D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
  D->setTargetNameLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setAliasedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitUsingDecl(UsingDecl *D) {
  VisitNamedDecl(D);
  D->setUsingLocation(Reader.ReadSourceLocation(Record, Idx));
  D->setNestedNameRange(Reader.ReadSourceRange(Record, Idx));
  D->setTargetNestedNameDecl(Reader.ReadNestedNameSpecifier(Record, Idx));

  // FIXME: It would probably be more efficient to read these into a vector
  // and then re-cosntruct the shadow decl set over that vector since it
  // would avoid existence checks.
  unsigned NumShadows = Record[Idx++];
  for(unsigned I = 0; I != NumShadows; ++I) {
    // Avoid invariant checking of UsingDecl::addShadowDecl, the decl may still
    // be initializing.
    D->Shadows.insert(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])));
  }
  D->setTypeName(Record[Idx++]);
  NamedDecl *Pattern = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
  if (Pattern)
    Reader.getContext()->setInstantiatedFromUsingDecl(D, Pattern);
}

void PCHDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
  VisitNamedDecl(D);
  D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
  D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++])));
  UsingShadowDecl *Pattern
      = cast_or_null<UsingShadowDecl>(Reader.GetDecl(Record[Idx++]));
  if (Pattern)
    Reader.getContext()->setInstantiatedFromUsingShadowDecl(D, Pattern);
}

void PCHDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
  VisitNamedDecl(D);
  D->setNamespaceKeyLocation(Reader.ReadSourceLocation(Record, Idx));
  D->setQualifierRange(Reader.ReadSourceRange(Record, Idx));
  D->setQualifier(Reader.ReadNestedNameSpecifier(Record, Idx));
  D->setIdentLocation(Reader.ReadSourceLocation(Record, Idx));
  D->setNominatedNamespace(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
  D->setCommonAncestor(cast_or_null<DeclContext>(
                                                Reader.GetDecl(Record[Idx++])));
}

void PCHDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
  VisitValueDecl(D);
  D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
  D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
}

void PCHDeclReader::VisitUnresolvedUsingTypenameDecl(
                                               UnresolvedUsingTypenameDecl *D) {
  VisitTypeDecl(D);
  D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
  D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setTypenameLoc(Reader.ReadSourceLocation(Record, Idx));
  D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
}

void PCHDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) {
  ASTContext &C = *Reader.getContext();

  // We need to allocate the DefinitionData struct ahead of VisitRecordDecl
  // so that the other CXXRecordDecls can get a pointer even when the owner
  // is still initializing.
  bool OwnsDefinitionData = false;
  enum DataOwnership { Data_NoDefData, Data_Owner, Data_NotOwner };
  switch ((DataOwnership)Record[Idx++]) {
  default:
    assert(0 && "Out of sync with PCHDeclWriter or messed up reading");
  case Data_NoDefData:
    break;
  case Data_Owner:
    OwnsDefinitionData = true;
    D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D);
    break;
  case Data_NotOwner:
    D->DefinitionData
        = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]))->DefinitionData;
    break;
  }

  VisitRecordDecl(D);

  if (OwnsDefinitionData) {
    assert(D->DefinitionData);
    struct CXXRecordDecl::DefinitionData &Data = *D->DefinitionData;

    Data.UserDeclaredConstructor = Record[Idx++];
    Data.UserDeclaredCopyConstructor = Record[Idx++];
    Data.UserDeclaredCopyAssignment = Record[Idx++];
    Data.UserDeclaredDestructor = Record[Idx++];
    Data.Aggregate = Record[Idx++];
    Data.PlainOldData = Record[Idx++];
    Data.Empty = Record[Idx++];
    Data.Polymorphic = Record[Idx++];
    Data.Abstract = Record[Idx++];
    Data.HasTrivialConstructor = Record[Idx++];
    Data.HasTrivialCopyConstructor = Record[Idx++];
    Data.HasTrivialCopyAssignment = Record[Idx++];
    Data.HasTrivialDestructor = Record[Idx++];
    Data.ComputedVisibleConversions = Record[Idx++];
    Data.DeclaredDefaultConstructor = Record[Idx++];
    Data.DeclaredCopyConstructor = Record[Idx++];
    Data.DeclaredCopyAssignment = Record[Idx++];
    Data.DeclaredDestructor = Record[Idx++];

    // setBases() is unsuitable since it may try to iterate the bases of an
    // uninitialized base.
    Data.NumBases = Record[Idx++];
    Data.Bases = new(C) CXXBaseSpecifier [Data.NumBases];
    for (unsigned i = 0; i != Data.NumBases; ++i)
      Data.Bases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);

    // FIXME: Make VBases lazily computed when needed to avoid storing them.
    Data.NumVBases = Record[Idx++];
    Data.VBases = new(C) CXXBaseSpecifier [Data.NumVBases];
    for (unsigned i = 0; i != Data.NumVBases; ++i)
      Data.VBases[i] = Reader.ReadCXXBaseSpecifier(Cursor, Record, Idx);

    Reader.ReadUnresolvedSet(Data.Conversions, Record, Idx);
    Reader.ReadUnresolvedSet(Data.VisibleConversions, Record, Idx);
    assert(Data.Definition && "Data.Definition should be already set!");
    Data.FirstFriend
        = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
  }

  enum CXXRecKind {
    CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization
  };
  switch ((CXXRecKind)Record[Idx++]) {
  default:
    assert(false && "Out of sync with PCHDeclWriter::VisitCXXRecordDecl?");
  case CXXRecNotTemplate:
    break;
  case CXXRecTemplate:
    D->setDescribedClassTemplate(
                        cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])));
    break;
  case CXXRecMemberSpecialization: {
    CXXRecordDecl *RD = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
    TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++];
    SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
    D->setInstantiationOfMemberClass(RD, TSK);
    D->getMemberSpecializationInfo()->setPointOfInstantiation(POI);
    break;
  }
  }
}

void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
  VisitFunctionDecl(D);
  unsigned NumOverridenMethods = Record[Idx++];
  while (NumOverridenMethods--) {
    CXXMethodDecl *MD = cast<CXXMethodDecl>(Reader.GetDecl(Record[Idx++]));
    // Avoid invariant checking of CXXMethodDecl::addOverriddenMethod,
    // MD may be initializing.
    Reader.getContext()->addOverriddenMethod(D, MD);
  }
}

void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
  VisitCXXMethodDecl(D);
  
  D->IsExplicitSpecified = Record[Idx++];
  D->ImplicitlyDefined = Record[Idx++];
  
  unsigned NumInitializers = Record[Idx++];
  D->NumBaseOrMemberInitializers = NumInitializers;
  if (NumInitializers) {
    ASTContext &C = *Reader.getContext();

    D->BaseOrMemberInitializers
        = new (C) CXXBaseOrMemberInitializer*[NumInitializers];
    for (unsigned i=0; i != NumInitializers; ++i) {
      TypeSourceInfo *BaseClassInfo = 0;
      bool IsBaseVirtual = false;
      FieldDecl *Member = 0;
  
      bool IsBaseInitializer = Record[Idx++];
      if (IsBaseInitializer) {
        BaseClassInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
        IsBaseVirtual = Record[Idx++];
      } else {
        Member = cast<FieldDecl>(Reader.GetDecl(Record[Idx++]));
      }
      SourceLocation MemberLoc = Reader.ReadSourceLocation(Record, Idx);
      Expr *Init = Reader.ReadExpr(Cursor);
      FieldDecl *AnonUnionMember
          = cast_or_null<FieldDecl>(Reader.GetDecl(Record[Idx++]));
      SourceLocation LParenLoc = Reader.ReadSourceLocation(Record, Idx);
      SourceLocation RParenLoc = Reader.ReadSourceLocation(Record, Idx);
      bool IsWritten = Record[Idx++];
      unsigned SourceOrderOrNumArrayIndices;
      llvm::SmallVector<VarDecl *, 8> Indices;
      if (IsWritten) {
        SourceOrderOrNumArrayIndices = Record[Idx++];
      } else {
        SourceOrderOrNumArrayIndices = Record[Idx++];
        Indices.reserve(SourceOrderOrNumArrayIndices);
        for (unsigned i=0; i != SourceOrderOrNumArrayIndices; ++i)
          Indices.push_back(cast<VarDecl>(Reader.GetDecl(Record[Idx++])));
      }
      
      CXXBaseOrMemberInitializer *BOMInit;
      if (IsBaseInitializer) {
        BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo,
                                                     IsBaseVirtual, LParenLoc,
                                                     Init, RParenLoc);
      } else if (IsWritten) {
        BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc,
                                                     LParenLoc, Init, RParenLoc);
      } else {
        BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc,
                                                     LParenLoc, Init, RParenLoc,
                                                     Indices.data(),
                                                     Indices.size());
      }

      BOMInit->setAnonUnionMember(AnonUnionMember);
      D->BaseOrMemberInitializers[i] = BOMInit;
    }
  }
}

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

  D->ImplicitlyDefined = Record[Idx++];
  D->OperatorDelete = cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]));
}

void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
  VisitCXXMethodDecl(D);
  D->IsExplicitSpecified = Record[Idx++];
}

void PCHDeclReader::VisitAccessSpecDecl(AccessSpecDecl *D) {
  VisitDecl(D);
  D->setColonLoc(Reader.ReadSourceLocation(Record, Idx));
}

void PCHDeclReader::VisitFriendDecl(FriendDecl *D) {
  VisitDecl(D);
  if (Record[Idx++])
    D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
  else
    D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
  D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++]));
  D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
}

void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
  VisitDecl(D);
  unsigned NumParams = Record[Idx++];
  D->NumParams = NumParams;
  D->Params = new TemplateParameterList*[NumParams];
  for (unsigned i = 0; i != NumParams; ++i)
    D->Params[i] = Reader.ReadTemplateParameterList(Record, Idx);
  if (Record[Idx++]) // HasFriendDecl
    D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
  else
    D->Friend = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
  D->FriendLoc = Reader.ReadSourceLocation(Record, Idx);
}

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

  NamedDecl *TemplatedDecl
    = cast_or_null<NamedDecl>(Reader.GetDecl(Record[Idx++]));
  TemplateParameterList* TemplateParams
      = Reader.ReadTemplateParameterList(Record, Idx); 
  D->init(TemplatedDecl, TemplateParams);
}

void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
  VisitTemplateDecl(D);

  D->IdentifierNamespace = Record[Idx++];
  RedeclarableTemplateDecl *PrevDecl =
      cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
  assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) &&
         "PrevDecl kind mismatch");
  if (PrevDecl)
    D->CommonOrPrev = PrevDecl;
  if (PrevDecl == 0) {
    if (RedeclarableTemplateDecl *RTD
          = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
      assert(RTD->getKind() == D->getKind() &&
             "InstantiatedFromMemberTemplate kind mismatch");
      D->setInstantiatedFromMemberTemplateImpl(RTD);
      if (Record[Idx++])
        D->setMemberSpecialization();
    }

    RedeclarableTemplateDecl *LatestDecl = 
        cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
  
    // This decl is a first one and the latest declaration that it points to is
    // in the same PCH. However, if this actually needs to point to a
    // redeclaration in another chained PCH, we need to update it by checking
    // the FirstLatestDeclIDs map which tracks this kind of decls.
    assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?");
    PCHReader::FirstLatestDeclIDMap::iterator I
        = Reader.FirstLatestDeclIDs.find(ThisDeclID);
    if (I != Reader.FirstLatestDeclIDs.end()) {
      Decl *NewLatest = Reader.GetDecl(I->second);
      assert((LatestDecl->getLocation().isInvalid() ||
              NewLatest->getLocation().isInvalid()  ||
              Reader.SourceMgr.isBeforeInTranslationUnit(
                                                   LatestDecl->getLocation(),
                                                   NewLatest->getLocation())) &&
             "The new latest is supposed to come after the previous latest");
      LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest);
    }

    assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch");
    D->getCommonPtr()->Latest = LatestDecl;
  }
}

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

  if (D->getPreviousDeclaration() == 0) {
    // This ClassTemplateDecl owns a CommonPtr; read it.

    // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
    unsigned size = Record[Idx++];
    while (size--)
      cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++]));

    size = Record[Idx++];
    while (size--)
      cast<ClassTemplatePartialSpecializationDecl>(
                                                 Reader.GetDecl(Record[Idx++]));

    // InjectedClassNameType is computed.
  }
}

void PCHDeclReader::VisitClassTemplateSpecializationDecl(
                                           ClassTemplateSpecializationDecl *D) {
  VisitCXXRecordDecl(D);

  if (Decl *InstD = Reader.GetDecl(Record[Idx++])) {
    if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(InstD)) {
      D->setInstantiationOf(CTD);
    } else {
      llvm::SmallVector<TemplateArgument, 8> TemplArgs;
      Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
      D->setInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(InstD),
                            TemplArgs.data(), TemplArgs.size());
    }
  }

  // Explicit info.
  if (TypeSourceInfo *TyInfo = Reader.GetTypeSourceInfo(Cursor, Record, Idx)) {
    D->setTypeAsWritten(TyInfo);
    D->setExternLoc(Reader.ReadSourceLocation(Record, Idx));
    D->setTemplateKeywordLoc(Reader.ReadSourceLocation(Record, Idx));
  }

  llvm::SmallVector<TemplateArgument, 8> TemplArgs;
  Reader.ReadTemplateArgumentList(TemplArgs, Cursor, Record, Idx);
  D->initTemplateArgs(TemplArgs.data(), TemplArgs.size());
  SourceLocation POI = Reader.ReadSourceLocation(Record, Idx);
  if (POI.isValid())
    D->setPointOfInstantiation(POI);
  D->setSpecializationKind((TemplateSpecializationKind)Record[Idx++]);

  if (D->isCanonicalDecl()) { // It's kept in the folding set.
    ClassTemplateDecl *CanonPattern
                       = cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
    if (ClassTemplatePartialSpecializationDecl *Partial
            = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
      CanonPattern->getPartialSpecializations().InsertNode(Partial);
    } else {
      CanonPattern->getSpecializations().InsertNode(D);
    }
  }
}

void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
                                    ClassTemplatePartialSpecializationDecl *D) {
  VisitClassTemplateSpecializationDecl(D);

  D->initTemplateParameters(Reader.ReadTemplateParameterList(Record, Idx));
  
  TemplateArgumentListInfo ArgInfos;
  unsigned NumArgs = Record[Idx++];
  while (NumArgs--)
    ArgInfos.addArgument(Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx));
  D->initTemplateArgsAsWritten(ArgInfos);
  
  D->setSequenceNumber(Record[Idx++]);

  // These are read/set from/to the first declaration.
  if (D->getPreviousDeclaration() == 0) {
    D->setInstantiatedFromMember(
        cast_or_null<ClassTemplatePartialSpecializationDecl>(
                                                Reader.GetDecl(Record[Idx++])));
    if (Record[Idx++])
      D->setMemberSpecialization();
  }
}

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

  if (D->getPreviousDeclaration() == 0) {
    // This FunctionTemplateDecl owns a CommonPtr; read it.

    // Read the function specialization declarations.
    // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled
    // through the specialized FunctionDecl's setFunctionTemplateSpecialization.
    unsigned NumSpecs = Record[Idx++];
    while (NumSpecs--)
      Reader.GetDecl(Record[Idx++]);
  }
}

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

  D->setDeclaredWithTypename(Record[Idx++]);
  D->setParameterPack(Record[Idx++]);

  bool Inherited = Record[Idx++];
  TypeSourceInfo *DefArg = Reader.GetTypeSourceInfo(Cursor, Record, Idx);
  D->setDefaultArgument(DefArg, Inherited);
}

void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
  VisitVarDecl(D);
  // TemplateParmPosition.
  D->setDepth(Record[Idx++]);
  D->setPosition(Record[Idx++]);
  // Rest of NonTypeTemplateParmDecl.
  if (Record[Idx++]) {
    Expr *DefArg = Reader.ReadExpr(Cursor);
    bool Inherited = Record[Idx++];
    D->setDefaultArgument(DefArg, Inherited);
 }
}

void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
  VisitTemplateDecl(D);
  // TemplateParmPosition.
  D->setDepth(Record[Idx++]);
  D->setPosition(Record[Idx++]);
  // Rest of TemplateTemplateParmDecl.
  TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(Cursor, Record, Idx);
  bool IsInherited = Record[Idx++];
  D->setDefaultArgument(Arg, IsInherited);
}

void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
  VisitDecl(D);
  D->AssertExpr = Reader.ReadExpr(Cursor);
  D->Message = cast<StringLiteral>(Reader.ReadExpr(Cursor));
}

std::pair<uint64_t, uint64_t>
PCHDeclReader::VisitDeclContext(DeclContext *DC) {
  uint64_t LexicalOffset = Record[Idx++];
  uint64_t VisibleOffset = Record[Idx++];
  return std::make_pair(LexicalOffset, VisibleOffset);
}

template <typename T>
void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
  enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
  RedeclKind Kind = (RedeclKind)Record[Idx++];
  switch (Kind) {
  default:
    assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed up"
                " reading");
  case NoRedeclaration:
    break;
  case PointsToPrevious:
    D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink(
                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
    break;
  case PointsToLatest:
    D->RedeclLink = typename Redeclarable<T>::LatestDeclLink(
                                cast_or_null<T>(Reader.GetDecl(Record[Idx++])));
    break;
  }

  assert(!(Kind == PointsToPrevious &&
           Reader.FirstLatestDeclIDs.find(ThisDeclID) !=
               Reader.FirstLatestDeclIDs.end()) &&
         "This decl is not first, it should not be in the map");
  if (Kind == PointsToPrevious)
    return;

  // This decl is a first one and the latest declaration that it points to is in
  // the same PCH. However, if this actually needs to point to a redeclaration
  // in another chained PCH, we need to update it by checking the
  // FirstLatestDeclIDs map which tracks this kind of decls.
  assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) &&
         "Invalid ThisDeclID ?");
  PCHReader::FirstLatestDeclIDMap::iterator I
      = Reader.FirstLatestDeclIDs.find(ThisDeclID);
  if (I != Reader.FirstLatestDeclIDs.end()) {
    Decl *NewLatest = Reader.GetDecl(I->second);
    assert((D->getMostRecentDeclaration()->getLocation().isInvalid() ||
            NewLatest->getLocation().isInvalid() ||
            Reader.SourceMgr.isBeforeInTranslationUnit(
                                   D->getMostRecentDeclaration()->getLocation(),
                                   NewLatest->getLocation())) &&
           "The new latest is supposed to come after the previous latest");
    D->RedeclLink
        = typename Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest));
  }
}

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

/// \brief Reads attributes from the current stream position.
Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
  unsigned Code = DeclsCursor.ReadCode();
  assert(Code == llvm::bitc::UNABBREV_RECORD &&
         "Expected unabbreviated record"); (void)Code;

  RecordData Record;
  unsigned Idx = 0;
  unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
  assert(RecCode == pch::DECL_ATTR && "Expected attribute record");
  (void)RecCode;

#define SIMPLE_ATTR(Name)                       \
 case attr::Name:                               \
   New = ::new (*Context) Name##Attr();         \
   break

#define STRING_ATTR(Name)                                       \
 case attr::Name:                                               \
   New = ::new (*Context) Name##Attr(*Context, ReadString(Record, Idx));  \
   break

#define UNSIGNED_ATTR(Name)                             \
 case attr::Name:                                       \
   New = ::new (*Context) Name##Attr(Record[Idx++]);    \
   break

  Attr *Attrs = 0;
  while (Idx < Record.size()) {
    Attr *New = 0;
    attr::Kind Kind = (attr::Kind)Record[Idx++];
    bool IsInherited = Record[Idx++];

    switch (Kind) {
    default:
      assert(0 && "Unknown attribute!");
      break;
    STRING_ATTR(Alias);
    SIMPLE_ATTR(AlignMac68k);
    UNSIGNED_ATTR(Aligned);
    SIMPLE_ATTR(AlwaysInline);
    SIMPLE_ATTR(AnalyzerNoReturn);
    STRING_ATTR(Annotate);
    STRING_ATTR(AsmLabel);
    SIMPLE_ATTR(BaseCheck);

    case attr::Blocks:
      New = ::new (*Context) BlocksAttr(
                                  (BlocksAttr::BlocksAttrTypes)Record[Idx++]);
      break;

    SIMPLE_ATTR(CDecl);

    case attr::Cleanup:
      New = ::new (*Context) CleanupAttr(
                                  cast<FunctionDecl>(GetDecl(Record[Idx++])));
      break;

    SIMPLE_ATTR(Const);
    UNSIGNED_ATTR(Constructor);
    SIMPLE_ATTR(DLLExport);
    SIMPLE_ATTR(DLLImport);
    SIMPLE_ATTR(Deprecated);
    UNSIGNED_ATTR(Destructor);
    SIMPLE_ATTR(FastCall);
    SIMPLE_ATTR(Final);

    case attr::Format: {
      std::string Type = ReadString(Record, Idx);
      unsigned FormatIdx = Record[Idx++];
      unsigned FirstArg = Record[Idx++];
      New = ::new (*Context) FormatAttr(*Context, Type, FormatIdx, FirstArg);
      break;
    }

    case attr::FormatArg: {
      unsigned FormatIdx = Record[Idx++];
      New = ::new (*Context) FormatArgAttr(FormatIdx);
      break;
    }

    case attr::Sentinel: {
      int sentinel = Record[Idx++];
      int nullPos = Record[Idx++];
      New = ::new (*Context) SentinelAttr(sentinel, nullPos);
      break;
    }

    SIMPLE_ATTR(GNUInline);
    SIMPLE_ATTR(Hiding);

    case attr::IBAction:
      New = ::new (*Context) IBActionAttr();
      break;

    case attr::IBOutlet:
      New = ::new (*Context) IBOutletAttr();
      break;

    case attr::IBOutletCollection: {
      ObjCInterfaceDecl *D =
        cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
      New = ::new (*Context) IBOutletCollectionAttr(D);
      break;
    }

    SIMPLE_ATTR(Malloc);
    SIMPLE_ATTR(NoDebug);
    SIMPLE_ATTR(NoInline);
    SIMPLE_ATTR(NoReturn);
    SIMPLE_ATTR(NoThrow);

    case attr::NonNull: {
      unsigned Size = Record[Idx++];
      llvm::SmallVector<unsigned, 16> ArgNums;
      ArgNums.insert(ArgNums.end(), &Record[Idx], &Record[Idx] + Size);
      Idx += Size;
      New = ::new (*Context) NonNullAttr(*Context, ArgNums.data(), Size);
      break;
    }

    case attr::ReqdWorkGroupSize: {
      unsigned X = Record[Idx++];
      unsigned Y = Record[Idx++];
      unsigned Z = Record[Idx++];
      New = ::new (*Context) ReqdWorkGroupSizeAttr(X, Y, Z);
      break;
    }

    SIMPLE_ATTR(ObjCException);
    SIMPLE_ATTR(ObjCNSObject);
    SIMPLE_ATTR(CFReturnsNotRetained);
    SIMPLE_ATTR(CFReturnsRetained);
    SIMPLE_ATTR(NSReturnsNotRetained);
    SIMPLE_ATTR(NSReturnsRetained);
    SIMPLE_ATTR(Overloadable);
    SIMPLE_ATTR(Override);
    SIMPLE_ATTR(Packed);
    UNSIGNED_ATTR(MaxFieldAlignment);
    SIMPLE_ATTR(Pure);
    UNSIGNED_ATTR(Regparm);
    STRING_ATTR(Section);
    SIMPLE_ATTR(StdCall);
    SIMPLE_ATTR(ThisCall);
    SIMPLE_ATTR(TransparentUnion);
    SIMPLE_ATTR(Unavailable);
    SIMPLE_ATTR(Unused);
    SIMPLE_ATTR(Used);

    case attr::Visibility:
      New = ::new (*Context) VisibilityAttr(
                              (VisibilityAttr::VisibilityTypes)Record[Idx++],
                              (bool)Record[Idx++]);
      break;

    SIMPLE_ATTR(WarnUnusedResult);
    SIMPLE_ATTR(Weak);
    SIMPLE_ATTR(WeakRef);
    SIMPLE_ATTR(WeakImport);
    }

    assert(New && "Unable to decode attribute?");
    New->setInherited(IsInherited);
    New->setNext(Attrs);
    Attrs = New;
  }
#undef UNSIGNED_ATTR
#undef STRING_ATTR
#undef SIMPLE_ATTR

  // The list of attributes was built backwards. Reverse the list
  // before returning it.
  Attr *PrevAttr = 0, *NextAttr = 0;
  while (Attrs) {
    NextAttr = Attrs->getNext();
    Attrs->setNext(PrevAttr);
    PrevAttr = Attrs;
    Attrs = NextAttr;
  }

  return PrevAttr;
}

//===----------------------------------------------------------------------===//
// PCHReader Implementation
//===----------------------------------------------------------------------===//

/// \brief 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 PCHReader::LoadedDecl(unsigned Index, Decl *D) {
  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
  DeclsLoaded[Index] = D;
}


/// \brief 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(Decl *D) {
  if (isa<FileScopeAsmDecl>(D))
    return true;
  if (VarDecl *Var = dyn_cast<VarDecl>(D))
    return Var->isFileVarDecl() &&
           Var->isThisDeclarationADefinition() == VarDecl::Definition;
  if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
    return Func->isThisDeclarationADefinition();
  return isa<ObjCProtocolDecl>(D);
}

/// \brief Get the correct cursor and offset for loading a type.
PCHReader::RecordLocation PCHReader::DeclCursorForIndex(unsigned Index) {
  PerFileData *F = 0;
  for (unsigned I = 0, N = Chain.size(); I != N; ++I) {
    F = Chain[N - I - 1];
    if (Index < F->LocalNumDecls)
      break;
    Index -= F->LocalNumDecls;
  }
  assert(F && F->LocalNumDecls > Index && "Broken chain");
  return RecordLocation(&F->DeclsCursor, F->DeclOffsets[Index]);
}

/// \brief Read the declaration at the given offset from the PCH file.
Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) {
  RecordLocation Loc = DeclCursorForIndex(Index);
  llvm::BitstreamCursor &DeclsCursor = *Loc.first;
  // 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.second);
  RecordData Record;
  unsigned Code = DeclsCursor.ReadCode();
  unsigned Idx = 0;
  PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx);

  Decl *D = 0;
  switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) {
  case pch::DECL_ATTR:
  case pch::DECL_CONTEXT_LEXICAL:
  case pch::DECL_CONTEXT_VISIBLE:
    assert(false && "Record cannot be de-serialized with ReadDeclRecord");
    break;
  case pch::DECL_TRANSLATION_UNIT:
    assert(Index == 0 && "Translation unit must be at index 0");
    D = Context->getTranslationUnitDecl();
    break;
  case pch::DECL_TYPEDEF:
    D = TypedefDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;
  case pch::DECL_ENUM:
    D = EnumDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_RECORD:
    D = RecordDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_ENUM_CONSTANT:
    D = EnumConstantDecl::Create(*Context, 0, SourceLocation(), 0, QualType(),
                                 0, llvm::APSInt());
    break;
  case pch::DECL_FUNCTION:
    D = FunctionDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
                             QualType(), 0);
    break;
  case pch::DECL_LINKAGE_SPEC:
    D = LinkageSpecDecl::Create(*Context, 0, SourceLocation(),
                                (LinkageSpecDecl::LanguageIDs)0,
                                false);
    break;
  case pch::DECL_NAMESPACE:
    D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
    break;
  case pch::DECL_NAMESPACE_ALIAS:
    D = NamespaceAliasDecl::Create(*Context, 0, SourceLocation(),
                                   SourceLocation(), 0, SourceRange(), 0,
                                   SourceLocation(), 0);
    break;
  case pch::DECL_USING:
    D = UsingDecl::Create(*Context, 0, SourceLocation(), SourceRange(),
                          SourceLocation(), 0, DeclarationName(), false);
    break;
  case pch::DECL_USING_SHADOW:
    D = UsingShadowDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;
  case pch::DECL_USING_DIRECTIVE:
    D = UsingDirectiveDecl::Create(*Context, 0, SourceLocation(),
                                   SourceLocation(), SourceRange(), 0,
                                   SourceLocation(), 0, 0);
    break;
  case pch::DECL_UNRESOLVED_USING_VALUE:
    D = UnresolvedUsingValueDecl::Create(*Context, 0, SourceLocation(),
                                         SourceRange(), 0, SourceLocation(),
                                         DeclarationName());
    break;
  case pch::DECL_UNRESOLVED_USING_TYPENAME:
    D = UnresolvedUsingTypenameDecl::Create(*Context, 0, SourceLocation(),
                                            SourceLocation(), SourceRange(),
                                            0, SourceLocation(),
                                            DeclarationName());
    break;
  case pch::DECL_CXX_RECORD:
    D = CXXRecordDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_CXX_METHOD:
    D = CXXMethodDecl::Create(*Context, 0, SourceLocation(), DeclarationName(),
                              QualType(), 0);
    break;
  case pch::DECL_CXX_CONSTRUCTOR:
    D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_CXX_DESTRUCTOR:
    D = CXXDestructorDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_CXX_CONVERSION:
    D = CXXConversionDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_ACCESS_SPEC:
    D = AccessSpecDecl::Create(*Context, AS_none, 0, SourceLocation(),
                               SourceLocation());
    break;
  case pch::DECL_FRIEND:
    D = FriendDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_FRIEND_TEMPLATE:
    D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_CLASS_TEMPLATE:
    D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(),
                                  DeclarationName(), 0, 0, 0);
    break;
  case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION:
    D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
    D = ClassTemplatePartialSpecializationDecl::Create(*Context,
                                                            Decl::EmptyShell());
    break;
  case pch::DECL_FUNCTION_TEMPLATE:
    D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(),
                                     DeclarationName(), 0, 0);
    break;
  case pch::DECL_TEMPLATE_TYPE_PARM:
    D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell());
    break;
  case pch::DECL_NON_TYPE_TEMPLATE_PARM:
    D = NonTypeTemplateParmDecl::Create(*Context, 0, SourceLocation(), 0,0,0,
                                        QualType(),0);
    break;
  case pch::DECL_TEMPLATE_TEMPLATE_PARM:
    D = TemplateTemplateParmDecl::Create(*Context, 0, SourceLocation(),0,0,0,0);
    break;
  case pch::DECL_STATIC_ASSERT:
    D = StaticAssertDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;

  case pch::DECL_OBJC_METHOD:
    D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
                               Selector(), QualType(), 0, 0);
    break;
  case pch::DECL_OBJC_INTERFACE:
    D = ObjCInterfaceDecl::Create(*Context, 0, SourceLocation(), 0);
    break;
  case pch::DECL_OBJC_IVAR:
    D = ObjCIvarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
                             ObjCIvarDecl::None);
    break;
  case pch::DECL_OBJC_PROTOCOL:
    D = ObjCProtocolDecl::Create(*Context, 0, SourceLocation(), 0);
    break;
  case pch::DECL_OBJC_AT_DEFS_FIELD:
    D = ObjCAtDefsFieldDecl::Create(*Context, 0, SourceLocation(), 0,
                                    QualType(), 0);
    break;
  case pch::DECL_OBJC_CLASS:
    D = ObjCClassDecl::Create(*Context, 0, SourceLocation());
    break;
  case pch::DECL_OBJC_FORWARD_PROTOCOL:
    D = ObjCForwardProtocolDecl::Create(*Context, 0, SourceLocation());
    break;
  case pch::DECL_OBJC_CATEGORY:
    D = ObjCCategoryDecl::Create(*Context, 0, SourceLocation(), 
                                 SourceLocation(), SourceLocation(), 0);
    break;
  case pch::DECL_OBJC_CATEGORY_IMPL:
    D = ObjCCategoryImplDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;
  case pch::DECL_OBJC_IMPLEMENTATION:
    D = ObjCImplementationDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;
  case pch::DECL_OBJC_COMPATIBLE_ALIAS:
    D = ObjCCompatibleAliasDecl::Create(*Context, 0, SourceLocation(), 0, 0);
    break;
  case pch::DECL_OBJC_PROPERTY:
    D = ObjCPropertyDecl::Create(*Context, 0, SourceLocation(), 0, SourceLocation(),
                                 0);
    break;
  case pch::DECL_OBJC_PROPERTY_IMPL:
    D = ObjCPropertyImplDecl::Create(*Context, 0, SourceLocation(),
                                     SourceLocation(), 0,
                                     ObjCPropertyImplDecl::Dynamic, 0);
    break;
  case pch::DECL_FIELD:
    D = FieldDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0, 0,
                          false);
    break;
  case pch::DECL_VAR:
    D = VarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
                        VarDecl::None, VarDecl::None);
    break;

  case pch::DECL_IMPLICIT_PARAM:
    D = ImplicitParamDecl::Create(*Context, 0, SourceLocation(), 0, QualType());
    break;

  case pch::DECL_PARM_VAR:
    D = ParmVarDecl::Create(*Context, 0, SourceLocation(), 0, QualType(), 0,
                            VarDecl::None, VarDecl::None, 0);
    break;
  case pch::DECL_FILE_SCOPE_ASM:
    D = FileScopeAsmDecl::Create(*Context, 0, SourceLocation(), 0);
    break;
  case pch::DECL_BLOCK:
    D = BlockDecl::Create(*Context, 0, SourceLocation());
    break;
  }

  assert(D && "Unknown declaration reading PCH file");
  LoadedDecl(Index, D);
  Reader.Visit(D);

  // If this declaration is also a declaration context, get the
  // offsets for its tables of lexical and visible declarations.
  if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
    std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC);
    if (Offsets.first || Offsets.second) {
      DC->setHasExternalLexicalStorage(Offsets.first != 0);
      DC->setHasExternalVisibleStorage(Offsets.second != 0);
      DeclContextInfo Info;
      if (ReadDeclContextStorage(DeclsCursor, Offsets, Info))
        return 0;
      DeclContextInfos &Infos = DeclContextOffsets[DC];
      // Reading the TU will happen after reading its update blocks, so we need
      // to make sure we insert in front. For all other contexts, the vector
      // is empty here anyway, so there's no loss in efficiency.
      Infos.insert(Infos.begin(), Info);
    }
  }
  assert(Idx == Record.size());

  // 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.
  if (isConsumerInterestedIn(D))
    InterestingDecls.push_back(D);

  return D;
}

bool PCHReader::ReadDeclContextStorage(llvm::BitstreamCursor &Cursor,
                                   const std::pair<uint64_t, uint64_t> &Offsets,
                                       DeclContextInfo &Info) {
  SavedStreamPosition SavedPosition(Cursor);
  // First the lexical decls.
  if (Offsets.first != 0) {
    Cursor.JumpToBit(Offsets.first);

    RecordData Record;
    const char *Blob;
    unsigned BlobLen;
    unsigned Code = Cursor.ReadCode();
    unsigned RecCode = Cursor.ReadRecord(Code, Record, &Blob, &BlobLen);
    if (RecCode != pch::DECL_CONTEXT_LEXICAL) {
      Error("Expected lexical block");
      return true;
    }

    Info.LexicalDecls = reinterpret_cast<const pch::DeclID*>(Blob);
    Info.NumLexicalDecls = BlobLen / sizeof(pch::DeclID);
  } else {
    Info.LexicalDecls = 0;
    Info.NumLexicalDecls = 0;
  }

  // Now the visible decls.
  Info.Stream = &Cursor;
  Info.OffsetToVisibleDecls = Offsets.second;

  return false;
}
