diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-07-12 23:32:39 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-07-12 23:32:39 +0000 |
| commit | c379d1a424badc74906db37c6c826e5b4a155b25 (patch) | |
| tree | c175c59ce266c7875cf1b4592bc51fb81cbee039 /clang/lib/Sema | |
| parent | 73dd5f9c08b974b41754faf410be596e306478b2 (diff) | |
| download | bcm5719-llvm-c379d1a424badc74906db37c6c826e5b4a155b25.tar.gz bcm5719-llvm-c379d1a424badc74906db37c6c826e5b4a155b25.zip | |
PR38136: improve handling of template argument deduction of non-trailing
function parameter packs.
This makes our handling of non-trailing function parameter packs
consistent between the case of deduction at the top level in a function
call and other cases where deduction encounters a non-trailing function
parameter pack.
Instead of treating a non-trailing pack and all later parameters as
being non-deduced, we treat a non-trailing pack as exactly matching
any explicitly-specified template arguments (or being an empty pack
if there are no such arguments). This corresponds to the "never deduced"
rule in [temp.deduct.call]p1, but generalized to all deduction contexts.
Non-trailing template argument packs still result in the entire
template argument list being treated as non-deduced, as specified in
[temp.deduct.type]p9.
llvm-svn: 336962
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 80 |
1 files changed, 52 insertions, 28 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 8ae22136e1e..3a480628a7e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -941,12 +941,6 @@ DeduceTemplateArguments(Sema &S, SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned TDF, bool PartialOrdering = false) { - // Fast-path check to see if we have too many/too few arguments. - if (NumParams != NumArgs && - !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && - !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1]))) - return Sema::TDK_MiscellaneousDeductionFailure; - // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type // Pi of the respective parameter-type- list of P is compared with the @@ -983,13 +977,6 @@ DeduceTemplateArguments(Sema &S, continue; } - // C++0x [temp.deduct.type]p5: - // The non-deduced contexts are: - // - A function parameter pack that does not occur at the end of the - // parameter-declaration-clause. - if (ParamIdx + 1 < NumParams) - return Sema::TDK_Success; - // C++0x [temp.deduct.type]p10: // If the parameter-declaration corresponding to Pi is a function // parameter pack, then the type of its declarator- id is compared with @@ -1000,15 +987,41 @@ DeduceTemplateArguments(Sema &S, QualType Pattern = Expansion->getPattern(); PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern); - for (; ArgIdx < NumArgs; ++ArgIdx) { - // Deduce template arguments from the pattern. - if (Sema::TemplateDeductionResult Result - = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, - Args[ArgIdx], Info, Deduced, - TDF, PartialOrdering)) - return Result; + if (ParamIdx + 1 == NumParams) { + for (; ArgIdx < NumArgs; ++ArgIdx) { + // Deduce template arguments from the pattern. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, Pattern, + Args[ArgIdx], Info, Deduced, + TDF, PartialOrdering)) + return Result; - PackScope.nextPackElement(); + PackScope.nextPackElement(); + } + } else { + // C++0x [temp.deduct.type]p5: + // The non-deduced contexts are: + // - A function parameter pack that does not occur at the end of the + // parameter-declaration-clause. + // + // FIXME: There is no wording to say what we should do in this case. We + // choose to resolve this by applying the same rule that is applied for a + // function call: that is, deduce all contained packs to their + // explicitly-specified values (or to <> if there is no such value). + // + // This is seemingly-arbitrarily different from the case of a template-id + // with a non-trailing pack-expansion in its arguments, which renders the + // entire template-argument-list a non-deduced context. + + // If the parameter type contains an explicitly-specified pack that we + // could not expand, skip the number of parameters notionally created + // by the expansion. + Optional<unsigned> NumExpansions = Expansion->getNumExpansions(); + if (NumExpansions && !PackScope.isPartiallyExpanded()) { + for (unsigned I = 0; I != *NumExpansions && ArgIdx < NumArgs; + ++I, ++ArgIdx) + PackScope.nextPackElement(); + } } // Build argument packs for each of the parameter packs expanded by this @@ -2195,10 +2208,6 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, // template parameter packs expanded by Pi. TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern(); - // FIXME: If there are no remaining arguments, we can bail out early - // and set any deduced parameter packs to an empty argument pack. - // The latter part of this is a (minor) correctness issue. - // Prepare to deduce the packs within the pattern. PackDeductionScope PackScope(S, TemplateParams, Deduced, Info, Pattern); @@ -5280,9 +5289,24 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, const FunctionProtoType *Proto = cast<FunctionProtoType>(T); MarkUsedTemplateParameters(Ctx, Proto->getReturnType(), OnlyDeduced, Depth, Used); - for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) - MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, - Depth, Used); + for (unsigned I = 0, N = Proto->getNumParams(); I != N; ++I) { + // C++17 [temp.deduct.type]p5: + // The non-deduced contexts are: [...] + // -- A function parameter pack that does not occur at the end of the + // parameter-declaration-list. + if (!OnlyDeduced || I + 1 == N || + !Proto->getParamType(I)->getAs<PackExpansionType>()) { + MarkUsedTemplateParameters(Ctx, Proto->getParamType(I), OnlyDeduced, + Depth, Used); + } else { + // FIXME: C++17 [temp.deduct.call]p1: + // When a function parameter pack appears in a non-deduced context, + // the type of that pack is never deduced. + // + // We should also track a set of "never deduced" parameters, and + // subtract that from the list of deduced parameters after marking. + } + } if (auto *E = Proto->getNoexceptExpr()) MarkUsedTemplateParameters(Ctx, E, OnlyDeduced, Depth, Used); break; |

