llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: I (wx257osn2) <details> <summary>Changes</summary> Fixes #<!-- -->175831. When transforming a `SubstNonTypeTemplateParmExpr`, `TreeTransform::TransformSubstNonTypeTemplateParmExpr` calls `Sema::CheckTemplateArgument` so that any sema annotations (such as implicit casts) that were stripped from the replacement are recovered. However, `CheckTemplateArgument` forces constant evaluation of the replacement expression, and that evaluation can fail in unevaluated contexts (e.g. inside `decltype`) for otherwise valid expressions. A typical case is a function call that takes a class-type parameter by value: in an unevaluated context the special members of the argument's class are not instantiated, so the implicit copy used to materialize the parameter cannot be constant-folded and `CheckTemplateArgument` reports an error. This caused rejects-valid regressions on real code such as mp-units. In an unevaluated context we only need the type of the resulting expression, not its value. This PR keeps the existing behavior in evaluated contexts but, when `CheckTemplateArgument` fails inside an unevaluated context, falls back to using the already-transformed replacement as-is instead of propagating the failure. -- Co-authored-by: A. Jiang <de34@<!-- -->live.cn> --- Full diff: https://github.com/llvm/llvm-project/pull/196791.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+1) - (modified) clang/lib/Sema/TreeTransform.h (+13-3) - (modified) clang/test/SemaTemplate/concepts.cpp (+18-1) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c17143e3c0398..6c2cecfb7dc20 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -543,6 +543,7 @@ Bug Fixes in This Version - Fixed a crash when parsing invalid ``static_assert`` declarations with string-literal messages (#GH187690). - Fixed a potential stack-use-after-return issue in Clang when copy-initializing an array via an element-at-a-time copy loop (#GH192026) +- Fixed a regression where calling a function that takes a class-type parameter by value inside ``decltype`` of a concept could be incorrectly rejected when used as a non-type template argument. (#GH175831) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 40187f71231bd..efaff4c0e02ec 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -16736,13 +16736,23 @@ ExprResult TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr( // specific annotations, such as implicit casts, are discarded. Calling the // corresponding sema action is necessary to recover those. Otherwise, // equivalency of the result would be lost. + // + // In unevaluated contexts (e.g. inside decltype), CheckTemplateArgument + // forces constant evaluation that is inappropriate and may fail for + // valid expressions (e.g. function calls with by-value class parameters). + // Since we only need the type in such contexts, we can tolerate the + // failure and proceed with the transformed replacement as-is. TemplateArgument SugaredConverted, CanonicalConverted; - Replacement = SemaRef.CheckTemplateArgument( + ExprResult Checked = SemaRef.CheckTemplateArgument( Param, ParamType, Replacement.get(), SugaredConverted, CanonicalConverted, /*StrictCheck=*/false, Sema::CTAK_Specified); - if (Replacement.isInvalid()) - return true; + if (Checked.isInvalid()) { + if (!SemaRef.isUnevaluatedContext()) + return true; + } else { + Replacement = Checked; + } } else { // Otherwise, the same expression would have been produced. Replacement = E->getReplacement(); diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 1b7cfc96243ef..c5fe4969a36b6 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1836,7 +1836,6 @@ namespace GH191016 { void test(){ S<int> s; } } - namespace GH188640 { namespace Ex1 { @@ -1880,3 +1879,21 @@ void g() { static_assert(f<1>() == 42); } } // namespace VAR } // namespace GH188640 + +namespace GH175831 { + +template<class> +struct reference {}; +template<class Q> +consteval Q get_spec(reference<Q>) { return {}; } + +template<class T> +concept repr_impl = sizeof(T) > 0; +template<class, auto V> +concept representation_of = repr_impl<decltype(V)>; +template<auto V, representation_of<get_spec(V)>> +struct quantity {}; + +auto x = quantity<reference<int>{}, int>{}; + +} // namespace GH175831 `````````` </details> https://github.com/llvm/llvm-project/pull/196791 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
