Refactor redeclarable template declarations

This patch refactors much of the common code in ClassTemplateDecl and
FunctionTemplateDecl into a common base class RedeclarableTemplateDecl
together with support functions in a template class RedeclarableTemplate.

The patch also includes similar refactoring for these classes' PCH
reader and writer implementations.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109754 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index fe2947d..94485d2 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -78,6 +78,7 @@
     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);
@@ -895,14 +896,32 @@
   D->init(TemplatedDecl, TemplateParams);
 }
 
-void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
   VisitTemplateDecl(D);
 
   D->IdentifierNamespace = Record[Idx++];
-  ClassTemplateDecl *PrevDecl =
-      cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-  D->setPreviousDeclaration(PrevDecl);
+  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();
+    }
+  }
+}
+
+void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  VisitRedeclarableTemplateDecl(D);
+
+  if (D->getPreviousDeclaration() == 0) {
     // This ClassTemplateDecl owns a CommonPtr; read it.
 
     // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
@@ -916,13 +935,6 @@
                                                  Reader.GetDecl(Record[Idx++]));
 
     // InjectedClassNameType is computed.
-
-    if (ClassTemplateDecl *CTD
-          = cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
-      D->setInstantiatedFromMemberTemplate(CTD);
-      if (Record[Idx++])
-        D->setMemberSpecialization();
-    }
   }
 }
 
@@ -993,13 +1005,9 @@
 }
 
 void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitTemplateDecl(D);
+  VisitRedeclarableTemplateDecl(D);
 
-  D->IdentifierNamespace = Record[Idx++];
-  FunctionTemplateDecl *PrevDecl =
-      cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
-  D->setPreviousDeclaration(PrevDecl);
-  if (PrevDecl == 0) {
+  if (D->getPreviousDeclaration() == 0) {
     // This FunctionTemplateDecl owns a CommonPtr; read it.
 
     // Read the function specialization declarations.
@@ -1008,13 +1016,6 @@
     unsigned NumSpecs = Record[Idx++];
     while (NumSpecs--)
       Reader.GetDecl(Record[Idx++]);
-
-    if (FunctionTemplateDecl *CTD
-          = cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
-      D->setInstantiatedFromMemberTemplate(CTD);
-      if (Record[Idx++])
-        D->setMemberSpecialization();
-    }
   }
 }
 
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 06266d2..3ac4958 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -76,6 +76,7 @@
     void VisitParmVarDecl(ParmVarDecl *D);
     void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     void VisitTemplateDecl(TemplateDecl *D);
+    void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
     void VisitClassTemplateDecl(ClassTemplateDecl *D);
     void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
     void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@@ -839,15 +840,25 @@
   Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
 }
 
-void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
   VisitTemplateDecl(D);
 
   Record.push_back(D->getIdentifierNamespace());
   Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   if (D->getPreviousDeclaration() == 0) {
-    // This ClassTemplateDecl owns the CommonPtr; write it.
+    // This TemplateDecl owns the CommonPtr; write it.
     assert(D->isCanonicalDecl());
 
+    Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
+    if (D->getInstantiatedFromMemberTemplate())
+      Record.push_back(D->isMemberSpecialization());
+  }
+}
+
+void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+  VisitRedeclarableTemplateDecl(D);
+
+  if (D->getPreviousDeclaration() == 0) {
     typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
     CTSDSetTy &CTSDSet = D->getSpecializations();
     Record.push_back(CTSDSet.size());
@@ -865,10 +876,6 @@
     }
 
     // InjectedClassNameType is computed, no need to write it.
-
-    Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
-    if (D->getInstantiatedFromMemberTemplate())
-      Record.push_back(D->isMemberSpecialization());
   }
   Code = pch::DECL_CLASS_TEMPLATE;
 }
@@ -929,10 +936,8 @@
 }
 
 void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
-  VisitTemplateDecl(D);
+  VisitRedeclarableTemplateDecl(D);
 
-  Record.push_back(D->getIdentifierNamespace());
-  Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
   if (D->getPreviousDeclaration() == 0) {
     // This FunctionTemplateDecl owns the CommonPtr; write it.
 
@@ -945,10 +950,6 @@
              "Expected only canonical decls in set");
       Writer.AddDeclRef(I->Function, Record);
     }
-
-    Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
-    if (D->getInstantiatedFromMemberTemplate())
-      Record.push_back(D->isMemberSpecialization());
   }
   Code = pch::DECL_FUNCTION_TEMPLATE;
 }