aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-07-15 14:38:15 -0400
committerJason Merrill <jason@gcc.gnu.org>2016-07-15 14:38:15 -0400
commit34bbc4c502157fb08e6eba1d09380e2599ec3720 (patch)
tree1ee707547ea5521e317e522ed83b170324ec4a05
parentd022c55a4b8bdac385efadf42ba2a374c5960418 (diff)
downloadgcc-34bbc4c502157fb08e6eba1d09380e2599ec3720.zip
gcc-34bbc4c502157fb08e6eba1d09380e2599ec3720.tar.gz
gcc-34bbc4c502157fb08e6eba1d09380e2599ec3720.tar.bz2
PR c++/71814 - mangling sizeof... (sP and sZ)
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
-rw-r--r--gcc/common.opt3
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/mangle.c71
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C11
-rw-r--r--libiberty/ChangeLog7
-rw-r--r--libiberty/cp-demangle.c62
-rw-r--r--libiberty/testsuite/demangle-expected6
12 files changed, 218 insertions, 15 deletions
diff --git a/gcc/common.opt b/gcc/common.opt
index 2b68fa7..b56ba47 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -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=
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1ef3812..eb4f0b9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 0e44409..8205da9 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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
index 0000000..51f9581
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C
@@ -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
index 0000000..b230ffa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C
@@ -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
index 0000000..ea96ef8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C
@@ -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
index 0000000..3ac1517
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C
@@ -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
index 0000000..f239ef7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C
@@ -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
index 0000000..eba8f59
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C
@@ -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); }
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 317bd63..3b50cdc 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -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
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 7f664b9..56d3bcb 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -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 },
@@ -2995,6 +2998,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;
struct demangle_component **pal;
@@ -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
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 1d95952..92ad01f 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -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