]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/71814 - mangling sizeof... (sP and sZ)
authorJason Merrill <jason@redhat.com>
Fri, 15 Jul 2016 18:38:15 +0000 (14:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 15 Jul 2016 18:38:15 +0000 (14:38 -0400)
gcc/cp/
* mangle.c (write_expression): Handle sizeof... an argument pack.
libiberty/
* cp-demangle.c (cplus_demangle_operators): Add sP and sZ.
(d_print_comp_inner): Handle them.
(d_template_args_1): Split out from d_template_args.
(d_args_length): New.

From-SVN: r238389

12 files changed:
gcc/common.opt
gcc/cp/ChangeLog
gcc/cp/mangle.c
gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C [new file with mode: 0644]
libiberty/ChangeLog
libiberty/cp-demangle.c
libiberty/testsuite/demangle-expected

index 2b68fa7bdee090b1ff4737b815079c789d752c61..b56ba47d0a7b796247cc14660ea2ac2c774489c9 100644 (file)
@@ -882,6 +882,9 @@ Driver Undocumented
 ;     identity, such as ia32 calling convention attributes (stdcall, etc.)
 ;     Default in G++ 6 (set in c_common_post_options).
 ;
+; 11: The version of the ABI that corrects mangling of sizeof... expressions.
+;     Default in G++ 7.
+;
 ; Additional positive integers will be assigned as new versions of
 ; the ABI become the default version of the ABI.
 fabi-version=
index 1ef3812a82fe9be4e85b1f2e2f6966d32c9724d3..eb4f0b93531eccfee9f98451955322ed019c8cde 100644 (file)
@@ -1,5 +1,8 @@
 2016-07-15  Jason Merrill  <jason@redhat.com>
 
+       PR c++/71814
+       * mangle.c (write_expression): Handle sizeof... an argument pack.
+
        PR c++/71718
        * pt.c (push_tinst_level_loc): Set at_eof before fatal_error.
 
index 0e444097c19ecbe0bf75aa32db237371a10f3ac2..8205da92a31fcabbc176f5059ade27b6dd9f5af5 100644 (file)
@@ -2767,17 +2767,67 @@ write_expression (tree expr)
       write_mangled_name (expr, false);
       write_char ('E');
     }
-  else if (TREE_CODE (expr) == SIZEOF_EXPR
-          && SIZEOF_EXPR_TYPE_P (expr))
+  else if (TREE_CODE (expr) == SIZEOF_EXPR)
     {
-      write_string ("st");
-      write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
-    }
-  else if (TREE_CODE (expr) == SIZEOF_EXPR
-          && TYPE_P (TREE_OPERAND (expr, 0)))
-    {
-      write_string ("st");
-      write_type (TREE_OPERAND (expr, 0));
+      tree op = TREE_OPERAND (expr, 0);
+
+      if (PACK_EXPANSION_P (op))
+       {
+         if (abi_warn_or_compat_version_crosses (11))
+           G.need_abi_warning = true;
+         if (abi_version_at_least (11))
+           {
+             /* sZ rather than szDp.  */
+             write_string ("sZ");
+             write_expression (PACK_EXPANSION_PATTERN (op));
+             return;
+           }
+       }
+
+      if (SIZEOF_EXPR_TYPE_P (expr))
+       {
+         write_string ("st");
+         write_type (TREE_TYPE (op));
+       }
+      else if (ARGUMENT_PACK_P (op))
+       {
+         tree args = ARGUMENT_PACK_ARGS (op);
+         int length = TREE_VEC_LENGTH (args);
+         if (abi_warn_or_compat_version_crosses (10))
+           G.need_abi_warning = true;
+         if (abi_version_at_least (10))
+           {
+             /* sP <template-arg>* E # sizeof...(T), size of a captured
+                template parameter pack from an alias template */
+             write_string ("sP");
+             for (int i = 0; i < length; ++i)
+               write_template_arg (TREE_VEC_ELT (args, i));
+             write_char ('E');
+           }
+         else
+           {
+             /* In GCC 5 we represented this sizeof wrong, with the effect
+                that we mangled it as the last element of the pack.  */
+             tree arg = TREE_VEC_ELT (args, length-1);
+             if (TYPE_P (op))
+               {
+                 write_string ("st");
+                 write_type (arg);
+               }
+             else
+               {
+                 write_string ("sz");
+                 write_expression (arg);
+               }
+           }
+       }
+      else if (TYPE_P (TREE_OPERAND (expr, 0)))
+       {
+         write_string ("st");
+         write_type (TREE_OPERAND (expr, 0));
+       }
+      else
+       goto normal_expr;
     }
   else if (TREE_CODE (expr) == ALIGNOF_EXPR
           && TYPE_P (TREE_OPERAND (expr, 0)))
