In this PR, we're crashing because the constraint handling inside
do_auto_deduction doesn't expect to see an adc_decomp_type context.
This patch fixes this by treating adc_decomp_type like adc_variable_type
and adc_return_type during the constraint handling.

Meanwhile, I noticed we weren't checking constraints at all when binding
an array via a structured binding, since do_auto_deduction would exit
early and bypass the constraint check.  This patch fixes this by
replacing the early exit with an appropriate setup of the 'targs'
vector.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

gcc/cp/ChangeLog:

        PR c++/99899
        * pt.c (do_auto_deduction): Don't exit early when deducing the
        array type of a structured binding.  Also handle adc_decomp_type
        during constraint checking.

gcc/testsuite/ChangeLog:

        PR c++/99899
        * g++.dg/cpp2a/concepts-placeholder7.C: New test.
---
 gcc/cp/pt.c                                   | 22 +++++++-----
 .../g++.dg/cpp2a/concepts-placeholder7.C      | 34 +++++++++++++++++++
 2 files changed, 48 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1d19a59dd62..0f9f5858038 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29438,8 +29438,6 @@ do_auto_deduction (tree type, tree init, tree auto_node,
                    tsubst_flags_t complain, auto_deduction_context context,
                   tree outer_targs, int flags)
 {
-  tree targs;
-
   if (init == error_mark_node)
     return error_mark_node;
 
@@ -29503,14 +29501,19 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
   else
     init = resolve_nondeduced_context (init, complain);
 
+  tree targs;
   if (context == adc_decomp_type
       && auto_node == type
       && init != error_mark_node
       && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
-    /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers
-       and initializer has array type, deduce cv-qualified array type.  */
-    return cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type),
-                                        complain);
+    {
+      /* [dcl.decomp]/1 - if decomposition declaration has no ref-qualifiers
+        and initializer has array type, deduce cv-qualified array type.  */
+      targs = make_tree_vec (1);
+      TREE_VEC_ELT (targs, 0)
+       = cp_build_qualified_type_real (TREE_TYPE (init), TYPE_QUALS (type),
+                                       complain);
+    }
   else if (AUTO_IS_DECLTYPE (auto_node))
     {
       tree stripped_init = tree_strip_any_location_wrapper (init);
@@ -29596,7 +29599,8 @@ do_auto_deduction (tree type, tree init, tree auto_node,
       if (processing_template_decl)
        {
          gcc_checking_assert (context == adc_variable_type
-                              || context == adc_return_type);
+                              || context == adc_return_type
+                              || context == adc_decomp_type);
          gcc_checking_assert (!type_dependent_expression_p (init));
          /* If the constraint is dependent, we need to wait until
             instantiation time to resolve the placeholder.  */
@@ -29604,7 +29608,9 @@ do_auto_deduction (tree type, tree init, tree auto_node,
            return type;
        }
 
-      if ((context == adc_return_type || context == adc_variable_type)
+      if ((context == adc_return_type
+          || context == adc_variable_type
+          || context == adc_decomp_type)
          && current_function_decl
          && DECL_TEMPLATE_INFO (current_function_decl))
        outer_targs = DECL_TI_ARGS (current_function_decl);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C
new file mode 100644
index 00000000000..db352a01e83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C
@@ -0,0 +1,34 @@
+// PR c++/99899
+// { dg-do compile { target c++20 } }
+
+template <class T> concept C1 = sizeof(T) > sizeof(int[1]);
+
+template <class>
+void f() {
+  int x[] = {1,2};
+  int y[] = {3};
+  C1 auto [a,b] = x;
+  C1 auto [c] = y; // { dg-error "constraints" }
+}
+
+template <class T>
+void g() {
+  T x[] = {1,2};
+  T y[] = {3};
+  C1 auto [a,b] = x;
+  C1 auto [c] = y; // { dg-error "constraints" }
+}
+
+template void g<int>();
+
+
+template <class... Ts> concept C2 = sizeof...(Ts) > 1;
+
+struct S { int a, b; } s;
+
+template <class T>
+void h() {
+  const C2<T> auto& [a, b] = s;
+}
+
+template void h<int>();
-- 
2.31.1.189.g2e36527f23

Reply via email to