================ @@ -5425,34 +5534,112 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, // the partial ordering is done: TemplateDeductionInfo Info(Loc); switch (TPOC) { - case TPOC_Call: + case TPOC_Call: { if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), Args1.size(), Info, Deduced, TDF_None, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; - break; + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), + Deduced.end()); + Sema::InstantiatingTemplate Inst( + S, Info.getLocation(), FT2, DeducedArgs, + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); + if (Inst.isInvalid()) + return false; - case TPOC_Conversion: + bool AtLeastAsSpecialized = true; + S.runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = + ::DeduceForEachType( + S, TemplateParams, Args2.data(), Args2.size(), Args1.data(), + Args1.size(), Info, Deduced, + /*PartialOrdering=*/true, /*FinishingDeduction=*/true, + [&FT2](Sema &S, TemplateParameterList *, int ArgIdx, QualType P, + QualType A, TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool PartialOrdering) { + return ::FinishTemplateArgumentDeduction(S, FT2, ArgIdx, P, A, + Deduced, Info); + }) == TemplateDeductionResult::Success; + }); + if (!AtLeastAsSpecialized) + return false; + } break; + + case TPOC_Conversion: { // - In the context of a call to a conversion operator, the return types // of the conversion function templates are used. if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, Proto2->getReturnType(), Proto1->getReturnType(), Info, Deduced, TDF_None, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; - break; - case TPOC_Other: + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), + Deduced.end()); + Sema::InstantiatingTemplate Inst( + S, Info.getLocation(), FT2, DeducedArgs, + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); + if (Inst.isInvalid()) + return false; + + bool AtLeastAsSpecialized; + S.runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = ::FinishTemplateArgumentDeduction( + S, FT2, /*ArgIdx=*/-1, Proto2->getReturnType(), + Proto1->getReturnType(), Deduced, + Info) == TemplateDeductionResult::Success; + }); + if (!AtLeastAsSpecialized) + return false; + } break; + + case TPOC_Other: { // - In other contexts (14.6.6.2) the function template's function type // is used. if (DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced, TDF_AllowCompatibleFunctionType, /*PartialOrdering=*/true) != TemplateDeductionResult::Success) return false; - break; + + SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), + Deduced.end()); + Sema::InstantiatingTemplate Inst( + S, Info.getLocation(), FT2, DeducedArgs, + Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution, Info); + if (Inst.isInvalid()) + return false; + + bool AtLeastAsSpecialized; + S.runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = ::FinishTemplateArgumentDeduction( + S, FT2, /*ArgIdx=*/-1, Proto2->getReturnType(), + Proto1->getReturnType(), Deduced, + Info) == TemplateDeductionResult::Success; + if (!AtLeastAsSpecialized) + return; + S.runWithSufficientStackSpace(Info.getLocation(), [&] { + AtLeastAsSpecialized = + ::DeduceForEachType( + S, TemplateParams, Proto2->getParamTypes().data(), + Proto2->getParamTypes().size(), Proto1->getParamTypes().data(), + Proto1->getParamTypes().size(), Info, Deduced, + /*PartialOrdering=*/true, /*FinishingDeduction=*/true, + [&FT2](Sema &S, TemplateParameterList *, int ArgIdx, QualType P, + QualType A, TemplateDeductionInfo &Info, + SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool PartialOrdering) { + return ::FinishTemplateArgumentDeduction(S, FT2, ArgIdx, P, A, + Deduced, Info); + }) == TemplateDeductionResult::Success; + }); + }); ---------------- zygoloid wrote:
Do we need to separately check the return type and the parameter types here, rather than checking the entire function type as a whole? (This is not quite the same: for example, checking the whole function type would also consider the exception specification.) 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