add PCH support for a bunch of C++ Decls, patch by
Andrew Sutton!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103301 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index d15cfef..a279eda 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -785,6 +785,12 @@
 }
 
 CXXConstructorDecl *
+CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) CXXConstructorDecl(0, SourceLocation(), DeclarationName(),
+                                    QualType(), 0, false, false, false);
+}
+
+CXXConstructorDecl *
 CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                            SourceLocation L, DeclarationName N,
                            QualType T, TypeSourceInfo *TInfo,
@@ -887,6 +893,12 @@
 }
 
 CXXDestructorDecl *
+CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) CXXDestructorDecl(0, SourceLocation(), DeclarationName(),
+                                   QualType(), false, false);
+}
+
+CXXDestructorDecl *
 CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                           SourceLocation L, DeclarationName N,
                           QualType T, bool isInline,
@@ -903,6 +915,12 @@
 }
 
 CXXConversionDecl *
+CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationName(),
+                                   QualType(), 0, false, false);
+}
+
+CXXConversionDecl *
 CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                           SourceLocation L, DeclarationName N,
                           QualType T, TypeSourceInfo *TInfo,
@@ -940,6 +958,12 @@
   return cast_or_null<NamespaceDecl>(NominatedNamespace);
 }
 
+void UsingDirectiveDecl::setNominatedNamespace(NamedDecl* ND) {
+  assert((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
+    "expected a NamespaceDecl or NamespaceAliasDecl");
+  NominatedNamespace = ND;
+}
+
 NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
                                                SourceLocation L,
                                                SourceLocation AliasLoc,
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index ae57ce5..8bc3b18 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2901,6 +2901,51 @@
   return DeclarationName();
 }
 
