From: Nedim Šehić <nedimsehi...@gmail.com>

Regtested on x86_64-pc-linux-gnu.

This patch fixes deduction for member array types from parenthesized
initializers which use braces and string literals.

        PR c++/121518

gcc/cp/ChangeLog:

        * pt.cc (maybe_aggr_guide): Add deduction for brace and string
          literal initializer cases.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/class-deduction-aggr17.C: New test.

Co-Authored-By: Nathaniel Shead <nathanielosh...@gmail.com>
Signed-off-by: Nedim Šehić <nedimsehi...@gmail.com>
---
 gcc/cp/pt.cc                                  | 22 +++--
 .../g++.dg/cpp2a/class-deduction-aggr17.C     | 88 +++++++++++++++++++
 2 files changed, 105 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index b6b13edd03f..35c3ce517e8 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -31116,22 +31116,34 @@ maybe_aggr_guide (tree tmpl, tree init, 
vec<tree,va_gc> *args)
     }
   else if (TREE_CODE (init) == TREE_LIST)
     {
-      int len = list_length (init);
+      tree elt = init;
       for (tree binfo : BINFO_BASE_BINFOS (TYPE_BINFO (template_type)))
        {
-         if (!len)
+         if (!elt)
            break;
          parms = tree_cons (NULL_TREE, BINFO_TYPE (binfo), parms);
-         --len;
+         elt = TREE_CHAIN (elt);
        }
       for (tree field = TYPE_FIELDS (template_type);
-          len;
-          --len, field = DECL_CHAIN (field))
+     elt;
+     elt = TREE_CHAIN (elt), field = DECL_CHAIN (field))
        {
          field = next_aggregate_field (field);
          if (!field)
            return NULL_TREE;
          tree ftype = finish_decltype_type (field, true, complain);
+    tree arg = tree_strip_any_location_wrapper (TREE_VALUE (elt));
+    if (TREE_CODE (ftype) == ARRAY_TYPE)
+      {
+        if (BRACE_ENCLOSED_INITIALIZER_P (arg))
+          ftype = cp_build_reference_type (ftype, true);
+        else if (TREE_CODE (arg) == STRING_CST)
+          {
+            ftype = cp_build_qualified_type
+              (ftype, cp_type_quals (ftype) | TYPE_QUAL_CONST);
+            ftype = cp_build_reference_type (ftype, false);
+          }
+      }
          parms = tree_cons (NULL_TREE, ftype, parms);
        }
     }
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C
new file mode 100644
index 00000000000..9fa63369426
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr17.C
@@ -0,0 +1,88 @@
+// PR c++/121518
+// { dg-do compile { target c++20 } }
+
+#include <cstddef>
+#include <utility>
+
+template <std::size_t N>
+struct Str {
+    char x[N]{};
+};
+
+struct MovableType {
+    MovableType() = default;
+    MovableType(MovableType const&) = delete;
+    MovableType(MovableType&&) = default;
+};
+
+struct ImmovableType {
+    ImmovableType() = default;
+    ImmovableType(ImmovableType&&) = delete;
+};
+
+template <typename T, std::size_t N>
+struct Deduct {
+    T x[N]{};
+};
+
+template<class, class> struct same;
+template<class T> struct same<T, T> {};
+
+Str s0("a");
+same<decltype(s0), Str<2>> c0;
+Str s1{"a"};
+same<decltype(s1), Str<2>> c1;
+Str s2 = {"a"};
+same<decltype(s2), Str<2>> c2;
+
+Str s3({'a', '\0'});
+same<decltype(s3), Str<2>> c3;
+Str s4{{'a', '\0'}};
+same<decltype(s4), Str<2>> c4;
+Str s5 = {{'a', '\0'}};
+same<decltype(s5), Str<2>> c5;
+
+Deduct ds0("a");
+same<decltype(ds0), Deduct<char, 2>> c15;
+Deduct ds1{"a"};
+same<decltype(ds1), Deduct<char, 2>> c16;
+Deduct ds2 = {"a"};
+same<decltype(ds2), Deduct<char, 2>> c17;
+
+Deduct ds3({'a', '\0'});
+same<decltype(ds3), Deduct<char, 2>> c18;
+Deduct ds4{{'a', '\0'}};
+same<decltype(ds4), Deduct<char, 2>> c19;
+Deduct ds5 = {{'a', '\0'}};
+same<decltype(ds5), Deduct<char, 2>> c20;
+
+MovableType mt;
+Deduct dm0({MovableType{}});
+same<decltype(dm0), Deduct<MovableType, 1>> c21;
+Deduct dm1({MovableType{}, std::move(mt)});
+same<decltype(dm1), Deduct<MovableType, 2>> c22;
+
+Deduct dm2{{MovableType{}}};
+same<decltype(dm2), Deduct<MovableType, 1>> c23;
+Deduct dm3{{MovableType{}, std::move(mt)}};
+same<decltype(dm3), Deduct<MovableType, 2>> c24;
+
+Deduct dm4 = {{MovableType{}}};
+same<decltype(dm4), Deduct<MovableType, 1>> c25;
+Deduct dm5 = {{MovableType{}, std::move(mt)}};
+same<decltype(dm5), Deduct<MovableType, 2>> c26;
+
+Deduct dm6({MovableType{}, mt}); // { dg-error "use of deleted function" }
+
+ImmovableType it;
+Deduct di0({ImmovableType{}});
+same<decltype(di0), Deduct<ImmovableType, 1>> c27;
+Deduct di1({ImmovableType{}, std::move(it)});  // { dg-error "use of deleted 
function" }
+
+Deduct di2{{ImmovableType{}}};
+same<decltype(di2), Deduct<ImmovableType, 1>> c28;
+Deduct di3{{ImmovableType{}, std::move(it)}};  // { dg-error "use of deleted 
function" }
+
+Deduct di4 = {{ImmovableType{}}};
+same<decltype(di4), Deduct<ImmovableType, 1>> c29;
+Deduct di5 = {{ImmovableType{}, std::move(it)}};  // { dg-error "use of 
deleted function" }
-- 
2.50.1

Reply via email to