[cfe-commits] r123343 - /cfe/trunk/lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 12 15:45:45 PST 2011


Author: dgregor
Date: Wed Jan 12 17:45:44 2011
New Revision: 123343

URL: http://llvm.org/viewvc/llvm-project?rev=123343&view=rev
Log:
Refactor and simplify Sema::TemplateParameterListsAreEqual. We had a
bunch of duplicated checks for parameter pack/non-pack mismatches.

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=123343&r1=123342&r2=123343&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jan 12 17:45:44 2011
@@ -3628,6 +3628,103 @@
   return Owned(E);
 }
 
+/// \brief Match two template parameters within template parameter lists.
+static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
+                                       bool Complain,
+                                     Sema::TemplateParameterListEqualKind Kind,
+                                       SourceLocation TemplateArgLoc) {
+  // Check the actual kind (type, non-type, template).
+  if (Old->getKind() != New->getKind()) {
+    if (Complain) {
+      unsigned NextDiag = diag::err_template_param_different_kind;
+      if (TemplateArgLoc.isValid()) {
+        S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+        NextDiag = diag::note_template_param_different_kind;
+      }
+      S.Diag(New->getLocation(), NextDiag)
+        << (Kind != Sema::TPL_TemplateMatch);
+      S.Diag(Old->getLocation(), diag::note_template_prev_declaration)
+        << (Kind != Sema::TPL_TemplateMatch);
+    }
+    
+    return false;
+  }
+
+  // Check that both are parameter packs are neither are parameter packs. 
+  if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) {
+    if (Complain) {
+      unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
+      if (TemplateArgLoc.isValid()) {
+        S.Diag(TemplateArgLoc,
+             diag::err_template_arg_template_params_mismatch);
+        NextDiag = diag::note_template_parameter_pack_non_pack;
+      }
+      
+      unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0
+                      : isa<NonTypeTemplateParmDecl>(New)? 1
+                      : 2;
+      S.Diag(New->getLocation(), NextDiag)
+        << ParamKind << New->isParameterPack();
+      S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here)
+        << ParamKind << Old->isParameterPack();
+    }
+        
+    return false;
+  }
+  
+  // For non-type template parameters, check the type of the parameter.
+  if (NonTypeTemplateParmDecl *OldNTTP
+                                    = dyn_cast<NonTypeTemplateParmDecl>(Old)) {
+    NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New);
+    
+    // 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 == Sema::TPL_TemplateTemplateArgumentMatch &&
+        (OldNTTP->getType()->isDependentType() ||
+         NewNTTP->getType()->isDependentType()))
+      return true;
+    
+    if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) {
+      if (Complain) {
+        unsigned NextDiag = diag::err_template_nontype_parm_different_type;
+        if (TemplateArgLoc.isValid()) {
+          S.Diag(TemplateArgLoc, 
+                 diag::err_template_arg_template_params_mismatch);
+          NextDiag = diag::note_template_nontype_parm_different_type;
+        }
+        S.Diag(NewNTTP->getLocation(), NextDiag)
+          << NewNTTP->getType()
+          << (Kind != Sema::TPL_TemplateMatch);
+        S.Diag(OldNTTP->getLocation(),
+               diag::note_template_nontype_parm_prev_declaration)
+          << OldNTTP->getType();
+      }
+      
+      return false;
+    }
+    
+    return true;
+  }
+  
+  // For template template parameters, check the template parameter types.
+  // The template parameter lists of template template
+  // parameters must agree.
+  if (TemplateTemplateParmDecl *OldTTP
+                                    = dyn_cast<TemplateTemplateParmDecl>(Old)) {
+    TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New);  
+    return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
+                                            OldTTP->getTemplateParameters(),
+                                            Complain,
+                                        (Kind == Sema::TPL_TemplateMatch
+                                           ? Sema::TPL_TemplateTemplateParmMatch 
+                                           : Kind),
+                                            TemplateArgLoc);
+  }
+  
+  return true;
+}
 
 /// \brief Determine whether the given template parameter lists are
 /// equivalent.
@@ -3677,142 +3774,18 @@
     return false;
   }
 