+NestedNameSpecifier *
+PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) {
+  unsigned N = Record[Idx++];
+  NestedNameSpecifier *NNS = 0, *Prev = 0;
+  for (unsigned I = 0; I != N; ++I) {
+    NestedNameSpecifier::SpecifierKind Kind
+      = (NestedNameSpecifier::SpecifierKind)Record[Idx++];
+    switch (Kind) {
+    case NestedNameSpecifier::Identifier: {
+      IdentifierInfo *II = GetIdentifierInfo(Record, Idx);
+      NNS = NestedNameSpecifier::Create(*Context, Prev, II);
+      break;
+    }
+
+    case NestedNameSpecifier::Namespace: {
+      NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++]));
+      NNS = NestedNameSpecifier::Create(*Context, Prev, NS);
+      break;
+    }
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate: {
+      Type *T = GetType(Record[Idx++]).getTypePtr();
+      bool Template = Record[Idx++];
+      NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T);
+      break;
+    }
+
+    case NestedNameSpecifier::Global: {
+      NNS = NestedNameSpecifier::GlobalSpecifier(*Context);
+      // No associated value, and there can't be a prefix.
+      break;
+    }
+    Prev = NNS;
+    }
+  }
+  return NNS;
+}
+
+SourceRange
+PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) {
+  return SourceRange(SourceLocation::getFromRawEncoding(Record[Idx++]),
+                     SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
+
 /// \brief Read an integral value
 llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
   unsigned BitWidth = Record[Idx++];
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 7e12660..c4f9622 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -17,6 +17,8 @@
 #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;
 
@@ -40,22 +42,49 @@
     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 VisitUnresolvedUsingTypename(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 VisitUnresolvedUsingValue(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 VisitClassTemplateDecl(ClassTemplateDecl *D);
+    void visitFunctionTemplateDecl(FunctionTemplateDecl *D);
+    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+    void VisitUsing(UsingDecl *D);
+    void VisitUsingShadow(UsingShadowDecl *D);
+    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
     void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD);
+    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
+    void VisitStaticAssertDecl(StaticAssertDecl *D);
     void VisitBlockDecl(BlockDecl *BD);
+
     std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC);
+
+    // FIXME: Reorder according to DeclNodes.def?
     void VisitObjCMethodDecl(ObjCMethodDecl *D);
     void VisitObjCContainerDecl(ObjCContainerDecl *D);
     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
@@ -90,6 +119,8 @@
 
 void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
   VisitDecl(TU);
+  TU->setAnonymousNamespace(
+                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
 }
 
 void PCHDeclReader::VisitNamedDecl(NamedDecl *ND) {
@@ -97,18 +128,6 @@
   ND->setDeclName(Reader.ReadDeclarationName(Record, Idx));
 }
 
-void PCHDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
-  VisitNamedDecl(D);
-  D->setLBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  D->setRBracLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
-  D->setNextNamespace(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setOriginalNamespace(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-  D->setAnonymousNamespace(
-                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
-}
-
 void PCHDeclReader::VisitTypeDecl(TypeDecl *TD) {
   VisitNamedDecl(TD);
   TD->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
@@ -193,6 +212,8 @@
   FD->setHasImplicitReturnZero(Record[Idx++]);
   FD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
   // FIXME: C++ TemplateOrInstantiation
+
+  // Read in the parameters.
   unsigned NumParams = Record[Idx++];
   llvm::SmallVector<ParmVarDecl *, 16> Params;
   Params.reserve(NumParams);
@@ -446,6 +467,155 @@
   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++])));
+
+  // Only read one reference--the original or anonymous namespace.
+  bool IsOriginal = Record[Idx++];
+  if (IsOriginal)
+    D->setAnonymousNamespace(
+                    cast_or_null<NamespaceDecl>(Reader.GetDecl(Record[Idx++])));
+  else
+    D->setOriginalNamespace(
+                    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::VisitUsing(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) {
+    D->addShadowDecl(cast<UsingShadowDecl>(Reader.GetDecl(Record[Idx++])));
+  }
+  D->setTypeName(Record[Idx++]);
+}
+
+void PCHDeclReader::VisitUsingShadow(UsingShadowDecl *D) {
+  VisitNamedDecl(D);
+  D->setTargetDecl(cast<NamedDecl>(Reader.GetDecl(Record[Idx++])));
+  D->setUsingDecl(cast<UsingDecl>(Reader.GetDecl(Record[Idx++])));
+}
+
+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::VisitUnresolvedUsingValue(UnresolvedUsingValueDecl *D) {
+  VisitValueDecl(D);
+  D->setTargetNestedNameRange(Reader.ReadSourceRange(Record, Idx));
+  D->setUsingLoc(Reader.ReadSourceLocation(Record, Idx));
+  D->setTargetNestedNameSpecifier(Reader.ReadNestedNameSpecifier(Record, Idx));
+}
+
+void PCHDeclReader::VisitUnresolvedUsingTypename(
+                                               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) {
+  // assert(false && "cannot read CXXRecordDecl");
+  VisitRecordDecl(D);
+}
+
+void PCHDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) {
+  // assert(false && "cannot read CXXMethodDecl");
+  VisitFunctionDecl(D);
+}
+
+void PCHDeclReader::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  // assert(false && "cannot read CXXConstructorDecl");
+  VisitCXXMethodDecl(D);
+}
+
+void PCHDeclReader::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  // assert(false && "cannot read CXXDestructorDecl");
+  VisitCXXMethodDecl(D);
+}
+
+void PCHDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  // assert(false && "cannot read CXXConversionDecl");
+  VisitCXXMethodDecl(D);
+}
+
+void PCHDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+  assert(false && "cannot read FriendTemplateDecl");
+}
+
+void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
+  assert(false && "cannot read TemplateDecl");
+}
+
+void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  assert(false && "cannot read ClassTemplateDecl");
+}
+
+void PCHDeclReader::VisitClassTemplateSpecializationDecl(
+                                           ClassTemplateSpecializationDecl *D) {
+  assert(false && "cannot read ClassTemplateSpecializationDecl");
+}
+
+void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
+                                    ClassTemplatePartialSpecializationDecl *D) {
+  assert(false && "cannot read ClassTemplatePartialSpecializationDecl");
+}
+
+void PCHDeclReader::visitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  assert(false && "cannot read FunctionTemplateDecl");
+}
+
+void PCHDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+  assert(false && "cannot read TemplateTypeParmDecl");
+}
+
+void PCHDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+  assert(false && "cannot read NonTypeTemplateParmDecl");
+}
+
+void PCHDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+  assert(false && "cannot read TemplateTemplateParmDecl");
+}
+
+void PCHDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  assert(false && "cannot read StaticAssertDecl");
+}
+
 std::pair<uint64_t, uint64_t>
 PCHDeclReader::VisitDeclContext(DeclContext *DC) {
   uint64_t LexicalOffset = Record[Idx++];
@@ -706,6 +876,94 @@
     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, TagDecl::TK_struct, 0,
+                              SourceLocation(), 0, SourceLocation(), 0);
+    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_FRIEND:
+    assert(false && "cannot read FriendDecl");
+    break;
+  case pch::DECL_FRIEND_TEMPLATE:
+    assert(false && "cannot read FriendTemplateDecl");
+    break;
+  case pch::DECL_TEMPLATE:
+    // FIXME: Should TemplateDecl be ABSTRACT_DECL???
+    assert(false && "TemplateDecl should be abstract!");
+    break;
+  case pch::DECL_CLASS_TEMPLATE:
+    assert(false && "cannot read ClassTemplateDecl");
+    break;
+  case pch::DECL_CLASS_TEMPLATE_SPECIALIZATION:
+    assert(false && "cannot read ClasstemplateSpecializationDecl");
+    break;
+  case pch::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
+    assert(false && "cannot read ClassTemplatePartialSpecializationDecl");
+    break;
+  case pch::DECL_FUNCTION_TEMPLATE:
+    assert(false && "cannot read FunctionTemplateDecl");
+    break;
+  case pch::DECL_TEMPLATE_TYPE_PARM:
+    assert(false && "cannot read TemplateTypeParmDecl");
+    break;
+  case pch::DECL_NON_TYPE_TEMPLATE_PARM:
+    assert(false && "cannot read NonTypeTemplateParmDecl");
+    break;
+  case pch::DECL_TEMPLATE_TEMPLATE_PARM:
+    assert(false && "cannot read TemplateTemplateParmDecl");
+    break;
+  case pch::DECL_STATIC_ASSERT:
+    assert(false && "cannot read StaticAssertDecl");
+    break;
+
   case pch::DECL_OBJC_METHOD:
     D = ObjCMethodDecl::Create(*Context, SourceLocation(), SourceLocation(),
                                Selector(), QualType(), 0, 0);
