[cfe-commits] r122251 - in /cfe/trunk: lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.variadic/p1.cpp
Douglas Gregor
dgregor at apple.com
Mon Dec 20 08:57:52 PST 2010
Author: dgregor
Date: Mon Dec 20 10:57:52 2010
New Revision: 122251
URL: http://llvm.org/viewvc/llvm-project?rev=122251&view=rev
Log:
When checking a template argument list against a template containing
a parameter pack, check the parameter pack against each of the
template arguments it corresponds to, then pack the converted
arguments into a template argument pack. Allows us to use variadic
class templates so long as instantiation isn't required, e.g.,
template<typename... Types> struct Tuple;
Tuple<int, float> *t2;
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p1.cpp
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122251&r1=122250&r2=122251&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Dec 20 10:57:52 2010
@@ -2377,30 +2377,40 @@
// a template-id shall match the type and form specified for the
// corresponding parameter declared by the template in its
// template-parameter-list.
+ llvm::SmallVector<TemplateArgument, 2> ArgumentPack;
+ TemplateParameterList::iterator Param = Params->begin(),
+ ParamEnd = Params->end();
unsigned ArgIdx = 0;
- for (TemplateParameterList::iterator Param = Params->begin(),
- ParamEnd = Params->end();
- Param != ParamEnd; ++Param, ++ArgIdx) {
+ while (Param != ParamEnd) {
if (ArgIdx > NumArgs && PartialTemplateArgs)
break;
- // If we have a template parameter pack, check every remaining template
- // argument against that template parameter pack.
- // FIXME: Variadic templates are unimplemented
- if ((*Param)->isTemplateParameterPack()) {
- Diag(TemplateLoc, diag::err_variadic_templates_unsupported);
- return true;
- }
-
if (ArgIdx < NumArgs) {
// Check the template argument we were given.
if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template,
TemplateLoc, RAngleLoc, Converted))
return true;
+ if ((*Param)->isTemplateParameterPack()) {
+ // The template parameter was a template parameter pack, so take the
+ // deduced argument and place it on the argument pack. Note that we
+ // stay on the same template parameter so that we can deduce more
+ // arguments.
+ ArgumentPack.push_back(Converted.back());
+ Converted.pop_back();
+ } else {
+ // Move to the next template parameter.
+ ++Param;
+ }
+ ++ArgIdx;
continue;
}
+ // If we have a template parameter pack with no more corresponding
+ // arguments, just break out now and we'll fill in the argument pack below.
+ if ((*Param)->isTemplateParameterPack())
+ break;
+
// We have a default template argument that we will use.
TemplateArgumentLoc Arg;
@@ -2475,8 +2485,31 @@
if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc,
RAngleLoc, Converted))
return true;
+
+ // Move to the next template parameter and argument.
+ ++Param;
+ ++ArgIdx;
}
-
+
+ // Form argument packs for each of the parameter packs remaining.
+ while (Param != ParamEnd) {
+ if ((*Param)->isTemplateParameterPack()) {
+ // The parameter pack takes the contents of the current argument pack,
+ // which we built up earlier.
+ if (ArgumentPack.empty()) {
+ Converted.push_back(TemplateArgument(0, 0));
+ } else {
+ TemplateArgument *PackedArgs
+ = new (Context) TemplateArgument [ArgumentPack.size()];
+ std::copy(ArgumentPack.begin(), ArgumentPack.end(), PackedArgs);
+ Converted.push_back(TemplateArgument(PackedArgs, ArgumentPack.size()));
+ ArgumentPack.clear();
+ }
+ }
+
+ ++Param;
+ }
+
return Invalid;
}
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p1.cpp?rev=122251&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p1.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p1.cpp Mon Dec 20 10:57:52 2010
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<class ...Types> struct Tuple;
+
+Tuple<> *t0;
+Tuple<int> *t1;
+Tuple<int, char> *t2a;
+Tuple<int, float> *t2b = t2a; // expected-error{{cannot initialize a variable of type 'Tuple<int, float> *' with an lvalue of type 'Tuple<int, char> *'}}
+Tuple<int, float, double> *t3;
More information about the cfe-commits
mailing list