diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-07 16:43:16 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-07 16:43:16 +0000 |
commit | 12c9c00024a01819e3a70ef6d951d32efaeb9312 (patch) | |
tree | 0c6499b83aab17269756d4e65041d29374506256 /lib/Sema/SemaTemplateVariadic.cpp | |
parent | 170464b7c0a2c0c86f2821f14a46f0d540cb5e94 (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.cpp | 58 |
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. |