Reimplement RedeclarableTemplateDecl in terms of
Redeclarable<RedeclarableTemplateDecl>, eliminating a bunch of
redeclaration-chain logic both in RedeclarableTemplateDecl and
especially in its (de-)serialization.

As part of this, eliminate the RedeclarableTemplate<> class template,
which was an abstraction that didn't actually save anything.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148181 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index fa21bf5..2417845 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -6152,10 +6152,10 @@
     PendingChainedObjCCategories.clear();
   }
   
-  // If we deserialized any C++ or Objective-C class definitions or any
-  // Objective-C protocol definitions, make sure that all redeclarations point 
-  // to the definitions. Note that this can only happen now, after the 
-  // redeclaration chains have been fully wired.
+  // If we deserialized any C++ or Objective-C class definitions, any
+  // Objective-C protocol definitions, or any redeclarable templates, make sure
+  // that all redeclarations point to the definitions. Note that this can only 
+  // happen now, after the redeclaration chains have been fully wired.
   for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
                                            DEnd = PendingDefinitions.end();
        D != DEnd; ++D) {
@@ -6177,11 +6177,21 @@
       continue;
     }
     
-    ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(*D);
-    for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
-                                        REnd = PD->redecls_end();
+    if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
+      for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
+                                          REnd = PD->redecls_end();
+           R != REnd; ++R)
+        R->Data = PD->Data;
+      
+      continue;
+    }
+    
+    RedeclarableTemplateDecl *RTD
+      = cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
+    for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
+                                                REnd = RTD->redecls_end();
          R != REnd; ++R)
-      R->Data = PD->Data;
+      R->Common = RTD->Common;    
   }
   PendingDefinitions.clear();
 }
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 75c079f..21a0fb0 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1234,72 +1234,40 @@
 
 ASTDeclReader::RedeclarableResult 
 ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
-  // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
-  // can be used while this is still initializing.
-  enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
-  RedeclKind Kind = (RedeclKind)Record[Idx++];
-  
-  // Determine the first declaration ID.
-  DeclID FirstDeclID = 0;
-  switch (Kind) {
-  case FirstDeclaration: {
-    FirstDeclID = ThisDeclID;
+  RedeclarableResult Redecl = VisitRedeclarable(D);
 
-    // Since this is the first declaration of the template, fill in the 
-    // information for the 'common' pointer.
-    if (D->CommonOrPrev.isNull()) {
-      RedeclarableTemplateDecl::CommonBase *Common
-        = D->newCommon(Reader.getContext());
-      Common->Latest = D;
-      D->CommonOrPrev = Common;
-    }
+  // Make sure we've allocated the Common pointer first. We do this before
+  // VisitTemplateDecl so that getCommonPtr() can be used during initialization.
+  RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
+  if (!CanonD->Common) {
+    CanonD->Common = CanonD->newCommon(Reader.getContext());
+    Reader.PendingDefinitions.insert(CanonD);
+  }
+  D->Common = CanonD->Common;
 
+  // If this is the first declaration of the template, fill in the information
+  // for the 'common' pointer.
+  if (ThisDeclID == Redecl.getFirstID()) {
     if (RedeclarableTemplateDecl *RTD
           = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
       assert(RTD->getKind() == D->getKind() &&
              "InstantiatedFromMemberTemplate kind mismatch");
-      D->setInstantiatedFromMemberTemplateImpl(RTD);
+      D->setInstantiatedFromMemberTemplate(RTD);
       if (Record[Idx++])
         D->setMemberSpecialization();
     }
-    break;
   }
-   
-  case FirstInFile:
-  case PointsToPrevious: {
-    FirstDeclID = ReadDeclID(Record, Idx);
-    DeclID PrevDeclID = ReadDeclID(Record, Idx);
-    
-    RedeclarableTemplateDecl *FirstDecl
-      = cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID));
-    
-    // We delay loading of the redeclaration chain to avoid deeply nested calls.
-    // We temporarily set the first (canonical) declaration as the previous one
-    // which is the one that matters and mark the real previous DeclID to be
-    // loaded and attached later on.
-    D->CommonOrPrev = FirstDecl;
-    
-    if (Kind == PointsToPrevious) {
-      // Make a note that we need to wire up this declaration to its
-      // previous declaration, later. We don't need to do this for the first
-      // declaration in any given module file, because those will be wired 
-      // together later.
-      Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
-    }
-    break;
-  }
-  }
-  
+     
   VisitTemplateDecl(D);
   D->IdentifierNamespace = Record[Idx++];
   
