r184791 - Check for matching template-parameter-lists when merging template declarations.

Richard Smith richard-llvm at metafoo.co.uk
Mon Jun 24 15:51:01 PDT 2013


Author: rsmith
Date: Mon Jun 24 17:51:00 2013
New Revision: 184791

URL: http://llvm.org/viewvc/llvm-project?rev=184791&view=rev
Log:
Check for matching template-parameter-lists when merging template declarations.

Modified:
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
    cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
    cfe/trunk/test/Modules/cxx-templates.cpp

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=184791&r1=184790&r2=184791&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Jun 24 17:51:00 2013
@@ -967,6 +967,9 @@ void ASTDeclReader::VisitParmVarDecl(Par
   PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++];
   if (Record[Idx++]) // hasUninstantiatedDefaultArg.
     PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F));
+
+  // FIXME: If this is a redeclaration of a function from another module, handle
+  // inheritance of default arguments.
 }
 
 void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
@@ -1334,6 +1337,9 @@ void ASTDeclReader::VisitTemplateDecl(Te
   TemplateParameterList* TemplateParams
       = Reader.ReadTemplateParameterList(F, Record, Idx); 
   D->init(TemplatedDecl, TemplateParams);
+
+  // FIXME: If this is a redeclaration of a template from another module, handle
+  // inheritance of default template arguments.
 }
 
 ASTDeclReader::RedeclarableResult 
@@ -1772,6 +1778,48 @@ uint64_t ASTReader::getGlobalBitOffset(M
   return LocalOffset + M.GlobalBitOffset;
 }
 
+static bool isSameTemplateParameterList(const TemplateParameterList *X,
+                                        const TemplateParameterList *Y);
+
+/// \brief Determine whether two template parameters are similar enough
+/// that they may be used in declarations of the same template.
+static bool isSameTemplateParameter(const NamedDecl *X,
+                                    const NamedDecl *Y) {
+  if (X->getKind() != Y->getKind())
+    return false;
+
+  if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
+    const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y);
+    return TX->isParameterPack() == TY->isParameterPack();
+  }
+
+  if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
+    const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y);
+    return TX->isParameterPack() == TY->isParameterPack() &&
+           TX->getASTContext().hasSameType(TX->getType(), TY->getType());
+  }
+
+  const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X);
+  const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y);
+  return TX->isParameterPack() == TY->isParameterPack() &&
+         isSameTemplateParameterList(TX->getTemplateParameters(),
+                                     TY->getTemplateParameters());
+}
+
+/// \brief Determine whether two template parameter lists are similar enough
+/// that they may be used in declarations of the same template.
+static bool isSameTemplateParameterList(const TemplateParameterList *X,
+                                        const TemplateParameterList *Y) {
+  if (X->size() != Y->size())
+    return false;
+
+  for (unsigned I = 0, N = X->size(); I != N; ++I)
+    if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
+      return false;
+
+  return true;
+}
+
 /// \brief Determine whether the two declarations refer to the same entity.
 static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
   assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
@@ -1841,10 +1889,11 @@ static bool isSameEntity(NamedDecl *X, N
   // Identical template names and kinds match if their template parameter lists
   // and patterns match.
   if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) {
-    TemplateDecl *TemplateY = dyn_cast<TemplateDecl>(Y);
-    // FIXME: Check template parameter lists.
+    TemplateDecl *TemplateY = cast<TemplateDecl>(Y);
     return isSameEntity(TemplateX->getTemplatedDecl(),
-                        TemplateY->getTemplatedDecl());
+                        TemplateY->getTemplatedDecl()) &&
+           isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+                                       TemplateY->getTemplateParameters());
   }
 
   // FIXME: Many other cases to implement.

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-a.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-a.h?rev=184791&r1=184790&r2=184791&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-a.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-a.h Mon Jun 24 17:51:00 2013
@@ -4,3 +4,7 @@ namespace N {
   template<typename T> T f() { return T(); }
   template<typename T> T f(T);
 }
+
+template<int N> int template_param_kinds_1();
+template<template<typename T, int, int> class> int template_param_kinds_2();
+template<template<typename T, typename U, T> class> int template_param_kinds_3();

Modified: cfe/trunk/test/Modules/Inputs/cxx-templates-b.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-templates-b.h?rev=184791&r1=184790&r2=184791&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-templates-b.h (original)
+++ cfe/trunk/test/Modules/Inputs/cxx-templates-b.h Mon Jun 24 17:51:00 2013
@@ -4,3 +4,7 @@ namespace N {
   template<typename T> T f();
   template<typename T> T f(T t) { return t; }
 }
+
+template<typename> int template_param_kinds_1();
+template<template<typename, int, int...> class> int template_param_kinds_2();
+template<template<typename T, typename U, U> class> int template_param_kinds_3();

Modified: cfe/trunk/test/Modules/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-templates.cpp?rev=184791&r1=184790&r2=184791&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cxx-templates.cpp (original)
+++ cfe/trunk/test/Modules/cxx-templates.cpp Mon Jun 24 17:51:00 2013
@@ -6,6 +6,12 @@
 @import cxx_templates_a;
 @import cxx_templates_b;
 
+template<typename, char> struct Tmpl_T_C {};
+template<typename, int, int> struct Tmpl_T_I_I {};
+
+template<typename A, typename B, A> struct Tmpl_T_T_A {};
+template<typename A, typename B, B> struct Tmpl_T_T_B {};
+
 void g() {
   f(0);
   f<double>(1.0);
@@ -20,6 +26,26 @@ void g() {
   N::f(); // expected-error {{no matching function}}
   // expected-note at Inputs/cxx-templates-a.h:4 {{couldn't infer template argument}}
   // expected-note at Inputs/cxx-templates-a.h:5 {{requires 1 argument, but 0 were provided}}
+
+  template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
+  template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
+
+  template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function}}
+  // expected-note at Inputs/cxx-templates-a.h:9 {{invalid explicitly-specified argument}}
+  // expected-note at Inputs/cxx-templates-b.h:9 {{invalid explicitly-specified argument}}
+
+  template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
+  // expected-note at Inputs/cxx-templates-a.h:9 {{candidate}}
+  // expected-note at Inputs/cxx-templates-b.h:9 {{candidate}}
+
+  // FIXME: This should be valid, but we incorrectly match the template template
+  // argument against both template template parameters.
+  template_param_kinds_3<Tmpl_T_T_A>(); // expected-error {{ambiguous}}
+  // expected-note at Inputs/cxx-templates-a.h:10 {{candidate}}
+  // expected-note at Inputs/cxx-templates-b.h:10 {{candidate}}
+  template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}}
+  // expected-note at Inputs/cxx-templates-a.h:10 {{candidate}}
+  // expected-note at Inputs/cxx-templates-b.h:10 {{candidate}}
 }
 
 // FIXME: There should only be two 'f's here.





More information about the cfe-commits mailing list