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/SemaTemplateInstantiate.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/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c4f91f9ff6..71ccb06212 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -617,6 +617,10 @@ namespace { NumExpansions); } + void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { + SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack); + } + /// \brief Transform the given declaration by instantiating a reference to /// this declaration. Decl *TransformDecl(SourceLocation Loc, Decl *D); @@ -1154,12 +1158,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; - bool WasParameterPack = false; - bool IsParameterPack = false; TypeLoc OldTL = OldDI->getTypeLoc(); if (isa<PackExpansionTypeLoc>(OldTL)) { PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL); - WasParameterPack = true; // We have a function parameter pack. Substitute into the pattern of the // expansion. @@ -1173,7 +1174,6 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // our function parameter is still a function parameter pack. // Therefore, make its type a pack expansion type. NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc()); - IsParameterPack = true; } } else { NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), @@ -1211,8 +1211,13 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, // FIXME: When OldParm is a parameter pack and NewParm is not a parameter // pack, we actually have a set of instantiated locations. Maintain this set! - if (!WasParameterPack || IsParameterPack) + if (OldParm->isParameterPack() && !NewParm->isParameterPack()) { + // Add the new parameter to + CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm); + } else { + // Introduce an Old -> New mapping CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm); + } // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext // can be anything, is this right ? @@ -1227,7 +1232,8 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, bool Sema::SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, const MultiLevelTemplateArgumentList &TemplateArgs, - llvm::SmallVectorImpl<QualType> &ParamTypes) { + llvm::SmallVectorImpl<QualType> &ParamTypes, + llvm::SmallVectorImpl<ParmVarDecl *> *OutParams) { assert(!ActiveTemplateInstantiations.empty() && "Cannot perform an instantiation without some context on the " "instantiation stack"); @@ -1235,7 +1241,7 @@ bool Sema::SubstParmTypes(SourceLocation Loc, TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, DeclarationName()); return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0, - ParamTypes, 0); + ParamTypes, OutParams); } /// \brief Perform substitution on the base class specifiers of the @@ -1899,15 +1905,27 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, } Decl *LocalInstantiationScope::getInstantiationOf(const Decl *D) { + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found= findInstantiationOf(D); + if (!Found) + return 0; + + if (Found->is<Decl *>()) + return Found->get<Decl *>(); + + return (*Found->get<DeclArgumentPack *>())[ + SemaRef.ArgumentPackSubstitutionIndex]; +} + +llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> * +LocalInstantiationScope::findInstantiationOf(const Decl *D) { for (LocalInstantiationScope *Current = this; Current; Current = Current->Outer) { // Check if we found something within this scope. const Decl *CheckD = D; do { - llvm::DenseMap<const Decl *, Decl *>::iterator Found - = Current->LocalDecls.find(CheckD); + LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD); if (Found != Current->LocalDecls.end()) - return Found->second; + return &Found->second; // If this is a tag declaration, it's possible that we need to look for // a previous declaration. @@ -1928,7 +1946,23 @@ Decl *LocalInstantiationScope::getInstantiationOf(const Decl *D) { } void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) { - Decl *&Stored = LocalDecls[D]; - assert((!Stored || Stored == Inst)&& "Already instantiated this local"); + llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; + assert((Stored.isNull() || + (Stored.get<Decl *>() == Inst)) && "Already instantiated this local"); Stored = Inst; } + +void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, + Decl *Inst) { + DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>(); + Pack->push_back(Inst); +} + +void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) { + llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; + assert(Stored.isNull() && "Already instantiated this local"); + DeclArgumentPack *Pack = new DeclArgumentPack; + Stored = Pack; + ArgumentPacks.push_back(Pack); +} + |