aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-19 20:10:05 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-19 20:10:05 +0000
commit6952f1e4256c5b43aee5e98cea4e9b663bd1d413 (patch)
tree0b18dbc34cc3a9d14d470beaf483f1d618579c8d /lib/Sema/SemaTemplate.cpp
parent61f438ac38cb7ccd40e77861b19f34553694416f (diff)
Implement support for non-type template parameter packs whose type is
a pack expansion, e.g., the parameter pack Values in: template<typename ...Types> struct Outer { template<Types ...Values> struct Inner; }; This new implementation approach introduces the notion of an "expanded" non-type template parameter pack, for which we have already expanded the types of the parameter pack (to, say, "int*, float*", for Outer<int*, float*>) but have not yet expanded the values. Aside from creating these expanded non-type template parameter packs, this patch updates template argument checking and non-type template parameter pack instantiation to make use of the appropriate types in the parameter pack. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123845 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp51
1 files changed, 49 insertions, 2 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index f97c650d96..ad08a11f20 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2197,11 +2197,36 @@ Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template,
/// \brief Check that the given template argument corresponds to the given
/// template parameter.
+///
+/// \param Param The template parameter against which the argument will be
+/// checked.
+///
+/// \param Arg The template argument.
+///
+/// \param Template The template in which the template argument resides.
+///
+/// \param TemplateLoc The location of the template name for the template
+/// whose argument list we're matching.
+///
+/// \param RAngleLoc The location of the right angle bracket ('>') that closes
+/// the template argument list.
+///
+/// \param ArgumentPackIndex The index into the argument pack where this
+/// argument will be placed. Only valid if the parameter is a parameter pack.
+///
+/// \param Converted The checked, converted argument will be added to the
+/// end of this small vector.
+///
+/// \param CTAK Describes how we arrived at this particular template argument:
+/// explicitly written, deduced, etc.
+///
+/// \returns true on error, false otherwise.
bool Sema::CheckTemplateArgument(NamedDecl *Param,
const TemplateArgumentLoc &Arg,
NamedDecl *Template,
SourceLocation TemplateLoc,
SourceLocation RAngleLoc,
+ unsigned ArgumentPackIndex,
llvm::SmallVectorImpl<TemplateArgument> &Converted,
CheckTemplateArgumentKind CTAK) {
// Check template type parameters.
@@ -2214,6 +2239,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param,
// with the template arguments we've seen thus far. But if the
// template has a dependent context then we cannot substitute yet.
QualType NTTPType = NTTP->getType();
+ if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack())
+ NTTPType = NTTP->getExpansionType(ArgumentPackIndex);
+
if (NTTPType->isDependentType() &&
!isa<TemplateTemplateParmDecl>(Template) &&
!Template->getDeclContext()->isDependentContext()) {
@@ -2447,9 +2475,28 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
if (ArgIdx < NumArgs) {
+ // If we have an expanded parameter pack, make sure we don't have too
+ // many arguments.
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
+ if (NTTP->isExpandedParameterPack() &&
+ ArgumentPack.size() >= NTTP->getNumExpansionTypes()) {
+ Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
+ << true
+ << (isa<ClassTemplateDecl>(Template)? 0 :
+ isa<FunctionTemplateDecl>(Template)? 1 :
+ isa<TemplateTemplateParmDecl>(Template)? 2 : 3)
+ << Template;
+ Diag(Template->getLocation(), diag::note_template_decl_here)
+ << Params->getSourceRange();
+ return true;
+ }
+ }
+
// Check the template argument we were given.
if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
- TemplateLoc, RAngleLoc, Converted))
+ TemplateLoc, RAngleLoc,
+ ArgumentPack.size(), Converted))
return true;
if ((*Param)->isTemplateParameterPack()) {
@@ -2544,7 +2591,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Check the default template argument.
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
- RAngleLoc, Converted))
+ RAngleLoc, 0, Converted))
return true;
// Move to the next template parameter and argument.