@@ -2947,6 +2997,7 @@ write_expression (tree expr)
     }
   else
     {
+    normal_expr:
       int i, len;
       const char *name;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C
new file mode 100644 (file)
index 0000000..51f9581
--- /dev/null
@@ -0,0 +1,11 @@
+// Test for sZ mangling.
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z1fIJidEEv1AIXsZT_EE" } }
+
+template <int I> struct A { };
+template <typename... Ts> void f(A<sizeof...(Ts)>);
+
+int main()
+{
+  f<int,double>(A<2>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C
new file mode 100644 (file)
index 0000000..b230ffa
--- /dev/null
@@ -0,0 +1,12 @@
+// Test for sZ mangling.
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z1fIJidEEv1AIXstDpT_EE" } }
+// { dg-options -fabi-version=9 }
+
+template <int I> struct A { };
+template <typename... Ts> void f(A<sizeof...(Ts)>);
+
+int main()
+{
+  f<int,double>(A<2>());
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C
new file mode 100644 (file)
index 0000000..ea96ef8
--- /dev/null
@@ -0,0 +1,18 @@
+// Testcase from cxx-abi-dev.
+// { dg-do compile { target c++11 } }
+
+struct A {
+  template<int...T> using N = int[sizeof...(T)];
+  template<int...A> void f(N<A...> &);
+
+  template<typename...T> using M = int[sizeof...(T)];
+  template<typename...A> void g(M<A...> &);
+};
+void g(A a)
+{
+  int arr[3];
+  // { dg-final { scan-assembler "_ZN1A1fIJLi1ELi2ELi3EEEEvRAsZT__i" } }
+  a.f<1,2,3>(arr);
+  // { dg-final { scan-assembler "_ZN1A1gIJiiiEEEvRAsZT__i" } }
+  a.g<int,int,int>(arr);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C
new file mode 100644 (file)
index 0000000..3ac1517
--- /dev/null
@@ -0,0 +1,19 @@
+// Testcase from cxx-abi-dev.
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=9" }
+
+struct A {
+  template<int...T> using N = int[sizeof...(T)];
+  template<int...A> void f(N<A...> &);
+
+  template<typename...T> using M = int[sizeof...(T)];
+  template<typename...A> void g(M<A...> &);
+};
+void g(A a)
+{
+  int arr[3];
+  // { dg-final { scan-assembler "_ZN1A1fIJLi1ELi2ELi3EEEEvRAszspT__i" } }
+  a.f<1,2,3>(arr);
+  // { dg-final { scan-assembler "_ZN1A1gIJiiiEEEvRAstDpT__i" } }
+  a.g<int,int,int>(arr);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C
new file mode 100644 (file)
index 0000000..f239ef7
--- /dev/null
@@ -0,0 +1,10 @@
+// Testcase from cxx-abi-dev.
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_ZN1A1fIJiiEiJiiiEEEvRAsPDpT_T0_DpT1_E_iS3_S5_" } }
+
+struct A {
+  template<typename...T> using N = int[sizeof...(T)];
+  template<typename...A, typename B, typename...C>
+      void f(N<A..., B, C...> &, B, C...);
+};
+void g(A a) { int arr[6]; a.f<int, int>(arr, 1, 2, 3, 4); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C
new file mode 100644 (file)
index 0000000..eba8f59
--- /dev/null
@@ -0,0 +1,11 @@
+// Testcase from cxx-abi-dev.
+// { dg-do compile { target c++11 } }
+// { dg-options -fabi-version=9 }
+// { dg-final { scan-assembler "_ZN1A1fIJiiEiJiiiEEEvRAstDpT1__iT0_S2_" } }
+
+struct A {
+  template<typename...T> using N = int[sizeof...(T)];
+  template<typename...A, typename B, typename...C>
+      void f(N<A..., B, C...> &, B, C...);
+};
+void g(A a) { int arr[6]; a.f<int, int>(arr, 1, 2, 3, 4); }
index 317bd63c0544f167b29327f6aa0d8743b0a3ac8f..3b50cdcd5b49efc5d7bcfaf80101bb4e370f9d94 100644 (file)
@@ -1,3 +1,10 @@
+2016-07-15  Jason Merrill  <jason@redhat.com>
+
+       * cp-demangle.c (cplus_demangle_operators): Add sP and sZ.
+       (d_print_comp_inner): Handle them.
+       (d_template_args_1): Split out from d_template_args.
+       (d_args_length): New.
+
 2016-07-13  Marcel BÃhme  <boehme.marcel@gmail.com>
 
        PR c++/70926
index 7f664b9c5c0d13342d94a272bb3e312fb665a35a..56d3bcb28fd33e4ca3cdc48f82fdfbae20a0d99d 100644 (file)
@@ -466,6 +466,7 @@ static struct demangle_component *
 d_template_param (struct d_info *);
 
 static struct demangle_component *d_template_args (struct d_info *);
+static struct demangle_component *d_template_args_1 (struct d_info *);
 
 static struct demangle_component *
 d_template_arg (struct d_info *);
@@ -1795,6 +1796,8 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "rc", NL ("reinterpret_cast"), 2 },
   { "rm", NL ("%"),         2 },
   { "rs", NL (">>"),        2 },
+  { "sP", NL ("sizeof..."), 1 },
+  { "sZ", NL ("sizeof..."), 1 },
   { "sc", NL ("static_cast"), 2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
@@ -2994,6 +2997,19 @@ d_template_param (struct d_info *di)
 
 static struct demangle_component *
 d_template_args (struct d_info *di)
+{
+  if (d_peek_char (di) != 'I'
+      && d_peek_char (di) != 'J')
+    return NULL;
+  d_advance (di, 1);
+
+  return d_template_args_1 (di);
+}
+
+/* <template-arg>* E  */
+
+static struct demangle_component *
+d_template_args_1 (struct d_info *di)
 {
   struct demangle_component *hold_last_name;
   struct demangle_component *al;
@@ -3004,11 +3020,6 @@ d_template_args (struct d_info *di)
      constructor or destructor.  */
   hold_last_name = di->last_name;
 
-  if (d_peek_char (di) != 'I'
-      && d_peek_char (di) != 'J')
-    return NULL;
-  d_advance (di, 1);
-
   if (d_peek_char (di) == 'E')
     {
       /* An argument pack can be empty.  */
@@ -3270,6 +3281,8 @@ d_expression_1 (struct d_info *di)
            if (op->type == DEMANGLE_COMPONENT_CAST
                && d_check_char (di, '_'))
              operand = d_exprlist (di, 'E');
+           else if (code && !strcmp (code, "sP"))
+             operand = d_template_args_1 (di);
            else
              operand = d_expression_1 (di);
 
@@ -4289,6 +4302,30 @@ d_pack_length (const struct demangle_component *dc)
   return count;
 }
 
+/* Returns the number of template args in DC, expanding any pack expansions
+   found there.  */
+
+static int
+d_args_length (struct d_print_info *dpi, const struct demangle_component *dc)
+{
+  int count = 0;
+  for (; dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST;
+       dc = d_right (dc))
+    {
+      struct demangle_component *elt = d_left (dc);
+      if (elt == NULL)
+       break;
+      if (elt->type == DEMANGLE_COMPONENT_PACK_EXPANSION)
+       {
+         struct demangle_component *a = d_find_pack (dpi, d_left (elt));
+         count += d_pack_length (a);
+       }
+      else
+       ++count;
+    }
+  return count;
+}
+
 /* DC is a component of a mangled expression.  Print it, wrapped in parens
    if needed.  */
 
@@ -5125,6 +5162,21 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
              }
          }
 
+       /* For sizeof..., just print the pack length.  */
+       if (code && !strcmp (code, "sZ"))
+         {
+           struct demangle_component *a = d_find_pack (dpi, operand);
+           int len = d_pack_length (a);
+           d_append_num (dpi, len);
+           return;
+         }
+       else if (code && !strcmp (code, "sP"))
+         {
+           int len = d_args_length (dpi, operand);
+           d_append_num (dpi, len);
+           return;
+         }
+
        if (op->type != DEMANGLE_COMPONENT_CAST)
          d_print_expr_op (dpi, options, op);
        else
index 1d959528b97be708e443e71f443f4b74d317bbe4..92ad01f6e61ee9e274f14a6d2348877b5a1181dd 100644 (file)
@@ -4536,6 +4536,12 @@ void baz<int>(A<sizeof (foo((int)(), (floatcomplex )00000000_00000000))>*)
 --format=gnu-v3
 _Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv
 X<sizeof ((P(((F)())())).array)>::Type foo<F>()
+
+_Z1fIJidEEv1AIXsZT_EE
+void f<int, double>(A<2>)
+
+_ZN1A1fIJiiEiJiiiEEEvRAsPDpT_T0_DpT1_E_iS3_S5_
+void A::f<int, int, int, int, int, int>(int (&) [6], int, int, int, int)
 #
 # Tests a use-after-free problem PR70481