================ @@ -5399,11 +5434,85 @@ static QualType GetImplicitObjectParameterType(ASTContext &Context, return Context.getLValueReferenceType(RawType); } +static TemplateDeductionResult FinishTemplateArgumentDeduction( + Sema &S, FunctionTemplateDecl *FTD, int ArgIdx, QualType P, QualType A, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + TemplateDeductionInfo &Info) { + // Unevaluated SFINAE context. + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::Unevaluated); + Sema::SFINAETrap Trap(S); + + Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(FTD)); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + bool IsIncomplete = false; + SmallVector<TemplateArgument, 4> SugaredBuilder, CanonicalBuilder; + if (auto Result = ConvertDeducedTemplateArguments( + S, FTD, /*IsDeduced=*/true, Deduced, Info, SugaredBuilder, + CanonicalBuilder, /*CurrentInstantiationScope=*/nullptr, + /*NumAlreadyConverted=*/0, &IsIncomplete); + Result != TemplateDeductionResult::Success) + return Result; + + // Form the template argument list from the deduced template arguments. + TemplateArgumentList *SugaredDeducedArgumentList = + TemplateArgumentList::CreateCopy(S.Context, SugaredBuilder); + TemplateArgumentList *CanonicalDeducedArgumentList = + TemplateArgumentList::CreateCopy(S.Context, CanonicalBuilder); + + Info.reset(SugaredDeducedArgumentList, CanonicalDeducedArgumentList); + + // Substitute the deduced template arguments into the argument + // and verify that the instantiated argument is both valid + // and equivalent to the parameter. + LocalInstantiationScope InstScope(S); + + QualType InstP; + { + MultiLevelTemplateArgumentList MLTAL(FTD, SugaredBuilder, + /*Final=*/true); + if (ArgIdx != -1) + if (auto *MD = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl()); + MD && MD->isImplicitObjectMemberFunction()) + ArgIdx -= 1; + Sema::ArgumentPackSubstitutionIndexRAII PackIndex( + S, ArgIdx != -1 ? ::getPackIndexForParam(S, FTD, MLTAL, ArgIdx) : -1); + InstP = S.SubstType(P, MLTAL, FTD->getLocation(), FTD->getDeclName()); + if (InstP.isNull()) + return TemplateDeductionResult::SubstitutionFailure; + } + + if (auto *PA = dyn_cast<PackExpansionType>(A); + PA && !isa<PackExpansionType>(InstP)) + A = PA->getPattern(); + if (!S.Context.hasSameType( + S.Context.getUnqualifiedArrayType(InstP.getNonReferenceType()), + S.Context.getUnqualifiedArrayType(A.getNonReferenceType()))) + return TemplateDeductionResult::NonDeducedMismatch; + + // C++20 [temp.deduct]p5 - Only check constraints when all parameters have + // been deduced. + if (!IsIncomplete) { + if (auto Result = CheckDeducedArgumentConstraints(S, FTD, SugaredBuilder, + CanonicalBuilder, Info); + Result != TemplateDeductionResult::Success) + return Result; + } ---------------- zyn0217 wrote:
I presume this happens before substituting into the function declaration, right? I have a concern about `CheckDeducedArgumentConstraints()` that it would check the function's associated constraints that might refer to uninstantiated function parameters. We didn't set up a scope for that because this function was just used for class/variable templates, which wasn't necessary previously. https://github.com/llvm/llvm-project/pull/100692 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits