On 2/14/26 3:02 AM, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/backports? Not sure if we want to do this for every choice of impl_conv_void, or just for ICV_CAST?
I don't see a reason to treat other cases differently. OK.
-- >8 -- Similar to r16-7056-g22f51c0f5e62a4, here the expression within the decltype void(Derived<T>) is non-dependent enough that we instantiate/fold it immediately, during which however convert_to_void tries to evaluate the concept-id, which fails. When in an unevaluated context such as decltype I don't think covert_to_void should be evaluating concept-ids. PR c++/121822 gcc/cp/ChangeLog: * cvt.cc (convert_to_void): Don't evaluate a concept-id in an unevaluated context. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-decltype6.C: New test. --- gcc/cp/cvt.cc | 2 +- gcc/testsuite/g++.dg/cpp2a/concepts-decltype6.C | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-decltype6.C diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index fe9b9dc6dd18..4042938da5e9 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -1210,7 +1210,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)/* Explicitly evaluate void-converted concept checks since theirsatisfaction may produce ill-formed programs. */ - if (concept_check_p (expr)) + if (concept_check_p (expr) && !cp_unevaluated_operand) expr = evaluate_concept_check (expr);/* Detect using expressions of consteval-only types outside manifestlydiff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-decltype6.C b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype6.C new file mode 100644 index 000000000000..3af2697b95d1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-decltype6.C @@ -0,0 +1,16 @@ +// PR c++/121822 +// { dg-do compile { target c++20 } } + +template<class...> +using void_t = void; + +template<class T> +concept Derived = requires {typename T::derived_type; }; + +template<class T, class = void> +struct Wrapper; + +template<class T> +struct Wrapper<T, void_t<decltype(void(Derived<T>))>> { }; + +Wrapper<int> x;
