[ODRHash] Diagnose differing template parameters.

llvm-svn: 311519
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index c968a55..fb8eade 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -158,7 +158,14 @@
   }
 }
 
-void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {}
+void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
+  assert(TPL && "Expecting non-null pointer.");
+
+  ID.AddInteger(TPL->size());
+  for (auto *ND : TPL->asArray()) {
+    AddSubDecl(ND);
+  }
+}
 
 void ODRHash::clear() {
   DeclMap.clear();
@@ -236,6 +243,10 @@
     }
   }
 
+  void AddTemplateArgument(TemplateArgument TA) {
+    Hash.AddTemplateArgument(TA);
+  }
+
   void Visit(const Decl *D) {
     ID.AddInteger(D->getKind());
     Inherited::Visit(D);
@@ -343,6 +354,42 @@
       AddDecl(D->getFriendDecl());
     }
   }
+
+  void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
+    // Only care about default arguments as part of the definition.
+    const bool hasDefaultArgument =
+        D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+    Hash.AddBoolean(hasDefaultArgument);
+    if (hasDefaultArgument) {
+      AddTemplateArgument(D->getDefaultArgument());
+    }
+
+    Inherited::VisitTemplateTypeParmDecl(D);
+  }
+
+  void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
+    // Only care about default arguments as part of the definition.
+    const bool hasDefaultArgument =
+        D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+    Hash.AddBoolean(hasDefaultArgument);
+    if (hasDefaultArgument) {
+      AddStmt(D->getDefaultArgument());
+    }
+
+    Inherited::VisitNonTypeTemplateParmDecl(D);
+  }
+
+  void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
+    // Only care about default arguments as part of the definition.
+    const bool hasDefaultArgument =
+        D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
+    Hash.AddBoolean(hasDefaultArgument);
+    if (hasDefaultArgument) {
+      AddTemplateArgument(D->getDefaultArgument().getArgument());
+    }
+
+    Inherited::VisitTemplateTemplateParmDecl(D);
+  }
 };
 } // namespace
 
@@ -403,6 +450,12 @@
   for (auto SubDecl : Decls) {
     AddSubDecl(SubDecl);
   }
+
+  const ClassTemplateDecl *TD = Record->getDescribedClassTemplate();
+  AddBoolean(TD);
+  if (TD) {
+    AddTemplateParameterList(TD->getTemplateParameters());
+  }
 }
 
 void ODRHash::AddDecl(const Decl *D) {