+  // C++0x [temp.arg.template]p3:
+  //   A template-argument matches a template template-parameter (call it P)
+  //   when each of the template parameters in the template-parameter-list of 
+  //   the template-argument’s corresponding class template or template alias
+  //   (call it A) matches the corresponding template parameter in the 
+  //   template-parameter-list of P.
   for (TemplateParameterList::iterator OldParm = Old->begin(),
          OldParmEnd = Old->end(), NewParm = New->begin();
        OldParm != OldParmEnd; ++OldParm, ++NewParm) {
-    if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
-      if (Complain) {
-        unsigned NextDiag = diag::err_template_param_different_kind;
-        if (TemplateArgLoc.isValid()) {
-          Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
-          NextDiag = diag::note_template_param_different_kind;
-        }
-        Diag((*NewParm)->getLocation(), NextDiag)
-          << (Kind != TPL_TemplateMatch);
-        Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
-          << (Kind != TPL_TemplateMatch);
-      }
-      return false;
-    }
-
-    if (TemplateTypeParmDecl *OldTTP
-                                  = dyn_cast<TemplateTypeParmDecl>(*OldParm)) {
-      // Template type parameters are equivalent if either both are template
-      // type parameter packs or neither are (since we know we're at the same 
-      // index).
-      TemplateTypeParmDecl *NewTTP = cast<TemplateTypeParmDecl>(*NewParm);
-      if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) {
-        // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
-        // allow one to match a template parameter pack in the template
-        // parameter list of a template template parameter to one or more
-        // template parameters in the template parameter list of the 
-        // corresponding template template argument.        
-        if (Complain) {
-          unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
-          if (TemplateArgLoc.isValid()) {
-            Diag(TemplateArgLoc,
-                 diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_parameter_pack_non_pack;
-          }
-          Diag(NewTTP->getLocation(), NextDiag)
-            << 0 << NewTTP->isParameterPack();
-          Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
-            << 0 << OldTTP->isParameterPack();
-        }
-        return false;
-      }
-    } else if (NonTypeTemplateParmDecl *OldNTTP
-                 = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) {
-      // The types of non-type template parameters must agree.
-      NonTypeTemplateParmDecl *NewNTTP
-        = cast<NonTypeTemplateParmDecl>(*NewParm);
-      
-      if (OldNTTP->isParameterPack() != NewNTTP->isParameterPack()) {
-        // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
-        // allow one to match a template parameter pack in the template
-        // parameter list of a template template parameter to one or more
-        // template parameters in the template parameter list of the 
-        // corresponding template template argument.        
-        if (Complain) {
-          unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
-          if (TemplateArgLoc.isValid()) {
-            Diag(TemplateArgLoc,
-                 diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_parameter_pack_non_pack;
-          }
-          Diag(NewNTTP->getLocation(), NextDiag)
-            << 1 << NewNTTP->isParameterPack();
-          Diag(OldNTTP->getLocation(), diag::note_template_parameter_pack_here)
-            << 1 << OldNTTP->isParameterPack();
-        }
-        return false;
-      }
-
-      // 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) {
-          unsigned NextDiag = diag::err_template_nontype_parm_different_type;
-          if (TemplateArgLoc.isValid()) {
-            Diag(TemplateArgLoc,
-                 diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_nontype_parm_different_type;
-          }
-          Diag(NewNTTP->getLocation(), NextDiag)
-            << NewNTTP->getType()
-            << (Kind != TPL_TemplateMatch);
-          Diag(OldNTTP->getLocation(),
-               diag::note_template_nontype_parm_prev_declaration)
-            << OldNTTP->getType();
-        }
-        return false;
-      }
-    } else {
-      // The template parameter lists of template template
-      // parameters must agree.
-      assert(isa<TemplateTemplateParmDecl>(*OldParm) &&
-             "Only template template parameters handled here");
-      TemplateTemplateParmDecl *OldTTP
-        = cast<TemplateTemplateParmDecl>(*OldParm);
-      TemplateTemplateParmDecl *NewTTP
-        = cast<TemplateTemplateParmDecl>(*NewParm);
-      
-      if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) {
-        // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that
-        // allow one to match a template parameter pack in the template
-        // parameter list of a template template parameter to one or more
-        // template parameters in the template parameter list of the 
-        // corresponding template template argument.        
-        if (Complain) {
-          unsigned NextDiag = diag::err_template_parameter_pack_non_pack;
-          if (TemplateArgLoc.isValid()) {
-            Diag(TemplateArgLoc,
-                 diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_parameter_pack_non_pack;
-          }
-          Diag(NewTTP->getLocation(), NextDiag)
-            << 2 << NewTTP->isParameterPack();
-          Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here)
-            << 2 << OldTTP->isParameterPack();
-        }
-        return false;
-      }
-
-      if (!TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(),
-                                          OldTTP->getTemplateParameters(),
-                                          Complain,
-              (Kind == TPL_TemplateMatch? TPL_TemplateTemplateParmMatch : Kind),
-                                          TemplateArgLoc))
-        return false;
-    }
+    if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain,
+                                    Kind, TemplateArgLoc))
+      return false;    
   }
 
   return true;





More information about the cfe-commits mailing list