@@ -775,10 +1033,6 @@
   case pch::DECL_BLOCK:
     D = BlockDecl::Create(*Context, 0, SourceLocation());
     break;
-      
-  case pch::DECL_NAMESPACE:
-    D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
-    break;
   }
 
   assert(D && "Unknown declaration reading PCH file");
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e56dd31..225772b 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2181,6 +2181,11 @@
   Record.push_back(Loc.getRawEncoding());
 }
 
+void PCHWriter::AddSourceRange(SourceRange Range, RecordData &Record) {
+  AddSourceLocation(Range.getBegin(), Record);
+  AddSourceLocation(Range.getEnd(), Record);
+}
+
 void PCHWriter::AddAPInt(const llvm::APInt &Value, RecordData &Record) {
   Record.push_back(Value.getBitWidth());
   unsigned N = Value.getNumWords();
@@ -2407,3 +2412,42 @@
     break;
   }
 }
+
+void PCHWriter::AddNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                       RecordData &Record) {
+  // Nested name specifiers usually aren't too long. I think that 8 would
+  // typically accomodate the vast majority.
+  llvm::SmallVector<NestedNameSpecifier *, 8> NestedNames;
+
+  // Push each of the NNS's onto a stack for serialization in reverse order.
+  while (NNS) {
+    NestedNames.push_back(NNS);
+    NNS = NNS->getPrefix();
+  }
+
+  Record.push_back(NestedNames.size());
+  while(!NestedNames.empty()) {
+    NNS = NestedNames.pop_back_val();
+    NestedNameSpecifier::SpecifierKind Kind = NNS->getKind();
+    Record.push_back(Kind);
+    switch (Kind) {
+    case NestedNameSpecifier::Identifier:
+      AddIdentifierRef(NNS->getAsIdentifier(), Record);
+      break;
+
+    case NestedNameSpecifier::Namespace:
+      AddDeclRef(NNS->getAsNamespace(), Record);
+      break;
+
+    case NestedNameSpecifier::TypeSpec:
+    case NestedNameSpecifier::TypeSpecWithTemplate:
+      AddTypeRef(QualType(NNS->getAsType(), 0), Record);
+      Record.push_back(Kind == NestedNameSpecifier::TypeSpecWithTemplate);
+      break;
+
+    case NestedNameSpecifier::Global:
+      // Don't need to write an associated value.
+      break;
+    }
+  }
+}
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 3585093..a898c70 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -13,6 +13,8 @@
 
 #include "clang/Frontend/PCHWriter.h"
 #include "clang/AST/DeclVisitor.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Bitcode/BitstreamWriter.h"
