[cfe-commits] r86992 - in /cfe/trunk: lib/AST/TypePrinter.cpp lib/Sema/Sema.h lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/SemaTemplate/instantiate-template-template-parm.cpp

Douglas Gregor dgregor at apple.com
Thu Nov 12 08:20:59 PST 2009


Author: dgregor
Date: Thu Nov 12 10:20:59 2009
New Revision: 86992

URL: http://llvm.org/viewvc/llvm-project?rev=86992&view=rev
Log:
When comparing template parameter lists, distinguish between three cases:
  - Comparing template parameter lists to determine if we have a redeclaration
  - Comparing template parameter lists to determine if we have equivalent
    template template parameters
  - Comparing template parameter lists to determine whether a template 
    template argument is valid for a given template template parameter.

Previously, we did not distinguish between the last two cases, which
got us into trouble when we were looking for exact type matches
between the types of non-type template parameters that were dependent
types. Now we do, so we properly delay checking of template template
arguments until instantiation time.

Also, fix an accidental fall-through in a case statement that was
causing crashes.


Modified:
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=86992&r1=86991&r2=86992&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Thu Nov 12 10:20:59 2009
@@ -579,6 +579,7 @@
     case TemplateArgument::Template: {
       llvm::raw_string_ostream s(Buffer);
       Arg.getAsTemplate().print(s, Policy);
+      break;
     }
       
     case TemplateArgument::Integral:

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86992&r1=86991&r2=86992&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Nov 12 10:20:59 2009
@@ -2621,10 +2621,45 @@
                              TemplateArgument &Converted);
   bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, 
                              const TemplateArgumentLoc &Arg);
+  
+  /// \brief Enumeration describing how template parameter lists are compared
+  /// for equality.
+  enum TemplateParameterListEqualKind {
+    /// \brief We are matching the template parameter lists of two templates
+    /// that might be redeclarations.
+    ///
+    /// \code
+    /// template<typename T> struct X;
+    /// template<typename T> struct X;
+    /// \endcode
+    TPL_TemplateMatch,
+    
+    /// \brief We are matching the template parameter lists of two template
+    /// template parameters as part of matching the template parameter lists
+    /// of two templates that might be redeclarations.
+    ///
+    /// \code
+    /// template<template<int I> class TT> struct X;
+    /// template<template<int Value> class Other> struct X;
+    /// \endcode
+    TPL_TemplateTemplateParmMatch,
+    
+    /// \brief We are matching the template parameter lists of a template
+    /// template argument against the template parameter lists of a template
+    /// template parameter.
+    ///
+    /// \code
+    /// template<template<int Value> class Metafun> struct X;
+    /// template<int Value> struct integer_c;
+    /// X<integer_c> xic;
+    /// \endcode
+    TPL_TemplateTemplateArgumentMatch
+  };
+  
   bool TemplateParameterListsAreEqual(TemplateParameterList *New,
                                       TemplateParameterList *Old,
                                       bool Complain,
-                                      bool IsTemplateTemplateParm = false,
+                                      TemplateParameterListEqualKind Kind,
                                       SourceLocation TemplateArgLoc
                                         = SourceLocation());
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=86992&r1=86991&r2=86992&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Nov 12 10:20:59 2009
@@ -350,7 +350,7 @@
     if (NewTemplate &&
         (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
                                          OldTemplate->getTemplateParameters(),
-                                         false, false, SourceLocation()) ||
+                                         false, TPL_TemplateMatch) ||
          OldType->getResultType() != NewType->getResultType()))
       return true;
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=86992&r1=86991&r2=86992&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Nov 12 10:20:59 2009
@@ -706,7 +706,8 @@
     // Ensure that the template parameter lists are compatible.
     if (!TemplateParameterListsAreEqual(TemplateParams,
                                    PrevClassTemplate->getTemplateParameters(),
-                                        /*Complain=*/true))
+                                        /*Complain=*/true,
+                                        TPL_TemplateMatch))
       return true;
 
     // C++ [temp.class]p4:
@@ -1124,7 +1125,7 @@
         if (ExpectedTemplateParams)
           TemplateParameterListsAreEqual(ParamLists[Idx],
                                          ExpectedTemplateParams,
-                                         true);
+                                         true, TPL_TemplateMatch);
       }
     } else if (ParamLists[Idx]->size() > 0)
       Diag(ParamLists[Idx]->getTemplateLoc(),
@@ -2511,7 +2512,8 @@
 
   return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
                                          Param->getTemplateParameters(),
-                                         true, true,
+                                         true, 
+                                         TPL_TemplateTemplateArgumentMatch,
                                          Arg.getLocation());
 }
 
