Skip to content

Commit 327865d

Browse files
author
Anders Carlsson
committed
A parameter pack must always come last in a class template.
llvm-svn: 73269
1 parent 508caae commit 327865d

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,8 @@ def err_template_kw_refers_to_function_template : Error<
836836
// C++0x Variadic Templates
837837
def err_template_param_pack_default_arg : Error<
838838
"template parameter pack cannot have a default argument">;
839+
def err_template_param_pack_must_be_last_template_parameter : Error<
840+
"template parameter pack must be the last template parameter">;
839841

840842
def err_unexpected_typedef : Error<
841843
"unexpected type name %0: expected expression">;

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
591591
bool SawDefaultArgument = false;
592592
SourceLocation PreviousDefaultArgLoc;
593593

594+
bool SawParameterPack = false;
595+
SourceLocation ParameterPackLoc;
596+
594597
// Dummy initialization to avoid warnings.
595598
TemplateParameterList::iterator OldParam = NewParams->end();
596599
if (OldParams)
@@ -607,13 +610,27 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
607610
// Variables used to diagnose missing default arguments
608611
bool MissingDefaultArg = false;
609612

613+
// C++0x [temp.param]p11:
614+
// If a template parameter of a class template is a template parameter pack,
615+
// it must be the last template parameter.
616+
if (SawParameterPack) {
617+
Diag(ParameterPackLoc,
618+
diag::err_template_param_pack_must_be_last_template_parameter);
619+
Invalid = true;
620+
}
621+
610622
// Merge default arguments for template type parameters.
611623
if (TemplateTypeParmDecl *NewTypeParm
612624
= dyn_cast<TemplateTypeParmDecl>(*NewParam)) {
613625
TemplateTypeParmDecl *OldTypeParm
614626
= OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0;
615627

616-
if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
628+
if (NewTypeParm->isParameterPack()) {
629+
assert(!NewTypeParm->hasDefaultArgument() &&
630+
"Parameter packs can't have a default argument!");
631+
SawParameterPack = true;
632+
ParameterPackLoc = NewTypeParm->getLocation();
633+
} else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
617634
NewTypeParm->hasDefaultArgument()) {
618635
OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
619636
NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
22

3-
template<typename... Args = int> struct S { }; // expected-error{{template parameter pack cannot have a default argument}}
3+
template<typename ... Args = int> struct S1 { }; // expected-error{{template parameter pack cannot have a default argument}}
4+
template<typename ... Args, typename T> struct S2 { }; // expected-error{{template parameter pack must be the last template parameter}}

0 commit comments

Comments
 (0)