@@ -43,23 +45,51 @@
     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
     void VisitNamedDecl(NamedDecl *D);
     void VisitNamespaceDecl(NamespaceDecl *D);
+    void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+    void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
     void VisitTypeDecl(TypeDecl *D);
     void VisitTypedefDecl(TypedefDecl *D);
+    void VisitUnresolvedUsingTypename(UnresolvedUsingTypenameDecl *D);
     void VisitTagDecl(TagDecl *D);
     void VisitEnumDecl(EnumDecl *D);
     void VisitRecordDecl(RecordDecl *D);
+    void VisitCXXRecordDecl(CXXRecordDecl *D);
+    void VisitClassTemplateSpecializationDecl(
+                                            ClassTemplateSpecializationDecl *D);
+    void VisitClassTemplatePartialSpecializationDecl(
+                                     ClassTemplatePartialSpecializationDecl *D);
+    void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
     void VisitValueDecl(ValueDecl *D);
     void VisitEnumConstantDecl(EnumConstantDecl *D);
+    void VisitUnresolvedUsingValue(UnresolvedUsingValueDecl *D);
     void VisitDeclaratorDecl(DeclaratorDecl *D);
     void VisitFunctionDecl(FunctionDecl *D);
+    void VisitCXXMethodDecl(CXXMethodDecl *D);
+    void VisitCXXConstructorDecl(CXXConstructorDecl *D);
+    void VisitCXXDestructorDecl(CXXDestructorDecl *D);
+    void VisitCXXConversionDecl(CXXConversionDecl *D);
     void VisitFieldDecl(FieldDecl *D);
     void VisitVarDecl(VarDecl *D);
     void VisitImplicitParamDecl(ImplicitParamDecl *D);
     void VisitParmVarDecl(ParmVarDecl *D);
+    void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+    void VisitTemplateDecl(TemplateDecl *D);
+    void VisitClassTemplateDecl(ClassTemplateDecl *D);
+    void visitFunctionTemplateDecl(FunctionTemplateDecl *D);
+    void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
+    void VisitUsing(UsingDecl *D);
+    void VisitUsingShadow(UsingShadowDecl *D);
+    void VisitLinkageSpecDecl(LinkageSpecDecl *D);
     void VisitFileScopeAsmDecl(FileScopeAsmDecl *D);
+    void VisitFriendTemplateDecl(FriendTemplateDecl *D);
+    void VisitStaticAssertDecl(StaticAssertDecl *D);
     void VisitBlockDecl(BlockDecl *D);
+
     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
                           uint64_t VisibleOffset);
+
+
+    // FIXME: Put in the same order is DeclNodes.def?
     void VisitObjCMethodDecl(ObjCMethodDecl *D);
     void VisitObjCContainerDecl(ObjCContainerDecl *D);
     void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
@@ -92,6 +122,7 @@
 
 void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
   VisitDecl(D);
+  Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
   Code = pch::DECL_TRANSLATION_UNIT;
 }
 
@@ -100,16 +131,6 @@
   Writer.AddDeclarationName(D->getDeclName(), Record);
 }
 
