https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/223645
We were not implementing https://eel.is/c++draft/temp.deduct.type#13 properly. Fixes #40328 Assisted-By: Opus 5 >From c219d31ac01331b4937d31360b2d2ad2ebf5e0bd Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Tue, 15 Sep 2026 12:12:25 +0200 Subject: [PATCH] [Clang] Fix deduction from constant TP of reference type. We were not implementing https://eel.is/c++draft/temp.deduct.type#13 properly. Fixes #40328 Assisted-By: Opus 5 --- clang/docs/ReleaseNotes.md | 3 ++ clang/lib/Sema/SemaTemplateDeduction.cpp | 30 ++++++++++--------- .../SemaTemplate/temp_arg_nontype_cxx1z.cpp | 13 ++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 043a0ddae2a6c..b5dfb5930c3f4 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -676,6 +676,9 @@ features cannot lower the translation-unit ABI level; class with an invalid non-static data member, such as one qualified with an address space. (#GH194605) +- Fixed deduction of the template parameters appearing in the type of a + constant template parameter of reference type. (#GH40328) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index b66152f2d971d..795d199ee5224 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -261,6 +261,20 @@ getDeducedNTTParameterFromExpr(TemplateDeductionInfo &Info, Expr *E) { return getDeducedNTTParameterFromExpr(E, Info.getDeducedDepth()); } +/// C++26 [temp.deduct.type]p13: +/// When the value of the argument corresponding to a constant template +/// parameter P that is declared with a dependent type is deduced from an +/// expression, the template parameters in the type of P are deduced from the +/// type of the value. +static QualType getTypeOfTemplateArgumentValue(TemplateDeductionInfo &Info, + const TemplateArgument &A) { + const Expr *E = unwrapExpressionForDeduction(A.getAsExpr()); + if (NonTypeOrVarTemplateParmDecl NTTP = + getDeducedNTTParameterFromExpr(E, Info.getDeducedDepth())) + return NTTP.getType(); + return E->getType(); +} + /// Determine whether two declaration pointers refer to the same /// declaration. static bool isSameDeclaration(Decl *X, Decl *Y) { @@ -497,17 +511,6 @@ DeduceNonTypeTemplateArgument(Sema &S, TemplateParameterList *TemplateParams, if (auto *Expansion = dyn_cast<PackExpansionType>(ParamType)) ParamType = Expansion->getPattern(); - // FIXME: It's not clear how deduction of a parameter of reference - // type from an argument (of non-reference type) should be performed. - // For now, we just make the argument have same reference type as the - // parameter. - if (ParamType->isReferenceType() && !ValueType->isReferenceType()) { - if (ParamType->isRValueReferenceType()) - ValueType = S.Context.getRValueReferenceType(ValueType); - else - ValueType = S.Context.getLValueReferenceType(ValueType); - } - return DeduceTemplateArgumentsByTypeMatch( S, TemplateParams, ParamType, ValueType, Info, Deduced, TDF_SkipNonDependent | TDF_IgnoreQualifiers, @@ -2648,11 +2651,10 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, getDeducedNTTParameterFromExpr(Info, P.getAsExpr())) { switch (A.getKind()) { case TemplateArgument::Expression: { - // The type of the value is the type of the expression as written. return DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, DeducedTemplateArgument(A), - A.getAsExpr()->IgnoreImplicitAsWritten()->getType(), Info, - PartialOrdering, Deduced, HasDeducedAnyParam); + getTypeOfTemplateArgumentValue(Info, A), Info, PartialOrdering, + Deduced, HasDeducedAnyParam); } case TemplateArgument::Integral: case TemplateArgument::StructuralValue: diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 5077d5ff8ad89..a39bb02084aa7 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -648,3 +648,16 @@ namespace GH58682 { template <decltype(auto) v> struct B<A<v>> { static constexpr int k = 1; }; static_assert(B<A<(g)>>::k == 1, ""); } // namespace GH58682 + +// C++26 [temp.deduct.type]p13, Example 8. +namespace temp_deduct_type_p13 { + template<long n> struct A { }; + + template<typename T> struct C; + template<typename T, T n> struct C<A<n>> { + using Q = T; + }; + + using R = long; + using R = C<A<2>>::Q; +} // namespace temp_deduct_type_p13 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
