llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Daniel Petrovic (daniel-petrovic) <details> <summary>Changes</summary> 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 --- Full diff: https://github.com/llvm/llvm-project/pull/227214.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.md (+3) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+13-5) - (modified) clang/test/SemaCXX/cxx20-ctad-type-alias.cpp (+26) ``````````diff 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 `````````` </details> https://github.com/llvm/llvm-project/pull/227214 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
