aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateVariadic.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-07 16:43:16 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-07 16:43:16 +0000
commit12c9c00024a01819e3a70ef6d951d32efaeb9312 (patch)
tree0c6499b83aab17269756d4e65041d29374506256 /lib/Sema/SemaTemplateVariadic.cpp
parent170464b7c0a2c0c86f2821f14a46f0d540cb5e94 (diff)
Implement substitution of a function parameter pack for its set of
instantiated function parameters, enabling instantiation of arbitrary pack expansions involving function parameter packs. At this point, we can now correctly compile a simple, variadic print() example: #include <iostream> #include <string> void print() {} template<typename Head, typename ...Tail> void print(const Head &head, const Tail &...tail) { std::cout << head; print(tail...); } int main() { std::string hello = "Hello"; print(hello, ", world!", " ", 2011, '\n'); } git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123000 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp58
1 files changed, 39 insertions, 19 deletions
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 3090d1532d..1928c59642 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -67,13 +67,8 @@ namespace {
/// \brief Record occurrences of (FIXME: function and) non-type template
/// parameter packs in an expression.
bool VisitDeclRefExpr(DeclRefExpr *E) {
- if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) {
- if (NTTP->isParameterPack())
- Unexpanded.push_back(std::make_pair(NTTP, E->getLocation()));
- }
-
- // FIXME: Function parameter packs.
+ if (E->getDecl()->isParameterPack())
+ Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation()));
return true;
}
@@ -440,6 +435,7 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
unsigned Depth;
unsigned Index;
IdentifierInfo *Name;
+ bool IsFunctionParameterPack = false;
if (const TemplateTypeParmType *TTP
= Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
@@ -455,26 +451,50 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
= dyn_cast<NonTypeTemplateParmDecl>(ND)) {
Depth = NTTP->getDepth();
Index = NTTP->getIndex();
- } else {
- TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ } else if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(ND)) {
Depth = TTP->getDepth();
Index = TTP->getIndex();
+ } else {
+ assert(cast<ParmVarDecl>(ND)->isParameterPack());
+ IsFunctionParameterPack = true;
}
- // FIXME: Variadic templates function parameter packs?
Name = ND->getIdentifier();
}
- // If we don't have a template argument at this depth/index, then we
- // cannot expand the pack expansion. Make a note of this, but we still
- // want to check any parameter packs we *do* have arguments for.
- if (Depth >= TemplateArgs.getNumLevels() ||
- !TemplateArgs.hasTemplateArgument(Depth, Index)) {
- ShouldExpand = false;
- continue;
+ // Determine the size of this argument pack.
+ unsigned NewPackSize;
+ if (IsFunctionParameterPack) {
+ // Figure out whether we're instantiating to an argument pack or not.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+ = CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation &&
+ Instantiation->is<DeclArgumentPack *>()) {
+ // We could expand this function parameter pack.
+ NewPackSize = Instantiation->get<DeclArgumentPack *>()->size();
+ } else {
+ // We can't expand this function parameter pack, so we can't expand
+ // the pack expansion.
+ ShouldExpand = false;
+ continue;
+ }
+ } else {
+ // If we don't have a template argument at this depth/index, then we
+ // cannot expand the pack expansion. Make a note of this, but we still
+ // want to check any parameter packs we *do* have arguments for.
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index)) {
+ ShouldExpand = false;
+ continue;
+ }
+
+ // Determine the size of the argument pack.
+ NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
- // Determine the size of the argument pack.
- unsigned NewPackSize = TemplateArgs(Depth, Index).pack_size();
if (!HaveFirstPack) {
// The is the first pack we've seen for which we have an argument.
// Record it.