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 /gcc | |
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
Diffstat (limited to 'gcc')
-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 |
9 files changed, 148 insertions, 10 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); } |