On Fri, Dec 15, 2017 at 11:23:21PM +0100, Jakub Jelinek wrote:
> Hi!
> 
> I've backported today following 23 patches after bootstrapping/regtesting
> them on x86_64-linux and i686-linux.

And 2 more:

        Jakub
2017-12-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/81197
        * cp-tree.h (cp_maybe_mangle_decomp): Declare.
        * decl.c (cp_maybe_mangle_decomp): New function.
        (cp_finish_decomp): Don't SET_DECL_ASSEMBLER_NAME here.
        * parser.c (cp_convert_range_for,
        cp_parser_decomposition_declaration): Call cp_maybe_mangle_decomp.
        * pt.c (tsubst_expr): Likewise.
        * mangle.c (find_decomp_unqualified_name): New function.
        (write_unqualified_name): Handle DECL_DECOMPOSITION_P
        where DECL_ASSEMBLER_NAME is already set.

        * g++.dg/cpp1z/decomp34.C: New test.

--- gcc/cp/decl.c       (revision 255704)
+++ gcc/cp/decl.c       (revision 255705)
@@ -7339,6 +7339,25 @@ lookup_decomp_type (tree v)
   return *decomp_type_table->get (v);
 }
 
+/* Mangle a decomposition declaration if needed.  Arguments like
+   in cp_finish_decomp.  */
+
+void
+cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count)
+{
+  if (!processing_template_decl
+      && !error_operand_p (decl)
+      && DECL_NAMESPACE_SCOPE_P (decl))
+    {
+      auto_vec<tree, 16> v;
+      v.safe_grow (count);
+      tree d = first;
+      for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d))
+       v[count - i - 1] = d;
+      SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
+    }
+}
+
 /* Finish a decomposition declaration.  DECL is the underlying declaration
    "e", FIRST is the head of a chain of decls for the individual identifiers
    chained through DECL_CHAIN in reverse order and COUNT is the number of
@@ -7612,8 +7631,6 @@ cp_finish_decomp (tree decl, tree first,
            DECL_HAS_VALUE_EXPR_P (v[i]) = 1;
          }
     }
-  else if (DECL_NAMESPACE_SCOPE_P (decl))
-    SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v));
 }
 
 /* Returns a declaration for a VAR_DECL as if:
--- gcc/cp/pt.c (revision 255704)
+++ gcc/cp/pt.c (revision 255705)
@@ -16135,19 +16135,23 @@ tsubst_expr (tree t, tree args, tsubst_f
                    if (VAR_P (decl))
                      const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P
                                    (pattern_decl));
-                   cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
                    if (VAR_P (decl)
                        && DECL_DECOMPOSITION_P (decl)
                        && TREE_TYPE (pattern_decl) != error_mark_node)
                      {
                        unsigned int cnt;
                        tree first;
-                       decl = tsubst_decomp_names (decl, pattern_decl, args,
-                                                   complain, in_decl, &first,
-                                                   &cnt);
-                       if (decl != error_mark_node)
-                         cp_finish_decomp (decl, first, cnt);
+                       tree ndecl
+                         = tsubst_decomp_names (decl, pattern_decl, args,
+                                                complain, in_decl, &first, 
&cnt);
+                       if (ndecl != error_mark_node)
+                         cp_maybe_mangle_decomp (ndecl, first, cnt);
+                       cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
+                       if (ndecl != error_mark_node)
+                         cp_finish_decomp (ndecl, first, cnt);
                      }
+                   else
+                     cp_finish_decl (decl, init, const_init, NULL_TREE, 0);
                  }
              }
          }
--- gcc/cp/parser.c     (revision 255704)
+++ gcc/cp/parser.c     (revision 255705)
@@ -11735,6 +11735,9 @@ cp_convert_range_for (tree statement, tr
                                     tf_warning_or_error);
   finish_for_expr (expression, statement);
 
+  if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl))
+    cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt);
+
   /* The declaration is initialized with *__begin inside the loop body.  */
   cp_finish_decl (range_decl,
                  build_x_indirect_ref (input_location, begin, RO_NULL,
@@ -13059,6 +13062,7 @@ cp_parser_decomposition_declaration (cp_
 
       if (decl != error_mark_node)
        {
+         cp_maybe_mangle_decomp (decl, prev, v.length ());
          cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
                          is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT);
          cp_finish_decomp (decl, prev, v.length ());
--- gcc/cp/mangle.c     (revision 255704)
+++ gcc/cp/mangle.c     (revision 255705)
@@ -1247,6 +1247,51 @@ write_template_prefix (const tree node)
   add_substitution (substitution);
 }
 
+/* As the list of identifiers for the structured binding declaration
+   DECL is likely gone, try to recover the DC <source-name>+ E portion
+   from its mangled name.  Return pointer to the DC and set len to
+   the length up to and including the terminating E.  On failure
+   return NULL.  */
+
+static const char *
+find_decomp_unqualified_name (tree decl, size_t *len)
+{
+  const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
+  bool nested = false;
+  if (strncmp (p, "_Z", 2))
+    return NULL;
+  p += 2;
+  if (!strncmp (p, "St", 2))
+    p += 2;
+  else if (*p == 'N')
+    {
+      nested = true;
+      ++p;
+      while (ISDIGIT (p[0]))
+       {
+         char *e;
+         long num = strtol (p, &e, 10);
+         if (num >= 1 && num < end - e)
+           p = e + num;
+         else
+           break;
+       }
+    }
+  if (strncmp (p, "DC", 2))
+    return NULL;
+  if (nested)
+    {
+      if (end[-1] != 'E')
+       return NULL;
+      --end;
+    }
+  if (end[-1] != 'E')
+    return NULL;
+  *len = end - p;
+  return p;
+}
+
 /* We don't need to handle thunks, vtables, or VTTs here.  Those are
    mangled through special entry points.
 
@@ -1291,7 +1336,17 @@ write_unqualified_name (tree decl)
     {
       found = true;
       gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-      write_source_name (DECL_ASSEMBLER_NAME (decl));
+      const char *decomp_str = NULL;
+      size_t decomp_len = 0;
+      if (VAR_P (decl)
+         && DECL_DECOMPOSITION_P (decl)
+         && DECL_NAME (decl) == NULL_TREE
+         && DECL_NAMESPACE_SCOPE_P (decl))
+       decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
+      if (decomp_str)
+       write_chars (decomp_str, decomp_len);
+      else
+       write_source_name (DECL_ASSEMBLER_NAME (decl));
     }
   else if (DECL_DECLARES_FUNCTION_P (decl))
     {
--- gcc/cp/cp-tree.h    (revision 255704)
+++ gcc/cp/cp-tree.h    (revision 255705)
@@ -6149,6 +6149,7 @@ extern void start_decl_1                  (tree, bool);
 extern bool check_array_initializer            (tree, tree, tree);
 extern void cp_finish_decl                     (tree, tree, bool, tree, int);
 extern tree lookup_decomp_type                 (tree);
+extern void cp_maybe_mangle_decomp             (tree, tree, unsigned int);
 extern void cp_finish_decomp                   (tree, tree, unsigned int);
 extern int cp_complete_array_type              (tree *, tree, bool);
 extern int cp_complete_array_type_or_error     (tree *, tree, bool, 
tsubst_flags_t);
--- gcc/testsuite/g++.dg/cpp1z/decomp34.C       (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp34.C       (revision 255705)
@@ -0,0 +1,11 @@
+// PR c++/81197
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct X { int a; };
+struct Y { int b, c, d; };
+auto&& [t] = X{};      // { dg-warning "decomposition declaration only 
available with" "" { target c++14_down } }
+namespace A { namespace B { auto&& [u, v, ww] = Y{}; } }       // { dg-warning 
"decomposition declaration only available with" "" { target c++14_down } }
+
+// { dg-final { scan-assembler "_ZGRDC1tE0" } }
+// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } }
2017-12-16  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2017-12-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/83205
        * decl.c (cp_finish_decomp): Handle the case when tsize is not
        error_mark_node, but doesn't fit into uhwi.  Split up count != eltscnt
        and !tree_fits_uhwi_p (tsize) error_at calls into error_n and inform_n
        to handle plural forms properly.

        * g++.dg/cpp1z/decomp3.C: Adjust for structured binding count
        mismatch diagnostics split into error and warning with plural
        forms.
        * g++.dg/cpp1z/decomp10.C: Likewise.
        * g++.dg/cpp1z/decomp32.C: New test.

--- gcc/cp/decl.c       (revision 255705)
+++ gcc/cp/decl.c       (revision 255706)
@@ -7446,11 +7446,20 @@ cp_finish_decomp (tree decl, tree first,
        {
        cnt_mismatch:
          if (count > eltscnt)
-           error_at (loc, "%u names provided while %qT decomposes into "
-                          "%wu elements", count, type, eltscnt);
+           error_n (loc, count,
+                    "%u name provided for structured binding",
+                    "%u names provided for structured binding", count);
          else
-           error_at (loc, "only %u names provided while %qT decomposes into "
-                          "%wu elements", count, type, eltscnt);
+           error_n (loc, count,
+                    "only %u name provided for structured binding",
+                    "only %u names provided for structured binding", count);
+         /* Some languages have special plural rules even for large values,
+            but it is periodic with period of 10, 100, 1000 etc.  */
+         inform_n (loc, eltscnt > INT_MAX
+                        ? (eltscnt % 1000000) + 1000000 : eltscnt,
+                   "while %qT decomposes into %wu element",
+                   "while %qT decomposes into %wu elements",
+                   type, eltscnt);
          goto error_out;
        }
       eltype = TREE_TYPE (type);
@@ -7519,6 +7528,15 @@ cp_finish_decomp (tree decl, tree first,
                         "constant expression", type);
          goto error_out;
        }
