diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index b79904c0a70..a9fd8fd40ce 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -669,6 +669,19 @@ public: Info.PendingDeducedPacks[Pack.Index] = Pack.Outer; } + /// Determine whether this pack has already been partially expanded into a + /// sequence of (prior) function parameters / template arguments. + bool isPartiallyExpanded() { + if (Packs.size() != 1 || !S.CurrentInstantiationScope) + return false; + + auto *PartiallySubstitutedPack = + S.CurrentInstantiationScope->getPartiallySubstitutedPack(); + return PartiallySubstitutedPack && + getDepthAndIndex(PartiallySubstitutedPack) == + std::make_pair(Info.getDeducedDepth(), Packs.front().Index); + } + /// Move to deducing the next element in each pack that is being deduced. void nextPackElement() { // Capture the deduced template arguments for each parameter pack expanded @@ -2552,6 +2565,12 @@ static bool isSimpleTemplateIdType(QualType T) { return false; } +static void +MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, + bool OnlyDeduced, + unsigned Level, + llvm::SmallBitVector &Deduced); + /// \brief Substitute the explicitly-provided template arguments into the /// given function template according to C++ [temp.arg.explicit]. /// @@ -2613,7 +2632,7 @@ Sema::SubstituteExplicitTemplateArguments( // Enter a new template instantiation context where we check the // explicitly-specified template arguments against this function template, // and then substitute them into the function parameter types. - SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), Deduced.end()); + SmallVector<TemplateArgument, 4> DeducedArgs; InstantiatingTemplate Inst(*this, Info.getLocation(), FunctionTemplate, DeducedArgs, ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution, @@ -3389,7 +3408,6 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. - unsigned CheckArgs = Args.size(); if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) return TDK_TooFewArguments; else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { @@ -3397,9 +3415,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) /* Do nothing */; - else if (Proto->isVariadic()) - CheckArgs = NumParams; - else + else if (!Proto->isVariadic()) return TDK_TooManyArguments; } @@ -3456,7 +3472,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( dyn_cast<PackExpansionType>(ParamType); if (!ParamExpansion) { // Simple case: matching a function parameter to a function argument. - if (ArgIdx >= CheckArgs) + if (ArgIdx >= Args.size()) break; if (auto Result = DeduceCallArgument(ParamType, ArgIdx++)) @@ -3465,36 +3481,47 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( continue; } + QualType ParamPattern = ParamExpansion->getPattern(); + PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info, + ParamPattern); + // C++0x [temp.deduct.call]p1: // For a function parameter pack that occurs at the end of the // parameter-declaration-list, the type A of each remaining argument of // the call is compared with the type P of the declarator-id of the // function parameter pack. Each comparison deduces template arguments // for subsequent positions in the template parameter packs expanded by - // the function parameter pack. For a function parameter pack that does - // not occur at the end of the parameter-declaration-list, the type of - // the parameter pack is a non-deduced context. - // FIXME: This does not say that subsequent parameters are also non-deduced. - // See also DR1388 / DR1399, which effectively says we should keep deducing - // after the pack. - if (ParamIdx + 1 < NumParamTypes) - break; - - QualType ParamPattern = ParamExpansion->getPattern(); - PackDeductionScope PackScope(*this, TemplateParams, Deduced, Info, - ParamPattern); - - for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) - if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) - return Result; + // the function parameter pack. When a function parameter pack appears + // in a non-deduced context [not at the end of the list], the type of + // that parameter pack is never deduced. + // + // FIXME: The above rule allows the size of the parameter pack to change + // after we skip it (in the non-deduced case). That makes no sense, so + // we instead notionally deduce the pack against N arguments, where N is + // the length of the explicitly-specified pack if it's expanded by the + // parameter pack and 0 otherwise, and we treat each deduction as a + // non-deduced context. + if (ParamIdx + 1 == NumParamTypes) { + for (; ArgIdx < Args.size(); PackScope.nextPackElement(), ++ArgIdx) + if (auto Result = DeduceCallArgument(ParamPattern, ArgIdx)) + return Result; + } else { + // 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 = ParamExpansion->getNumExpansions(); + if (NumExpansions && !PackScope.isPartiallyExpanded()) + for (unsigned I = 0; I != *NumExpansions && ArgIdx < Args.size(); + ++I, ++ArgIdx) + // FIXME: Should we add OriginalCallArgs for these? What if the + // corresponding argument is a list? + PackScope.nextPackElement(); + } // Build argument packs for each of the parameter packs expanded by this // pack expansion. if (auto Result = PackScope.finish()) return Result; - - // After we've matching against a parameter pack, we're done. - break; } return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, @@ -4230,12 +4257,6 @@ bool Sema::DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, return StillUndeduced; } -static void -MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, - bool OnlyDeduced, - unsigned Level, - llvm::SmallBitVector &Deduced); - /// \brief If this is a non-static member function, static void AddImplicitObjectParameterType(ASTContext &Context, |