-void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
-  VisitNamedDecl(D);
-  Writer.AddSourceLocation(D->getLBracLoc(), Record);
-  Writer.AddSourceLocation(D->getRBracLoc(), Record);
-  Writer.AddDeclRef(D->getNextNamespace(), Record);
-  Writer.AddDeclRef(D->getOriginalNamespace(), Record);
-  Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
-  Code = pch::DECL_NAMESPACE;
-}
-
 void PCHDeclWriter::VisitTypeDecl(TypeDecl *D) {
   VisitNamedDecl(D);
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
@@ -173,9 +194,11 @@
 
 void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
   VisitDeclaratorDecl(D);
+
   Record.push_back(D->isThisDeclarationADefinition());
   if (D->isThisDeclarationADefinition())
     Writer.AddStmt(D->getBody());
+
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
   Record.push_back(D->getStorageClassAsWritten());
@@ -188,8 +211,9 @@
   Record.push_back(D->isTrivial());
   Record.push_back(D->isCopyAssignment());
   Record.push_back(D->hasImplicitReturnZero());
+  // FIXME: C++ TemplateOrInstantiation???
   Writer.AddSourceLocation(D->getLocEnd(), Record);
-  // FIXME: C++ TemplateOrInstantiation
+
   Record.push_back(D->param_size());
   for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
        P != PEnd; ++P)
@@ -227,9 +251,7 @@
 
 void PCHDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
   VisitNamedDecl(D);
-  SourceRange R = D->getAtEndRange();
-  Writer.AddSourceLocation(R.getBegin(), Record);
-  Writer.AddSourceLocation(R.getEnd(), Record);
+  Writer.AddSourceRange(D->getAtEndRange(), Record);
   // Abstract class (no need to define a stable pch::DECL code).
 }
 
@@ -411,7 +433,6 @@
   Record.push_back(D->hasInheritedDefaultArg());
   Code = pch::DECL_PARM_VAR;
 
-
   // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here
   // we dynamically check for the properties that we optimize for, but don't
   // know are true of all PARM_VAR_DECLs.
@@ -454,6 +475,161 @@
   Code = pch::DECL_BLOCK;
 }
 
