Apart from storing/retrieving the previous redeclaration from PCH, also store/retrieve the most recent
redeclaration. That way we are sure that the full redeclarations chain is loaded.

When using chained PCHs, first declarations point to the most recent redeclarations in the same PCH.
To address this use a REDECLS_UPDATE_LATEST record block to keep track of which first declarations need
to point to a most recent redeclaration in another PCH.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110125 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 28a82cd..9e9835a 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -92,6 +92,7 @@
 
     void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset,
                           uint64_t VisibleOffset);
+    template <typename T> void VisitRedeclarable(Redeclarable<T> *D);
 
 
     // FIXME: Put in the same order is DeclNodes.td?
@@ -163,7 +164,7 @@
 void PCHDeclWriter::VisitTagDecl(TagDecl *D) {
   VisitTypeDecl(D);
   Record.push_back(D->getIdentifierNamespace());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding
   Record.push_back(D->isDefinition());
   Record.push_back(D->isEmbeddedInDeclarator());
@@ -279,7 +280,7 @@
   // FunctionDecl's body is handled last at PCHWriterDecl::Visit,
   // after everything else is written.
 
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back(D->getStorageClass()); // FIXME: stable encoding
   Record.push_back(D->getStorageClassAsWritten());
   Record.push_back(D->isInlineSpecified());
@@ -500,7 +501,7 @@
   Record.push_back(D->isDeclaredInCondition());
   Record.push_back(D->isExceptionVariable());
   Record.push_back(D->isNRVOVariable());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
+  VisitRedeclarable(D);
   Record.push_back(D->getInit() ? 1 : 0);
   if (D->getInit())
     Writer.AddStmt(D->getInit());
@@ -854,6 +855,18 @@
       Record.push_back(D->isMemberSpecialization());
 
     Writer.AddDeclRef(D->getCommonPtr()->Latest, Record);
+  } else {
+    RedeclarableTemplateDecl *First = D->getFirstDeclaration();
+    assert(First != D);
+    // If this is a most recent redeclaration that is pointed to by a first decl
+    // in a chained PCH, keep track of the association with the map so we can
+    // update the first decl during PCH reading.
+    if (First->getMostRecentDeclaration() == D &&
+        First->getPCHLevel() > D->getPCHLevel()) {
+      assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end()
+             && "The latest is already set");
+      Writer.FirstLatestDecls[First] = D;
+    }
   }
 }
 
@@ -1016,6 +1029,29 @@
   Record.push_back(VisibleOffset);
 }
 
+template <typename T>
+void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) {
+  enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest };
+  if (D->RedeclLink.getNext() == D) {
+    Record.push_back(NoRedeclaration);
+  } else {
+    Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious
+                                                    : PointsToLatest);
+    Writer.AddDeclRef(D->RedeclLink.getPointer(), Record);
+  }
+
+  T *First = D->getFirstDeclaration();
+  T *ThisDecl = static_cast<T*>(D);
+  // If this is a most recent redeclaration that is pointed to by a first decl
+  // in a chained PCH, keep track of the association with the map so we can
+  // update the first decl during PCH reading.
+  if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl &&
+      First->getPCHLevel() > ThisDecl->getPCHLevel()) {
+    assert(Writer.FirstLatestDecls.find(First) == Writer.FirstLatestDecls.end()
+           && "The latest is already set");
+    Writer.FirstLatestDecls[First] = ThisDecl;
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // PCHWriter Implementation