================ @@ -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; + }); + }); ---------------- mizvekov wrote:
Since the deduction itself ignores the exception specification (`TDF_AllowCompatibleFunctionType`), it would seem strange to check exception spec compatibility now, when we could have done that during deduction. Otherwise, this would fail the first example in `ExplicitArgs` from `CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp`: ```C++ namespace ExplicitArgs { template<typename T, typename U> constexpr int f(U) noexcept(noexcept(T())) { return 0; } template<typename T> constexpr int f(T*) noexcept { return 1; } template<> constexpr int f<int>(int*) noexcept { return 2; } static_assert(f<int>(1) == 0); static_assert(f<short>(y) == 1); static_assert(f<int>(x) == 2); ``` But also otherwise, we would not handle packs correctly. See temp_deduct_type_example3 in `CXX/CXX/drs/cwg6xx.cpp` ```C++ template<class T, class... U> void f(T*, U...){} template<class T> void f(T){} template void f(int*); ``` We would fail the consistency check as we would get A = `void (T)`, InstP = `void (T, U...)` if I remember right. 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