On 4/5/21 12:31 PM, Patrick Palka wrote:
On Mon, 5 Apr 2021, Patrick Palka wrote:

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?

OK.

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);

On second thought, I think we can get away with using just TREE_TYPE (init)
here and leaving the propagation of type qualifiers to tsubst.  This has
the effect of making us reject the testcase placeholder8.C below, which
is consistent with the non-array case.  IIUC, the type qualifiers on a
constrained 'auto' shouldn't be relevant during constraint checking.

I'm testing the following:

-- >8 --

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.
        * g++.dg/cpp2a/concepts-placeholder8.C: New test.
---
  gcc/cp/pt.c                                   | 20 +++++++-----
  .../g++.dg/cpp2a/concepts-placeholder7.C      | 32 +++++++++++++++++++
  .../g++.dg/cpp2a/concepts-placeholder8.C      | 10 ++++++
  3 files changed, 54 insertions(+), 8 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C
  create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1d19a59dd62..fd1e4db42cf 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,17 @@ 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.struct.bind]/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) = TREE_TYPE (init);
+    }
    else if (AUTO_IS_DECLTYPE (auto_node))
      {
        tree stripped_init = tree_strip_any_location_wrapper (init);
@@ -29596,7 +29597,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 +29606,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..93219ff4f05
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder7.C
@@ -0,0 +1,32 @@
+// 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>();
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C
new file mode 100644
index 00000000000..e78659203ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder8.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++20 } }
+
+template <class T> concept is_const = __is_same(T, const T);
+
+void f() {
+  int x[] = {1,2};
+  const int y[] = {3};
+  const is_const auto [a,b] = x; // { dg-error "constraints" }
+  const is_const auto [c] = y;
+}


Reply via email to