https://github.com/daniel-petrovic updated https://github.com/llvm/llvm-project/pull/227214
>From d88b100d7acce3cba266e5529c7e10cc76f336da Mon Sep 17 00:00:00 2001 From: Daniel Petrovic <[email protected]> Date: Tue, 29 Sep 2026 10:23:50 +0200 Subject: [PATCH 1/2] [clang] Fix crash/assert for NTTP defaults in CTAD TransformTemplateParmRefExpr was asserting on argument being expression, but a non-type template parameter that defaults to another non-type template parameter can be canonicalized into a non-expression argument, which caused the crash. Rebuild the expression from the canonical argument instead. Fixes #227007. --- clang/docs/ReleaseNotes.md | 3 +++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 18 ++++++++++---- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 26 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 3c6acf353f93f..5074dd7a21959 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -802,6 +802,9 @@ features cannot lower the translation-unit ABI level; - Fixed an assertion failure when a method or function definition follows an Objective-C `@implementation` that was ended by a nested `@interface`, `@protocol` or `@implementation` before its `@end`. (#GH209503) +- Fixed a crash and an assertion failure when a non-type template parameter + is canonicalized into a non-expression form (e.g. in a deduction guide), + which the template rewrite now rebuilds instead of asserting. (#GH227007) ### OpenACC Specific Changes diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 06ea12ca7bd73..6544986cea8f7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2227,11 +2227,19 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, // We're rewriting the template parameter as a reference to another // template parameter. Arg = getTemplateArgumentPackPatternForRewrite(Arg); - assert(Arg.getKind() == TemplateArgument::Expression && - "unexpected nontype template argument kind in template rewrite"); - // FIXME: This can lead to the same subexpression appearing multiple times - // in a complete expression. - return Arg.getAsExpr(); + if (Arg.getKind() == TemplateArgument::Expression) { + // FIXME: This can lead to the same subexpression appearing multiple times + // in a complete expression. + return Arg.getAsExpr(); + } + // Otherwise try to rebuild expression if argument has been canonicalized + // into a non-expression form (e.g. integral value or template parameter + // object) + ExprResult Rewritten = SemaRef.BuildExpressionFromNonTypeTemplateArgument( + Arg, E->getLocation()); + if (Rewritten.isInvalid()) + return ExprError(); + return Rewritten; } QualType ParamType = NTTP->isExpandedParameterPack() diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 78911cbaed67b..7b68ed394393d 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -629,3 +629,29 @@ template <typename T> using S3 = S2<T>; // expected-note {{candidate function no // expected-note {{cannot deduce template arguments for 'GH190517::S3' from 'GH190517::S1<char>'}} S3 foo(42); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'S3'}} } + +namespace GH227007 { + +// A non-type template parameter that defaults to another non-type template +// parameter is canonicalized to a non-expression argument, so the rewrite has +// to rebuild the expression from the canonical argument. +struct Id {}; + +template <auto Kind, class Value, auto Token = Kind> struct Tagged { Value value; }; +template <auto Kind = Id{}, class Value, auto Token = Kind> +Tagged(Value) -> Tagged<Kind, Value, Token>; +template <class Value> using Default = Tagged<Id{}, Value>; + +Default value{false}; +static_assert(__is_same(decltype(value), Tagged<Id{}, bool, Id{}>)); + +// Same, but with both defaulted parameters being of integral type. +template <auto Kind, class Value, auto Token = Kind> struct IntTagged { Value value; }; +template <auto Kind = 0, class Value, auto Token = Kind> +IntTagged(Value) -> IntTagged<Kind, Value, Token>; +template <class Value> using IntDefault = IntTagged<0, Value>; + +IntDefault int_value{false}; +static_assert(__is_same(decltype(int_value), IntTagged<0, bool, 0>)); + +} // namespace GH227007 >From 83c0cdee08e075cb7ff3d58e0cbe1959638dd205 Mon Sep 17 00:00:00 2001 From: Daniel Petrovic <[email protected]> Date: Tue, 29 Sep 2026 14:06:08 +0200 Subject: [PATCH 2/2] Get assertion back because of MLTAL --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 6544986cea8f7..70a701f1b75a9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2232,9 +2232,23 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, // in a complete expression. return Arg.getAsExpr(); } - // Otherwise try to rebuild expression if argument has been canonicalized - // into a non-expression form (e.g. integral value or template parameter - // object) + + // Otherwise try rebuilding the expression if argument has been + // canonicalized into a non-expression form + // (e.g. integral value, template parameter object, ...). + // Any other kind indicates a mismatch between the template argument list and the + // parameter being rewritten. + switch (Arg.getKind()) { + case TemplateArgument::Integral: + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + case TemplateArgument::StructuralValue: + break; + default: + assert(false && + "unexpected nontype template argument kind in template rewrite"); + return ExprError(); + } ExprResult Rewritten = SemaRef.BuildExpressionFromNonTypeTemplateArgument( Arg, E->getLocation()); if (Rewritten.isInvalid()) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
