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?

-- >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 their
      satisfaction 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 manifestly
diff --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;
-- 
2.53.0.80.g6fcee47852

Reply via email to