[cfe-commits] r122774 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp

Douglas Gregor dgregor at apple.com
Mon Jan 3 13:13:47 PST 2011


Author: dgregor
Date: Mon Jan  3 15:13:47 2011
New Revision: 122774

URL: http://llvm.org/viewvc/llvm-project?rev=122774&view=rev
Log:
Unwrap template argument packs when checking the template arguments of
a class template partial specialiation, and look through pack
expansions when checking the conditions of C++0x [temp.class.spec]p8.

Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122774&r1=122773&r2=122774&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan  3 15:13:47 2011
@@ -2910,10 +2910,6 @@
                                               bool EnteringContext,
                                               TemplateTy &Template);
 
-  bool CheckClassTemplatePartialSpecializationArgs(
-                                        TemplateParameterList *TemplateParams,
-                        llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs);
-
   DeclResult
   ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK,
                                    SourceLocation KWLoc,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122774&r1=122773&r2=122774&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jan  3 15:13:47 2011
@@ -3915,34 +3915,31 @@
   
   return false;
 }
-                                             
-/// \brief Check the non-type template arguments of a class template
-/// partial specialization according to C++ [temp.class.spec]p9.
-///
-/// \param TemplateParams the template parameters of the primary class
-/// template.
-///
-/// \param TemplateArg the template arguments of the class template
-/// partial specialization.
-///
-/// \returns true if there was an error, false otherwise.
-bool Sema::CheckClassTemplatePartialSpecializationArgs(
-                                        TemplateParameterList *TemplateParams,
-                       llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) {
-  const TemplateArgument *ArgList = TemplateArgs.data();
-
-  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
-    NonTypeTemplateParmDecl *Param
-      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
-    if (!Param)
+                     
+/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs
+/// that checks non-type template partial specialization arguments.
+static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S,
+                                                NonTypeTemplateParmDecl *Param,
+                                                  const TemplateArgument *Args,
+                                                        unsigned NumArgs) {
+  for (unsigned I = 0; I != NumArgs; ++I) {
+    if (Args[I].getKind() == TemplateArgument::Pack) {
+      if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param,
+                                                           Args[I].pack_begin(), 
+                                                           Args[I].pack_size()))
+        return true;
+      
       continue;
-
-    Expr *ArgExpr = ArgList[I].getAsExpr();
+    }
+      
+    Expr *ArgExpr = Args[I].getAsExpr();
     if (!ArgExpr) {
       continue;
     }
 
-    // FIXME: Variadic templates. Unwrap argument packs.
+    // We can have a pack expansion of any of the above.
+    if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
+      ArgExpr = Expansion->getPattern();
     
     // C++ [temp.class.spec]p8:
     //   A non-type argument is non-specialized if it is the name of a
@@ -3964,24 +3961,53 @@
     //        specialization except when the argument expression is a
     //        simple identifier.
     if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) {
-      Diag(ArgExpr->getLocStart(),
+      S.Diag(ArgExpr->getLocStart(),
            diag::err_dependent_non_type_arg_in_partial_spec)
         << ArgExpr->getSourceRange();
       return true;
     }
-
+    
     //     -- The type of a template parameter corresponding to a
     //        specialized non-type argument shall not be dependent on a
     //        parameter of the specialization.
     if (Param->getType()->isDependentType()) {
-      Diag(ArgExpr->getLocStart(),
+      S.Diag(ArgExpr->getLocStart(),
            diag::err_dependent_typed_non_type_arg_in_partial_spec)
         << Param->getType()
         << ArgExpr->getSourceRange();
-      Diag(Param->getLocation(), diag::note_template_param_here);
+      S.Diag(Param->getLocation(), diag::note_template_param_here);
       return true;
     }
   }
+  
+  return false;
+}
+                                                        
+/// \brief Check the non-type template arguments of a class template
+/// partial specialization according to C++ [temp.class.spec]p9.
+///
+/// \param TemplateParams the template parameters of the primary class
+/// template.
+///
+/// \param TemplateArg the template arguments of the class template
+/// partial specialization.
+///
+/// \returns true if there was an error, false otherwise.
+static bool CheckClassTemplatePartialSpecializationArgs(Sema &S,
+                                        TemplateParameterList *TemplateParams,
+                       llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) {
+  const TemplateArgument *ArgList = TemplateArgs.data();
+
+  for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
+    NonTypeTemplateParmDecl *Param
+      = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I));
+    if (!Param)
+      continue;
+
+    if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, 
+                                                           &ArgList[I], 1))
+      return true;
+  }
 
   return false;
 }
@@ -4145,7 +4171,7 @@
   // Find the class template (partial) specialization declaration that
   // corresponds to these arguments.
   if (isPartialSpecialization) {
-    if (CheckClassTemplatePartialSpecializationArgs(
+    if (CheckClassTemplatePartialSpecializationArgs(*this,
                                          ClassTemplate->getTemplateParameters(),
                                          Converted))
       return true;

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp?rev=122774&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p8-0x.cpp Mon Jan  3 15:13:47 2011
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<int ...Values> struct X1;
+
+template<int ...Values> 
+struct X1<0, Values+1 ...>; // expected-error{{non-type template argument depends on a template parameter of the partial specialization}}
+
+





More information about the cfe-commits mailing list