+      if (!tree_fits_uhwi_p (tsize))
+       {
+         error_n (loc, count,
+                  "%u name provided for structured binding",
+                  "%u names provided for structured binding", count);
+         inform (loc, "while %qT decomposes into %E elements",
+                 type, tsize);
+         goto error_out;
+       }
       eltscnt = tree_to_uhwi (tsize);
       if (count != eltscnt)
        goto cnt_mismatch;
--- gcc/testsuite/g++.dg/cpp1z/decomp3.C        (revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp3.C        (revision 255706)
@@ -51,16 +51,21 @@ int arr[4];
 void
 test3 (A &b, B c)
 {
-  auto [ d, e, f ] = arr;              // { dg-error "only 3 names provided 
while 'int .4.' decomposes into 4 elements" }
-                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
-  auto & [ g, h, i, j, k ] = arr;      // { dg-error "5 names provided while 
'int .4.' decomposes into 4 elements" }
-                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
-  auto [ l, m ] = b;                   // { dg-error "only 2 names provided 
while 'A' decomposes into 3 elements" }
-                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
-  auto & [ n, o, p, q ] = b;           // { dg-error "4 names provided while 
'A' decomposes into 3 elements" }
-                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
+  auto [ d, e, f ] = arr;              // { dg-error "only 3 names provided" }
+                                       // { dg-message "while 'int .4.' 
decomposes into 4 elements" "" { target *-*-* } .-1 }
+                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-2 }
+  auto & [ g, h, i, j, k ] = arr;      // { dg-error "5 names provided" }
+                                       // { dg-message "while 'int .4.' 
decomposes into 4 elements" "" { target *-*-* } .-1 }
+                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-2 }
+  auto [ l, m ] = b;                   // { dg-error "only 2 names provided" }
+                                       // { dg-message "while 'A' decomposes 
into 3 elements" "" { target *-*-* } .-1 }
+                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-2 }
+  auto & [ n, o, p, q ] = b;           // { dg-error "4 names provided" }
+                                       // { dg-message "while 'A' decomposes 
into 3 elements" "" { target *-*-* } .-1 }
+                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-2 }
   auto [] { c };                       // { dg-error "empty decomposition 
