From 34bbc4c502157fb08e6eba1d09380e2599ec3720 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 15 Jul 2016 14:38:15 -0400 Subject: [PATCH] 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 --- gcc/common.opt | 3 + gcc/cp/ChangeLog | 3 + gcc/cp/mangle.c | 71 ++++++++++++++++--- gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C | 11 +++ .../g++.dg/cpp0x/variadic-mangle1a.C | 12 ++++ gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C | 18 +++++ .../g++.dg/cpp0x/variadic-mangle2a.C | 19 +++++ gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C | 10 +++ .../g++.dg/cpp0x/variadic-mangle3a.C | 11 +++ libiberty/ChangeLog | 7 ++ libiberty/cp-demangle.c | 62 ++++++++++++++-- libiberty/testsuite/demangle-expected | 6 ++ 12 files changed, 218 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C diff --git a/gcc/common.opt b/gcc/common.opt index 2b68fa7bdee..b56ba47d0a7 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 1ef3812a82f..eb4f0b93531 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2016-07-15 Jason Merrill + 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 0e444097c19..8205da92a31 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 * 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 00000000000..51f9581c6d1 --- /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 struct A { }; +template void f(A); + +int main() +{ + f(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 00000000000..b230ffa6560 --- /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 struct A { }; +template void f(A); + +int main() +{ + f(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 00000000000..ea96ef87308 --- /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 using N = int[sizeof...(T)]; + template void f(N &); + + template using M = int[sizeof...(T)]; + template void g(M &); +}; +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(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 00000000000..3ac15176704 --- /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 using N = int[sizeof...(T)]; + template void f(N &); + + template using M = int[sizeof...(T)]; + template void g(M &); +}; +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(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 00000000000..f239ef717de --- /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 using N = int[sizeof...(T)]; + template + void f(N &, B, C...); +}; +void g(A a) { int arr[6]; a.f(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 00000000000..eba8f591c3e --- /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 using N = int[sizeof...(T)]; + template + void f(N &, B, C...); +}; +void g(A a) { int arr[6]; a.f(arr, 1, 2, 3, 4); } diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 317bd63c054..3b50cdcd5b4 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2016-07-15 Jason Merrill + + * 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 PR c++/70926 diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 7f664b9c5c0..56d3bcb28fd 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 }, @@ -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); +} + +/* * 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 diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 1d959528b97..92ad01f6e61 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4536,6 +4536,12 @@ void baz(A*) --format=gnu-v3 _Z3fooI1FEN1XIXszdtcl1PclcvT__EEE5arrayEE4TypeEv X::Type foo() + +_Z1fIJidEEv1AIXsZT_EE +void f(A<2>) + +_ZN1A1fIJiiEiJiiiEEEvRAsPDpT_T0_DpT1_E_iS3_S5_ +void A::f(int (&) [6], int, int, int, int) # # Tests a use-after-free problem PR70481 -- 2.30.2