Implement C++0x [temp.param]p11 for non-type and template template

parameter packs. Also, the "no template parameters after a template
parameter pack" rule only applies to primary class templates.

llvm-svn: 122877
This commit is contained in:
Douglas Gregor 2011-01-05 16:19:19 +00:00
parent 6a78995369
commit 0018cdc105
2 changed files with 65 additions and 5 deletions

View File

@ -1144,9 +1144,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
bool MissingDefaultArg = false;
// C++0x [temp.param]p11:
// If a template parameter of a class template is a template parameter pack,
// it must be the last template parameter.
if (SawParameterPack) {
// If a template parameter of a primary class template is a template
// parameter pack, it shall be the last template parameter.
if (SawParameterPack && TPC == TPC_ClassTemplate) {
Diag(ParameterPackLoc,
diag::err_template_param_pack_must_be_last_template_parameter);
Invalid = true;
@ -1211,7 +1211,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for non-type template parameters
NonTypeTemplateParmDecl *OldNonTypeParm
= OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0;
if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
if (NewNonTypeParm->isParameterPack()) {
assert(!NewNonTypeParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
ParameterPackLoc = NewNonTypeParm->getLocation();
} else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() &&
NewNonTypeParm->hasDefaultArgument()) {
OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc();
NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc();
@ -1254,7 +1259,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
// Merge default arguments for template template parameters
TemplateTemplateParmDecl *OldTemplateParm
= OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
if (NewTemplateParm->isParameterPack()) {
assert(!NewTemplateParm->hasDefaultArgument() &&
"Parameter packs can't have a default argument!");
SawParameterPack = true;
ParameterPackLoc = NewTemplateParm->getLocation();
} else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
NewTemplateParm->hasDefaultArgument()) {
OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();

View File

@ -0,0 +1,50 @@
// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
// If a template-parameter of a class template has a default
// template-argument, each subsequent template-parameter shall either
// have a default template-argument supplied or be a template
// parameter pack.
template<typename> struct vector;
template<typename T = int, typename ...Types> struct X2t;
template<int V = 0, int ...Values> struct X2nt;
template<template<class> class M = vector, template<class> class... Metas>
struct X2tt;
// If a template-parameter of a primary class template is a template
// parameter pack, it shall be the last template-parameter .
template<typename ...Types, // expected-error{{template parameter pack must be the last template parameter}}
int After>
struct X0t;
template<int ...Values, // expected-error{{template parameter pack must be the last template parameter}}
int After>
struct X0nt;
template<template<typename> class ...Templates, // expected-error{{template parameter pack must be the last template parameter}}
int After>
struct X0tt;
// [ Note: These are not requirements for function templates or class
// template partial specializations because template arguments can be
// deduced (14.8.2). -- end note]
template<typename... Types> struct X1t;
template<typename ...Types, typename T> struct X1t<T, Types...> { };
template<int... Values> struct X1nt;
template<int ...Values, int V> struct X1nt<V, Values...> { };
// FIXME: Need template template argument packs!
// template<template<int> class... Meta> struct X1tt;
// template<template<int> class... Meta, template<int> class M>
// struct X1tt<M, Meta...> { };
template<typename ...Types, typename T>
void f1t(X1t<T, Types...>);
template<int ...Values, int V>
void f1nt(X1nt<V, Values...>);
// FIXME: Need template template argument packs!
// template<template<int> class... Meta, template<int> class M>
// void f1tt(X1tt<M, Meta...>);