https://github.com/keinflue updated https://github.com/llvm/llvm-project/pull/152864
>From f36c8dbedace87b378d2870402eb1119a2ed253f Mon Sep 17 00:00:00 2001 From: keinflue <keinf...@posteo.de> Date: Sat, 9 Aug 2025 09:33:20 +0200 Subject: [PATCH 1/2] [clang] Distinguish NTTPs with deduced types in variable template partial specializations If a template argument in a partial specialization of a variable template directly refers to a NTTP of the specialization without implicit type conversion it was assumed that the NTTP is identical to that of the primary template. This doesn't hold if the primary template's NTTP uses a deduced type, so instead compare the types explicitly as well. Fixes #118190 Fixes #152750 --- clang/lib/Sema/SemaTemplate.cpp | 6 +++++- clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 2d8fdb5b766fc..ae16323535bdc 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4126,7 +4126,11 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, return false; const NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); - return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index; + if (!NTTP || NTTP->getDepth() != Depth || NTTP->getIndex() != Index) + return false; + QualType ParamType = cast<NonTypeTemplateParmDecl>(Param)->getType(); + QualType NTTPType = NTTP->getType(); + return ParamType.getCanonicalType() == NTTPType.getCanonicalType(); } case TemplateArgument::Template: diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index c35743b87adbc..9c25e26f43c36 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -621,3 +621,8 @@ namespace GH73460 { int j; template struct A<int&, j, j>; } // namespace GH73460 + +namespace GH118190 { + template <auto> int x; + template <int i> int x<i>; +} >From 07c9546f36e78441032dd50edced2b73f8fe4ef5 Mon Sep 17 00:00:00 2001 From: keinflue <keinf...@posteo.de> Date: Sat, 9 Aug 2025 15:01:58 +0200 Subject: [PATCH 2/2] Relocate new check into caller to not mess up interpretation of callee. Also remove unused and potentially confusing paramter from isTemplateArgumentTemplateParamter. --- clang/lib/Sema/SemaTemplate.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ae16323535bdc..784e82c5efa63 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4099,7 +4099,6 @@ static bool CheckTemplateSpecializationScope(Sema &S, NamedDecl *Specialized, static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D); static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, - NamedDecl *Param, unsigned Depth, unsigned Index) { switch (Arg.getKind()) { @@ -4126,11 +4125,7 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, return false; const NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); - if (!NTTP || NTTP->getDepth() != Depth || NTTP->getIndex() != Index) - return false; - QualType ParamType = cast<NonTypeTemplateParmDecl>(Param)->getType(); - QualType NTTPType = NTTP->getType(); - return ParamType.getCanonicalType() == NTTPType.getCanonicalType(); + return NTTP && NTTP->getDepth() == Depth && NTTP->getIndex() == Index; } case TemplateArgument::Template: @@ -4143,8 +4138,9 @@ static bool isTemplateArgumentTemplateParameter(const TemplateArgument &Arg, } static bool isSameAsPrimaryTemplate(TemplateParameterList *Params, + TemplateParameterList *SpecParams, ArrayRef<TemplateArgument> Args) { - if (Params->size() != Args.size()) + if (Params->size() != Args.size() || Params->size() != SpecParams->size()) return false; unsigned Depth = Params->getDepth(); @@ -4161,9 +4157,19 @@ static bool isSameAsPrimaryTemplate(TemplateParameterList *Params, Arg = Arg.pack_begin()->getPackExpansionPattern(); } - if (!isTemplateArgumentTemplateParameter(Arg, Params->getParam(I), Depth, - I)) + if (!isTemplateArgumentTemplateParameter(Arg, Depth, I)) return false; + + // For NTTPs further specialization is allowed via deduced types, so + // we need to make sure to only reject here if primary template and + // specialization use the same type for the NTTP. + if (auto *SpecNTTP = + dyn_cast<NonTypeTemplateParmDecl>(SpecParams->getParam(I))) { + auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(I)); + if (!NTTP || NTTP->getType().getCanonicalType() != + SpecNTTP->getType().getCanonicalType()) + return false; + } } return true; @@ -4361,7 +4367,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } if (isSameAsPrimaryTemplate(VarTemplate->getTemplateParameters(), - CTAI.CanonicalConverted) && + TemplateParams, CTAI.CanonicalConverted) && (!Context.getLangOpts().CPlusPlus20 || !TemplateParams->hasAssociatedConstraints())) { // C++ [temp.class.spec]p9b3: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits