diff options
author | Jason Merrill <jason@redhat.com> | 2016-07-15 14:38:15 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-07-15 14:38:15 -0400 |
commit | 34bbc4c502157fb08e6eba1d09380e2599ec3720 (patch) | |
tree | 1ee707547ea5521e317e522ed83b170324ec4a05 | |
parent | d022c55a4b8bdac385efadf42ba2a374c5960418 (diff) | |
download | gcc-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.opt | 3 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 71 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle1.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle1a.C | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle2.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle2a.C | 19 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle3.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/variadic-mangle3a.C | 11 | ||||
-rw-r--r-- | libiberty/ChangeLog | 7 | ||||
-rw-r--r-- | libiberty/cp-demangle.c | 62 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 6 |
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 |