/// \btief Returns the minimum number of arguments needed to form a
/// template specialization. This may be fewer than the number of
/// template parameters, if some of the parameters have default
- /// arguments.
+ /// arguments or if there is a parameter pack.
unsigned getMinRequiredArguments() const;
SourceLocation getTemplateLoc() const { return TemplateLoc; }
assert(!isAddingFromParameterPack() &&
"Size is not valid when adding from a parameter pack");
- return Args.size();
+ return Indices.size() / 2;
}
size_t flatSize() const { return Args.size(); }
static void
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
+ ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
TemplateArgs[Arg].Profile(ID);
}
ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
while (Param != ParamBegin) {
--Param;
- if (!(isa<TemplateTypeParmDecl>(*Param) &&
+
+ if (!(*Param)->isTemplateParameterPack() &&
+ !(isa<TemplateTypeParmDecl>(*Param) &&
cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
!(isa<NonTypeTemplateParmDecl>(*Param) &&
cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
unsigned NumArgs = NumTemplateArgs;
bool Invalid = false;
- if (NumArgs > NumParams ||
+ bool HasParameterPack =
+ NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
+
+ if ((NumArgs > NumParams && !HasParameterPack) ||
NumArgs < Params->getMinRequiredArguments()) {
// FIXME: point at either the first arg beyond what we can handle,
// or the '>', depending on whether we have too many or too few
// Retrieve the default template argument from the template
// parameter.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
+ if (TTP->isParameterPack()) {
+ // We have an empty parameter pack.
+ Converted.BeginParameterPack();
+ Converted.EndParameterPack();
+ break;
+ }
+
if (!TTP->hasDefaultArgument())
break;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
- if (CheckTemplateTypeArgument(TTP, Arg, Converted))
- Invalid = true;
+ if (TTP->isParameterPack()) {
+ Converted.BeginParameterPack();
+ // Check all the remaining arguments (if any).
+ for (; ArgIdx < NumArgs; ++ArgIdx) {
+ if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
+ Invalid = true;
+ }
+
+ Converted.EndParameterPack();
+ } else {
+ if (CheckTemplateTypeArgument(TTP, Arg, Converted))
+ Invalid = true;
+ }
} else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
// Check non-type template parameters.
--- /dev/null
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+// Type parameters packs
+template <typename ...> struct TS1 {}; // expected-note{{template parameter is declared here}}
+template struct TS1<>;
+template struct TS1<int>;
+template struct TS1<int, int>;
+template struct TS1<int, 10>; // expected-error{{template argument for template type parameter must be a type}}
+
+template <typename, typename ...> struct TS2 {}; // expected-note{{template is declared here}}
+template struct TS2<>; // expected-error{{too few template arguments for class template 'TS2'}}
+template struct TS2<int>;
+template struct TS2<int, int>;
+
+template <typename = int, typename ...> struct TS3 {}; // expected-note{{template parameter is declared here}}
+template struct TS3<>; // expected-note{{previous explicit instantiation is here}}
+template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3<>'}}
+template struct TS3<int, int>;
+template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}}