declaration" }
                                        // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
-  auto [ r, s ] = c;                   // { dg-error "2 names provided while 
'B' decomposes into 1 elements" }
-                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-1 }
+  auto [ r, s ] = c;                   // { dg-error "2 names provided" }
+                                       // { dg-message "while 'B' decomposes 
into 1 element" "" { target *-*-* } .-1 }
+                                       // { dg-warning "decomposition 
declaration only available with -std=c..1z or -std=gnu..1z" "" { target 
c++14_down } .-2 }
 }
--- gcc/testsuite/g++.dg/cpp1z/decomp10.C       (revision 255705)
+++ gcc/testsuite/g++.dg/cpp1z/decomp10.C       (revision 255706)
@@ -11,7 +11,8 @@ void f1() { auto [ x ] = a1; }        // { dg-e
 
 struct A2 { int i,j; } a2;
 template<> struct std::tuple_size<A2> { enum { value = 5 }; };
-void f2() { auto [ x ] = a2; } // { dg-error "decomposes into 5" }
+void f2() { auto [ x ] = a2; } // { dg-error "only 1 name provided" }
+                               // { dg-message "decomposes into 5" "" { target 
*-*-* } .-1 }
 
 struct A3 { int i,j; } a3;
 template<> struct std::tuple_size<A3> { enum { value = 1 }; };
--- gcc/testsuite/g++.dg/cpp1z/decomp32.C       (nonexistent)
+++ gcc/testsuite/g++.dg/cpp1z/decomp32.C       (revision 255706)
@@ -0,0 +1,32 @@
+// PR c++/83205
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A { int i; };
+struct B { int i; };
+namespace std {
+  template <typename T> struct tuple_size;
+  template <> struct tuple_size<A> {
+    static constexpr int value = -1;
+  };
+#ifdef __SIZEOF_INT128__
+  template <> struct tuple_size<B> {
+    static constexpr unsigned __int128 value = -1;
+  };
+#endif
+}
+
+auto [a] = A{};        // { dg-error "1 name provided" }
+               // { dg-message "while 'A' decomposes into -1 elements" "" { 
target *-*-* } .-1 }
+               // { dg-warning "decomposition declaration only available with" 
"" { target c++14_down } .-2 }
+#ifdef __SIZEOF_INT128__
+auto [b] = B{};        // { dg-error "1 name provided" "" { target int128 } }
+               // { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* 
elements" "" { target int128 } .-1 }
+               // { dg-warning "decomposition declaration only available with" 
"" { target { c++14_down && int128 } } .-2 }
+auto [c, d] = B{};     // { dg-error "2 names provided" "" { target int128 } }
+                       // { dg-message "while 'B' decomposes into 
\[0-9xa-fXA-F]* elements" "" { target int128 } .-1 }
+                       // { dg-warning "decomposition declaration only 
available with" "" { target { c++14_down && int128 } } .-2 }
+#endif
+auto [e, f, g] = A{};  // { dg-error "3 names provided" }
+                       // { dg-message "while 'A' decomposes into -1 elements" 
"" { target *-*-* } .-1 }
+                       // { dg-warning "decomposition declaration only 
available with" "" { target c++14_down } .-2 }

Reply via email to