aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.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/SemaTemplateInstantiateDecl.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/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp67
1 files changed, 50 insertions, 17 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 92521ae16e..2ef688b0eb 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1271,14 +1271,11 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
// synthesized in the method declaration.
if (!isa<FunctionProtoType>(T.IgnoreParens())) {
assert(!Params.size() && "Instantiating type could not yield parameters");
- for (unsigned I = 0, N = D->getNumParams(); I != N; ++I) {
- ParmVarDecl *P = SemaRef.SubstParmVarDecl(D->getParamDecl(I),
- TemplateArgs);
- if (!P)
- return 0;
-
- Params.push_back(P);
- }
+ llvm::SmallVector<QualType, 4> ParamTypes;
+ if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(),
+ D->getNumParams(), TemplateArgs, ParamTypes,
+ &Params))
+ return 0;
}
NestedNameSpecifier *Qualifier = D->getQualifier();
@@ -1904,12 +1901,31 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens();
FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL);
assert(NewProtoLoc && "Missing prototype?");
- for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i) {
- // FIXME: Variadic templates will break this.
- Params.push_back(NewProtoLoc->getArg(i));
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(
- OldProtoLoc->getArg(i),
- NewProtoLoc->getArg(i));
+ unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs();
+ for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs();
+ OldIdx != NumOldParams; ++OldIdx) {
+ ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);
+ if (!OldParam->isParameterPack() ||
+ (NewIdx < NumNewParams &&
+ NewProtoLoc->getArg(NewIdx)->isParameterPack())) {
+ // Simple case: normal parameter, or a parameter pack that's
+ // instantiated to a (still-dependent) parameter pack.
+ ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ Params.push_back(NewParam);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam,
+ NewParam);
+ continue;
+ }
+
+ // Parameter pack: make the instantiation an argument pack.
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
+ OldParam);
+ while (NewIdx < NumNewParams) {
+ ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
+ Params.push_back(NewParam);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam,
+ NewParam);
+ }
}
}
} else {
@@ -2179,11 +2195,28 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
// Introduce the instantiated function parameters into the local
// instantiation scope, and set the parameter names to those used
// in the template.
+ unsigned FParamIdx = 0;
for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
- ParmVarDecl *FunctionParam = Function->getParamDecl(I);
- FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ if (!PatternParam->isParameterPack()) {
+ // Simple case: not a parameter pack.
+ assert(FParamIdx < Function->getNumParams());
+ ParmVarDecl *FunctionParam = Function->getParamDecl(I);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ ++FParamIdx;
+ continue;
+ }
+
+ // Expand the parameter pack.
+ Scope.MakeInstantiatedLocalArgPack(PatternParam);
+ for (unsigned NumFParams = Function->getNumParams();
+ FParamIdx < NumFParams;
+ ++FParamIdx) {
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ }
}
// Enter the scope of this instantiation. We don't use