From 0ceffb51b28b09db67404058c642dcb1f877f6e8 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 13 Jun 2009 02:08:00 +0000 Subject: [PATCH] More work on type parameter packs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73281 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclTemplate.h | 5 ++-- lib/AST/DeclTemplate.cpp | 4 ++- lib/Sema/SemaTemplate.cpp | 27 ++++++++++++++++--- .../variadic-class-template-2.cpp | 19 +++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 test/SemaTemplate/variadic-class-template-2.cpp diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index ca4758031d..4363dda5c2 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -87,7 +87,7 @@ public: /// \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; } @@ -610,7 +610,7 @@ public: 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(); } @@ -770,6 +770,7 @@ public: 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); } diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9526b48468..5b1bf9b3af 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -50,7 +50,9 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { ParamBegin = const_cast(this)->begin(); while (Param != ParamBegin) { --Param; - if (!(isa(*Param) && + + if (!(*Param)->isTemplateParameterPack() && + !(isa(*Param) && cast(*Param)->hasDefaultArgument()) && !(isa(*Param) && cast(*Param)->hasDefaultArgument()) && diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f20bcd95ca..00d8c769bd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1016,7 +1016,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, 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 @@ -1050,6 +1053,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Retrieve the default template argument from the template // parameter. if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { + if (TTP->isParameterPack()) { + // We have an empty parameter pack. + Converted.BeginParameterPack(); + Converted.EndParameterPack(); + break; + } + if (!TTP->hasDefaultArgument()) break; @@ -1112,8 +1122,19 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (TemplateTypeParmDecl *TTP = dyn_cast(*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(*Param)) { // Check non-type template parameters. diff --git a/test/SemaTemplate/variadic-class-template-2.cpp b/test/SemaTemplate/variadic-class-template-2.cpp new file mode 100644 index 0000000000..eadea901c7 --- /dev/null +++ b/test/SemaTemplate/variadic-class-template-2.cpp @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +// Type parameters packs +template struct TS1 {}; // expected-note{{template parameter is declared here}} +template struct TS1<>; +template struct TS1; +template struct TS1; +template struct TS1; // expected-error{{template argument for template type parameter must be a type}} + +template struct TS2 {}; // expected-note{{template is declared here}} +template struct TS2<>; // expected-error{{too few template arguments for class template 'TS2'}} +template struct TS2; +template struct TS2; + +template struct TS3 {}; // expected-note{{template parameter is declared here}} +template struct TS3<>; // expected-note{{previous explicit instantiation is here}} +template struct TS3; // expected-error{{duplicate explicit instantiation of 'TS3<>'}} +template struct TS3; +template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}} -- 2.50.1