@@ -2528,9 +2530,7 @@
 /// \param Complain  If true, this routine will produce a diagnostic if
 /// the template parameter lists are not equivalent.
 ///
-/// \param IsTemplateTemplateParm  If true, this routine is being
-/// called to compare the template parameter lists of a template
-/// template parameter.
+/// \param Kind describes how we are to match the template parameter lists.
 ///
 /// \param TemplateArgLoc If this source location is valid, then we
 /// are actually checking the template parameter list of a template
@@ -2544,7 +2544,7 @@
 Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
                                      TemplateParameterList *Old,
                                      bool Complain,
-                                     bool IsTemplateTemplateParm,
+                                     TemplateParameterListEqualKind Kind,
                                      SourceLocation TemplateArgLoc) {
   if (Old->size() != New->size()) {
     if (Complain) {
@@ -2555,10 +2555,10 @@
       }
       Diag(New->getTemplateLoc(), NextDiag)
           << (New->size() > Old->size())
-          << IsTemplateTemplateParm
+          << (Kind != TPL_TemplateMatch)
           << SourceRange(New->getTemplateLoc(), New->getRAngleLoc());
       Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
-        << IsTemplateTemplateParm
+        << (Kind != TPL_TemplateMatch)
         << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
     }
 
@@ -2576,9 +2576,9 @@
           NextDiag = diag::note_template_param_different_kind;
         }
         Diag((*NewParm)->getLocation(), NextDiag)
-          << IsTemplateTemplateParm;
+          << (Kind != TPL_TemplateMatch);
         Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
-          << IsTemplateTemplateParm;
+          << (Kind != TPL_TemplateMatch);
       }
       return false;
     }
@@ -2591,6 +2591,16 @@
       // The types of non-type template parameters must agree.
       NonTypeTemplateParmDecl *NewNTTP
         = cast<NonTypeTemplateParmDecl>(*NewParm);
+      
+      // If we are matching a template template argument to a template
+      // template parameter and one of the non-type template parameter types
+      // is dependent, then we must wait until template instantiation time
+      // to actually compare the arguments.
+      if (Kind == TPL_TemplateTemplateArgumentMatch &&
+          (OldNTTP->getType()->isDependentType() ||
+           NewNTTP->getType()->isDependentType()))
+        continue;
+      
       if (Context.getCanonicalType(OldNTTP->getType()) !=
             Context.getCanonicalType(NewNTTP->getType())) {
         if (Complain) {
@@ -2602,7 +2612,7 @@
           }
           Diag(NewNTTP->getLocation(), NextDiag)
             << NewNTTP->getType()
-            << IsTemplateTemplateParm;
+            << (Kind != TPL_TemplateMatch);
           Diag(OldNTTP->getLocation(),
                diag::note_template_nontype_parm_prev_declaration)
             << OldNTTP->getType();
@@ -2621,7 +2631,7 @@
       if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
                                           OldTTP->getTemplateParameters(),
                                           Complain,
-                                          /*IsTemplateTemplateParm=*/true,
+              (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
                                           TemplateArgLoc))
         return false;
     }

Modified: cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp?rev=86992&r1=86991&r2=86992&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-template-template-parm.cpp Thu Nov 12 10:20:59 2009
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<template<typename T> class MetaFun, typename Value>
 struct apply {
   typedef typename MetaFun<Value>::type type;
@@ -31,3 +30,17 @@
 X0<int, B> x0b1;
 X0<float, B> x0b2; // expected-note{{while substituting}}
 X0<long, B> x0b3; // expected-error{{template template argument has different template parameters}}
+
+template<template<int V> class TT> // expected-note{{parameter with type 'int'}}
+struct X1 { };
+
+template<typename T, template<T V> class TT>
+struct X2 {
+  X1<TT> x1; // expected-error{{has different template parameters}}
+};
+
+template<int V> struct X3i { };
+template<long V> struct X3l { }; // expected-note{{different type 'long'}}
+
+X2<int, X3i> x2okay;
+X2<long, X3l> x2bad; // expected-note{{instantiation}}





More information about the cfe-commits mailing list