+void PCHDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
+  VisitDecl(D);
+  // FIXME: It might be nice to serialize the brace locations for this
+  // declaration, which don't seem to be readily available in the AST.
+  Record.push_back(D->getLanguage());
+  Record.push_back(D->hasBraces());
+  Code = pch::DECL_LINKAGE_SPEC;
+}
+
+void PCHDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddSourceLocation(D->getLBracLoc(), Record);
+  Writer.AddSourceLocation(D->getRBracLoc(), Record);
+  Writer.AddDeclRef(D->getNextNamespace(), Record);
+
+  // Only write one reference--original or anonymous
+  Record.push_back(D->isOriginalNamespace());
+  if (D->isOriginalNamespace())
+    Writer.AddDeclRef(D->getAnonymousNamespace(), Record);
+  else
+    Writer.AddDeclRef(D->getOriginalNamespace(), Record);
+  Code = pch::DECL_NAMESPACE;
+}
+
+void PCHDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddSourceLocation(D->getAliasLoc(), Record);
+  Writer.AddSourceRange(D->getQualifierRange(), Record);
+  Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+  Writer.AddSourceLocation(D->getTargetNameLoc(), Record);
+  Writer.AddDeclRef(D->getNamespace(), Record);
+  Code = pch::DECL_NAMESPACE_ALIAS;
+}
+
+void PCHDeclWriter::VisitUsing(UsingDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddSourceRange(D->getNestedNameRange(), Record);
+  Writer.AddSourceLocation(D->getUsingLocation(), Record);
+  Writer.AddNestedNameSpecifier(D->getTargetNestedNameDecl(), Record);
+  Record.push_back(D->getNumShadowDecls());
+  for (UsingDecl::shadow_iterator P = D->shadow_begin(),
+       PEnd = D->shadow_end(); P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  Record.push_back(D->isTypeName());
+  Code = pch::DECL_USING;
+}
+
+void PCHDeclWriter::VisitUsingShadow(UsingShadowDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddDeclRef(D->getTargetDecl(), Record);
+  Writer.AddDeclRef(D->getUsingDecl(), Record);
+  Code = pch::DECL_USING_SHADOW;
+}
+
+void PCHDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+  VisitNamedDecl(D);
+  Writer.AddSourceLocation(D->getNamespaceKeyLocation(), Record);
+  Writer.AddSourceRange(D->getQualifierRange(), Record);
+  Writer.AddNestedNameSpecifier(D->getQualifier(), Record);
+  Writer.AddSourceLocation(D->getIdentLocation(), Record);
+  Writer.AddDeclRef(D->getNominatedNamespace(), Record);
+  Writer.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor()), Record);
+  Code = pch::DECL_USING_DIRECTIVE;
+}
+
+void PCHDeclWriter::VisitUnresolvedUsingValue(UnresolvedUsingValueDecl *D) {
+  VisitValueDecl(D);
+  Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
+  Writer.AddSourceLocation(D->getUsingLoc(), Record);
+  Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+  Code = pch::DECL_UNRESOLVED_USING_VALUE;
+}
+
+void PCHDeclWriter::VisitUnresolvedUsingTypename(
+                                               UnresolvedUsingTypenameDecl *D) {
+  VisitTypeDecl(D);
+  Writer.AddSourceRange(D->getTargetNestedNameRange(), Record);
+  Writer.AddSourceLocation(D->getUsingLoc(), Record);
+  Writer.AddSourceLocation(D->getTypenameLoc(), Record);
+  Writer.AddNestedNameSpecifier(D->getTargetNestedNameSpecifier(), Record);
+  Code = pch::DECL_UNRESOLVED_USING_TYPENAME;
+}
+
+void PCHDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
+  // assert(false && "cannot write CXXRecordDecl");
+  VisitRecordDecl(D);
+  Code = pch::DECL_CXX_RECORD;
+}
+
+void PCHDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
+  // assert(false && "cannot write CXXMethodDecl");
+  VisitFunctionDecl(D);
+  Code = pch::DECL_CXX_METHOD;
+}
+
+void PCHDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+  // assert(false && "cannot write CXXConstructorDecl");
+  VisitCXXMethodDecl(D);
+  Code = pch::DECL_CXX_CONSTRUCTOR;
+}
+
+void PCHDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+  // assert(false && "cannot write CXXDestructorDecl");
+  VisitCXXMethodDecl(D);
+  Code = pch::DECL_CXX_DESTRUCTOR;
+}
+
+void PCHDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) {
+  // assert(false && "cannot write CXXConversionDecl");
+  VisitCXXMethodDecl(D);
+  Code = pch::DECL_CXX_CONVERSION;
+}
+
+void PCHDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) {
+  assert(false && "cannot write FriendTemplateDecl");
+}
+
+void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
+  assert(false && "cannot write TemplateDecl");
+}
+
+void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  assert(false && "cannot write ClassTemplateDecl");
+}
+
+void PCHDeclWriter::VisitClassTemplateSpecializationDecl(
+                                           ClassTemplateSpecializationDecl *D) {
+  assert(false && "cannot write ClassTemplateSpecializationDecl");
+}
+
+void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
+                                    ClassTemplatePartialSpecializationDecl *D) {
+  assert(false && "cannot write ClassTemplatePartialSpecializationDecl");
+}
+
+void PCHDeclWriter::visitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+  assert(false && "cannot write FunctionTemplateDecl");
+}
+
+void PCHDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+  assert(false && "cannot write TemplateTypeParmDecl");
+}
+
+void PCHDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+  assert(false && "cannot write NonTypeTemplateParmDecl");
+}
+
+void PCHDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+  assert(false && "cannot write TemplateTemplateParmDecl");
+}
+
+void PCHDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) {
+  assert(false && "cannot write StaticAssertDecl");
+}
+
 /// \brief Emit the DeclContext part of a declaration context decl.
 ///
 /// \param LexicalOffset the offset at which the DECL_CONTEXT_LEXICAL