diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-18 01:29:05 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-18 01:29:05 +0000 |
commit | 500d729e85028944355a119f9823ac99fa5ddcab (patch) | |
tree | 4c61dbac98164c678af990611d511df3c6915afc /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 5912597f3a01f6b5a6f6c5543317d209dbbb0a87 (diff) |
PR13386: When matching up parameters between a function template declaration
and a function template instantiation, if there's a parameter pack in the
declaration and one at the same place in the instantiation, don't assume that
the pack wasn't expanded -- it may have expanded to nothing. Instead, go ahead
and check whether the parameter pack was expandable. We can do this as a
side-effect of the work we'd need to do anyway, to find how many parameters
were produced.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160416 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 46 |
1 files changed, 22 insertions, 24 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index a2efa597c2..5a10dfbccd 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2176,35 +2176,31 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL); assert(NewProtoLoc && "Missing prototype?"); - unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs(); + unsigned NewIdx = 0; for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs(); OldIdx != NumOldParams; ++OldIdx) { ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); - if (!OldParam->isParameterPack() || - // FIXME: Is this right? OldParam could expand to an empty parameter - // pack and the next parameter could be an unexpanded parameter pack - (NewIdx < NumNewParams && - NewProtoLoc->getArg(NewIdx)->isParameterPack())) { + LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; + + llvm::Optional<unsigned> NumArgumentsInExpansion; + if (OldParam->isParameterPack()) + NumArgumentsInExpansion = + SemaRef.getNumArgumentsInExpansion(OldParam->getType(), + TemplateArgs); + if (!NumArgumentsInExpansion) { // 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); - unsigned NumArgumentsInExpansion - = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), - TemplateArgs); - while (NumArgumentsInExpansion--) { - ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); - Params.push_back(NewParam); - SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam, - NewParam); + Scope->InstantiatedLocal(OldParam, NewParam); + } else { + // Parameter pack expansion: make the instantiation an argument pack. + Scope->MakeInstantiatedLocalArgPack(OldParam); + for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) { + ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + Params.push_back(NewParam); + Scope->InstantiatedLocalPackArg(OldParam, NewParam); + } } } } @@ -2248,9 +2244,11 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); - unsigned NumArgumentsInExpansion + llvm::Optional<unsigned> NumArgumentsInExpansion = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); - for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) { + assert(NumArgumentsInExpansion && + "should only be called when all template arguments are known"); + for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); |