-  return RedeclarableResult(Reader, FirstDeclID);
+  return Redecl;
 }
 
 void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
+  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (ThisDeclID == Redecl.getFirstID()) {
     // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
     // the specializations.
     SmallVector<serialization::DeclID, 2> SpecIDs;
@@ -1321,6 +1289,7 @@
       typedef serialization::DeclID DeclID;
       
       ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+      // FIXME: Append specializations!
       CommonPtr->LazySpecializations
         = new (Reader.getContext()) DeclID [SpecIDs.size()];
       memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), 
@@ -1415,9 +1384,9 @@
 }
 
 void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitRedeclarableTemplateDecl(D);
+  RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (ThisDeclID == Redecl.getFirstID()) {
     // This FunctionTemplateDecl owns a CommonPtr; read it.
 
     // Read the function specialization declarations.
@@ -1808,7 +1777,7 @@
     ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
   } else {
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
-    TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous);
+    TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous));
   }
 }
 
@@ -1841,7 +1810,9 @@
                                                    cast<NamespaceDecl>(Latest));
   } else {
     RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
-    TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest);
+    TD->RedeclLink
+      = Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
+                                        cast<RedeclarableTemplateDecl>(Latest));
   }
 }
 
diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp
index b0ba7b4..32432c0 100644
--- a/lib/Serialization/ASTWriterDecl.cpp
+++ b/lib/Serialization/ASTWriterDecl.cpp
@@ -1031,38 +1031,17 @@
 }
 
 void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
+  VisitRedeclarable(D);
+
   // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
   // getCommonPtr() can be used while this is still initializing.
-  enum { FirstDeclaration, FirstInFile, PointsToPrevious };
-  RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
-  RedeclarableTemplateDecl *First = 0;
-  if (!Prev) {
-    Record.push_back(FirstDeclaration);
-    
+  if (D->isFirstDeclaration()) {
     // This declaration owns the 'common' pointer, so serialize that data now.
     Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
     if (D->getInstantiatedFromMemberTemplate())
       Record.push_back(D->isMemberSpecialization());
-  } else {
-    First = D->getFirstDeclaration();
-    Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
-    Writer.AddDeclRef(First, Record);
-    Writer.AddDeclRef(Prev, Record);    
   }
   
-  if (D->getMostRecentDeclaration() != D && (!Prev || Prev->isFromASTFile())) {
-    if (!First)
-      First = D->getFirstDeclaration();
-    
-    // Capture the set of redeclarations in this file.
-    LocalRedeclarationsInfo LocalInfo = {
-      Writer.GetDeclRef(First),
-      Writer.GetDeclRef(D),
-      Writer.GetDeclRef(D->getMostRecentDeclaration())
-    };
-    Writer.LocalRedeclarations.push_back(LocalInfo);
-  }
-
   VisitTemplateDecl(D);
   Record.push_back(D->getIdentifierNamespace());
 }
@@ -1070,7 +1049,7 @@
 void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
   VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->isFirstDeclaration()) {
     typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
     CTSDSetTy &CTSDSet = D->getSpecializations();
     Record.push_back(CTSDSet.size());
@@ -1158,7 +1137,7 @@
 void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
   VisitRedeclarableTemplateDecl(D);
 
-  if (D->getPreviousDeclaration() == 0) {
+  if (D->isFirstDeclaration()) {
     // This FunctionTemplateDecl owns the CommonPtr; write it.
 
     // Write the function specialization declarations.