From 187c6369c0b4c7e013fdbe9eb08d098166359056 Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Thu, 4 Apr 2019 23:10:23 +0000 Subject: [PATCH] PR c++/89974 - ICE on a definition of a non-type specialization on a struct object with pointer to member function PR c++/89974 - ICE on a definition of a non-type specialization on a struct object with pointer to member function PR c++/89878 - same specializations on a zero-initialized struct object as a non-type parameter treated as distinct PR c++/89833 - sorry, unimplemented: string literal in function template signature PR c++/47488 - sorry, unimplemented: string literal in function template signature gcc/cp/ChangeLog: PR c++/89974 PR c++/89878 PR c++/89833 PR c++/47488 * decl.c (reshape_init_array_1): Strip trailing zero-initializers from arrays of trivial type and known size. * mangle.c (write_expression): Convert braced initializer lists to STRING_CSTs. (write_expression): Trim trailing zero-initializers from arrays of trivial type. (write_template_arg_literal): Mangle strings the same as braced initializer lists. gcc/testsuite/ChangeLog: PR c++/89974 PR c++/89878 PR c++/89833 PR c++/47488 * gcc/testsuite/g++.dg/abi/mangle69.C: New test. * gcc/testsuite/g++.dg/abi/mangle70.C: New test. * gcc/testsuite/g++.dg/abi/mangle71.C: New test. * gcc/testsuite/g++.dg/abi/mangle72.C: New test. * gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C: New test. * gcc/testsuite/g++.dg/cpp2a/nontype-class15.C: New test. * gcc/testsuite/g++.dg/cpp2a/nontype-class16.C: New test. * gcc/testsuite/g++.dg/init/array51.C: New test. From-SVN: r270155 --- gcc/cp/ChangeLog | 15 ++ gcc/cp/decl.c | 22 ++ gcc/cp/mangle.c | 79 ++++++- gcc/testsuite/ChangeLog | 16 ++ gcc/testsuite/g++.dg/abi/mangle69.C | 164 +++++++++++++ gcc/testsuite/g++.dg/abi/mangle70.C | 29 +++ gcc/testsuite/g++.dg/abi/mangle71.C | 28 +++ gcc/testsuite/g++.dg/abi/mangle72.C | 106 +++++++++ .../g++.dg/cpp0x/constexpr-array19.C | 137 +++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class15.C | 222 ++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class16.C | 57 +++++ gcc/testsuite/g++.dg/init/array51.C | 86 +++++++ gcc/testsuite/g++.dg/template/nontype29.C | 81 +++++++ 13 files changed, 1032 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/mangle69.C create mode 100644 gcc/testsuite/g++.dg/abi/mangle70.C create mode 100644 gcc/testsuite/g++.dg/abi/mangle71.C create mode 100644 gcc/testsuite/g++.dg/abi/mangle72.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class15.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class16.C create mode 100644 gcc/testsuite/g++.dg/init/array51.C create mode 100644 gcc/testsuite/g++.dg/template/nontype29.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 888b431e099..729b7732565 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2019-04-04 Martin Sebor + + PR c++/89974 + PR c++/89878 + PR c++/89833 + PR c++/47488 + * decl.c (reshape_init_array_1): Strip trailing zero-initializers + from arrays of trivial type and known size. + * mangle.c (write_expression): Convert braced initializer lists + to STRING_CSTs. + (write_expression): Trim trailing zero-initializers from arrays + of trivial type. + (write_template_arg_literal): Mangle strings the same as braced + initializer lists. + 2019-04-03 Jason Merrill PR c++/81866 - ICE with member template and default targ. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c46a39665bd..400e1a274aa 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5799,6 +5799,9 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, max_index_cst = tree_to_uhwi (fold_convert (size_type_node, max_index)); } + /* Set to the index of the last element with a non-zero initializer. + Initializers for elements past this one can be dropped. */ + unsigned HOST_WIDE_INT last_nonzero = -1; /* Loop until there are no more initializers. */ for (index = 0; d->cur != d->end && (!sized_array_p || index <= max_index_cst); @@ -5817,11 +5820,30 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, if (!TREE_CONSTANT (elt_init)) TREE_CONSTANT (new_init) = false; + if (!initializer_zerop (elt_init)) + last_nonzero = index; + /* This can happen with an invalid initializer (c++/54501). */ if (d->cur == old_cur && !sized_array_p) break; } + if (sized_array_p + && (!CLASS_TYPE_P (elt_type) + || TYPE_HAS_TRIVIAL_DFLT (elt_type))) + { + /* Strip trailing zero-initializers from an array of a trivial + type of known size. They are redundant and get in the way + of telling them apart from those with implicit zero value. */ + unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init); + if (last_nonzero > nelts) + nelts = 0; + else if (last_nonzero < nelts - 1) + nelts = last_nonzero + 1; + + vec_safe_truncate (CONSTRUCTOR_ELTS (new_init), nelts); + } + return new_init; } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index f40c3e16c5d..a5fd66fe0de 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3136,18 +3136,48 @@ write_expression (tree expr) } else if (code == CONSTRUCTOR) { - vec *elts = CONSTRUCTOR_ELTS (expr); - unsigned i; tree val; + bool braced_init = BRACE_ENCLOSED_INITIALIZER_P (expr); + tree etype = TREE_TYPE (expr); - if (BRACE_ENCLOSED_INITIALIZER_P (expr)) + if (braced_init) write_string ("il"); else { write_string ("tl"); - write_type (TREE_TYPE (expr)); + write_type (etype); + } + + if (!initializer_zerop (expr) || !trivial_type_p (etype)) + { + /* Convert braced initializer lists to STRING_CSTs so that + A<"Foo"> mangles the same as A<{'F', 'o', 'o', 0}> while + still using the latter mangling for strings that + originated as braced initializer lists. */ + expr = braced_lists_to_strings (etype, expr); + + if (TREE_CODE (expr) == CONSTRUCTOR) + { + vec *elts = CONSTRUCTOR_ELTS (expr); + unsigned last_nonzero = -1, i; + tree val; + + FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) + if (!initializer_zerop (val)) + last_nonzero = i; + + FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) + { + if (i > last_nonzero) + break; + write_expression (val); + } + } + else + { + gcc_assert (TREE_CODE (expr) == STRING_CST); + write_expression (expr); + } } - FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) - write_expression (val); write_char ('E'); } else if (code == LAMBDA_EXPR) @@ -3353,8 +3383,14 @@ write_expression (tree expr) static void write_template_arg_literal (const tree value) { - write_char ('L'); - write_type (TREE_TYPE (value)); + if (TREE_CODE (value) == STRING_CST) + /* Temporarily mangle strings as braced initializer lists. */ + write_string ("tl"); + else + write_char ('L'); + + tree valtype = TREE_TYPE (value); + write_type (valtype); /* Write a null member pointer value as (type)0, regardless of its real representation. */ @@ -3397,8 +3433,31 @@ write_template_arg_literal (const tree value) break; case STRING_CST: - sorry ("string literal in function template signature"); - break; + { + /* Mangle strings the same as braced initializer lists. */ + unsigned n = TREE_STRING_LENGTH (value); + const char *str = TREE_STRING_POINTER (value); + + /* Count the number of trailing nuls and subtract them from + STRSIZE because they don't need to be mangled. */ + for (const char *p = str + n - 1; ; --p) + { + if (*p || p == str) + { + n -= str + n - !!*p - p; + break; + } + } + tree eltype = TREE_TYPE (valtype); + for (const char *p = str; n--; ++p) + { + write_char ('L'); + write_type (eltype); + write_unsigned_number (*(const unsigned char*)p); + write_string ("E"); + } + break; + } default: gcc_unreachable (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6954748fa15..26c5637619f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2019-04-04 Martin Sebor + + PR c++/89974 + PR c++/89878 + PR c++/89833 + PR c++/47488 + * gcc/testsuite/g++.dg/abi/mangle69.C: New test. + * gcc/testsuite/g++.dg/abi/mangle70.C: New test. + * gcc/testsuite/g++.dg/abi/mangle71.C: New test. + * gcc/testsuite/g++.dg/abi/mangle72.C: New test. + * gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C: New test. + * gcc/testsuite/g++.dg/cpp2a/nontype-class15.C: New test. + * gcc/testsuite/g++.dg/cpp2a/nontype-class16.C: New test. + * gcc/testsuite/g++.dg/init/array51.C: New test. + * gcc/testsuite/g++.dg/template/nontype29.C: New test. + 2019-04-04 Martin Sebor PR middle-end/89957 diff --git a/gcc/testsuite/g++.dg/abi/mangle69.C b/gcc/testsuite/g++.dg/abi/mangle69.C new file mode 100644 index 00000000000..dea3eeca022 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle69.C @@ -0,0 +1,164 @@ +// { dg-do compile { target c++2a } } + +struct A1 { char c[5]; }; + +template struct B { }; + +// All of the following name the same type. +typedef B A______; +typedef B A_Z____; +typedef B A_ZZ___; +typedef B A_ZZZ__; +typedef B A_ZZZZ_; +typedef B A_ZZZZZ; + +// Verify that the types mangle the same. +void a______ (A______) { } +// { dg-final { scan-assembler "_Z7a______1BIXtl2A1EEE" } } + +void a_z____ (A_Z____) { } +// { dg-final { scan-assembler "_Z7a_z____1BIXtl2A1EEE" } } + +void a_zz___ (A_ZZ___) { } +// { dg-final { scan-assembler "_Z7a_zz___1BIXtl2A1EEE" } } + +void a_zzz__ (A_ZZZ__) { } +// { dg-final { scan-assembler "_Z7a_zzz__1BIXtl2A1EEE" } } + +void a_zzzz_ (A_ZZZZ_) { } +// { dg-final { scan-assembler "_Z7a_zzzz_1BIXtl2A1EEE" } } + +void a_zzzzz (A_ZZZZZ) { } +// { dg-final { scan-assembler "_Z7a_zzzzz1BIXtl2A1EEE" } } + + +// All of the following use a string to initialize the array but +// also name the same type as the above. +typedef B S_z____; +typedef B S_Zz___; +typedef B S_ZZz__; +typedef B S_ZZZz_; +typedef B S_ZZZZz; + +// Verify that the types mangle the same. +void s_z____ (S_z____) { } +// { dg-final { scan-assembler "_Z7s_z____1BIXtl2A1EEE" } } + +void s_Zz___ (S_Zz___) { } +// { dg-final { scan-assembler "_Z7s_Zz___1BIXtl2A1EEE" } } + +void s_ZZz__ (S_ZZz__) { } +// { dg-final { scan-assembler "_Z7s_ZZz__1BIXtl2A1EEE" } } + +void s_ZZZz_ (S_ZZZz_) { } +// { dg-final { scan-assembler "_Z7s_ZZZz_1BIXtl2A1EEE" } } + +void s_ZZZZz (S_ZZZZz) { } +// { dg-final { scan-assembler "_Z7s_ZZZZz1BIXtl2A1EEE" } } + + +// All of the following also name the same type (distinct from +// the above). +typedef B A_A____; +typedef B A_AZ___; +typedef B A_AZZ__; +typedef B A_AZZZ_; +typedef B A_AZZZZ; + +void a_A____ (A_A____) { } +// { dg-final { scan-assembler "_Z7a_A____1BIXtl2A1tlA5_cLc65EEEEE" } } + +void a_AZ___ (A_AZ___) { } +// { dg-final { scan-assembler "_Z7a_AZ___1BIXtl2A1tlA5_cLc65EEEEE" } } + +void a_AZZ__ (A_AZZ__) { } +// { dg-final { scan-assembler "_Z7a_AZZ__1BIXtl2A1tlA5_cLc65EEEEE" } } + +void a_AZZZ_ (A_AZZZ_) { } +// { dg-final { scan-assembler "_Z7a_AZZZ_1BIXtl2A1tlA5_cLc65EEEEE" } } + +void a_AZZZZ (A_AZZZZ) { } +// { dg-final { scan-assembler "_Z7a_AZZZZ1BIXtl2A1tlA5_cLc65EEEEE" } } + + +typedef B S_Az___; +typedef B S_AZz__; +typedef B S_AZZz_; +typedef B S_AZZZz; + +void s_Az___ (S_Az___) { } +// { dg-final { scan-assembler "_Z7s_Az___1BIXtl2A1tlA5_cLc65EEEEE" } } + +void s_AZz__ (S_AZz__) { } +// { dg-final { scan-assembler "_Z7s_AZz__1BIXtl2A1tlA5_cLc65EEEEE" } } + +void s_AZZz_ (S_AZZz_) { } +// { dg-final { scan-assembler "_Z7s_AZZz_1BIXtl2A1tlA5_cLc65EEEEE" } } + +void s_AZZZz (S_AZZZz) { } +// { dg-final { scan-assembler "_Z7s_AZZZz1BIXtl2A1tlA5_cLc65EEEEE" } } + + +typedef B A_AZZDZ; +typedef B A_AZZD_; + +void a_AZZDZ (A_AZZDZ) { } +// { dg-final { scan-assembler "_Z7a_AZZD_1BIXtl2A1tlA5_cLc65ELc0ELc0ELc68EEEEE" } } + +void a_AZZD_ (A_AZZD_) { } +// { dg-final { scan-assembler "_Z7a_AZZDZ1BIXtl2A1tlA5_cLc65ELc0ELc0ELc68EEEEE" } } + + +typedef B S_ABZD_; +typedef B S_ABZZ_; +typedef B S_ABZ__; +typedef B S_AB___; + +void s_abzd_ (S_ABZD_) { } +// { dg-final { scan-assembler "_Z7s_abzd_1BIXtl2A1tlA5_cLc65ELc66ELc0ELc68EEEEE" } } + +void s_abzz_ (S_ABZZ_) { } +// { dg-final { scan-assembler "_Z7s_abzz_1BIXtl2A1tlA5_cLc65ELc66EEEEE" } } + +void s_abz__ (S_ABZ__) { } +// { dg-final { scan-assembler "_Z7s_abz__1BIXtl2A1tlA5_cLc65ELc66EEEEE" } } + +void s_ab___ (S_AB___) { } +// { dg-final { scan-assembler "_Z7s_ab___1BIXtl2A1tlA5_cLc65ELc66EEEEE" } } + + +struct A3 { char a[5], b[5], c[5]; }; +template struct B3 { }; + +/* These all name the same type. */ +typedef B3 T_123z_______3456z; +typedef B3 T_123z__Z____3456z; +typedef B3 T_123z__ZZ___3456z; +typedef B3 T_123z__ZZZ__3456z; +typedef B3 T_123z__ZZZZ_3456z; +typedef B3 T_123z__Z____3456z; +typedef B3 T_123z__ZZ___3456z; +typedef B3 T_123z__ZZZ__3456z; +typedef B3 T_123z__ZZZZ_3456z; +typedef B3 T_123z__ZZZZZ3456z; +typedef B3 T_123Zz_ZZZZZ3456z; +typedef B3 T_123ZZzZZZZZ3456z; + + +void ft0 (T_123z_______3456z) { } +// { dg-final { scan-assembler "_Z3ft02B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } + +void ft1 (T_123z__Z____3456z) { } +// { dg-final { scan-assembler "_Z3ft12B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void ft2 (T_123z__ZZ___3456z) { } +// { dg-final { scan-assembler "_Z3ft22B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void ft3 (T_123z__ZZZ__3456z) { } +// { dg-final { scan-assembler "_Z3ft32B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void ft4 (T_123z__ZZZZ_3456z) { } +// { dg-final { scan-assembler "_Z3ft42B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void ft9 (T_123z__ZZZZZ3456z) { } +// { dg-final { scan-assembler "_Z3ft92B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void fta (T_123Zz_ZZZZZ3456z) { } +// { dg-final { scan-assembler "_Z3fta2B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } +void ftb (T_123ZZzZZZZZ3456z) { } +// { dg-final { scan-assembler "_Z3ftb2B3IXtl2A3tlA5_cLc1ELc2EEtlS1_EtlS1_Lc3ELc4ELc5ELc6EEEEE" } } diff --git a/gcc/testsuite/g++.dg/abi/mangle70.C b/gcc/testsuite/g++.dg/abi/mangle70.C new file mode 100644 index 00000000000..39c987d73c2 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle70.C @@ -0,0 +1,29 @@ +// Verify that class literals are mangled the same way regardless +// of the underlying type. +// { dg-do compile { target c++2a } } + +struct I { int a[5], b[5], c[5]; }; +template struct X { }; + +typedef X Ti; +void f (Ti) { } +// { dg-final { scan-assembler "_Z1f1XIXtl1ItlA5_iLi1ELi2EEtlS1_EtlS1_Li11ELi12ELi13ELi14EEEEE" } } + +struct C { char a[5], b[5], c[5]; }; +template struct Y { }; + +typedef Y Tca; +void g (Tca) { } +// { dg-final { scan-assembler "_Z1g1YIXtl1CtlA5_cLc1ELc2EEtlS1_EtlS1_Lc11ELc12ELc13ELc14EEEEE" } } + +typedef Y Tcs; +void h (Tcs) { } +// { dg-final { scan-assembler "_Z1h1YIXtl1CtlA5_cLc1ELc2EEtlS1_EtlS1_Lc11ELc12ELc13ELc14EEEEE" } } + +struct S { signed char a[5], b[5], c[5]; }; +template struct Z { }; + +typedef Z Tsc; + +void i (Tsc) { } +// { dg-final { scan-assembler "_Z1i1ZIXtl1StlA5_aLa1ELa2EEtlS1_EtlS1_La11ELa12ELa13ELa14EEEEE" } } diff --git a/gcc/testsuite/g++.dg/abi/mangle71.C b/gcc/testsuite/g++.dg/abi/mangle71.C new file mode 100644 index 00000000000..cb9d7d3a1d8 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle71.C @@ -0,0 +1,28 @@ +// Verify manglinng of class literals of types with ctors. +// { dg-do compile { target c++2a } } + +struct A +{ + char i; + constexpr A (): i (1) { } + constexpr A (int i): i (i) { } +}; + +struct B { A a[3]; }; + +template struct X { }; + +void f___ (X) { } +// { dg-final { scan-assembler "_Z4f___1XIXtl1BtlA3_1AtlS1_Lc1EEEEEE" } } + +void f0__ (X) { } +// { dg-final { scan-assembler "_Z4f0__1XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc1EEEEEE" } } + +void f00_ (X) { } +// { dg-final { scan-assembler "_Z4f00_1XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc0EEtlS1_Lc1EEEEEE" } } + +void f000 (X) { } +// { dg-final { scan-assembler "_Z4f0001XIXtl1BtlA3_1AtlS1_Lc0EEtlS1_Lc0EEtlS1_Lc0EEEEEE" } } + +void f1__ (X) { } +// { dg-final { scan-assembler "_Z4f1__1XIXtl1BtlA3_1AtlS1_Lc1EEtlS1_Lc1EEEEEE" } } diff --git a/gcc/testsuite/g++.dg/abi/mangle72.C b/gcc/testsuite/g++.dg/abi/mangle72.C new file mode 100644 index 00000000000..656a0cae403 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle72.C @@ -0,0 +1,106 @@ +// Verify manglinng of class literals with pointers to members. +// Some of the mangling here is wrong. Note the FIXME comments below. +// { dg-do compile { target c++2a } } + +struct A { int a[2]; }; + +template struct X { }; + +// Let's mangle some non-member pointer literals for comparison. +void f__ (X) { } +// { dg-final { scan-assembler "_Z3f001XIXtl1AEEE" } } + +void f0_ (X) { } +// { dg-final { scan-assembler "_Z3f0_1XIXtl1AEEE" } } + +void f00 (X) { } +// { dg-final { scan-assembler "_Z3f__1XIXtl1AEEE" } } + + +// Exercise arrays of pointers to data members. +typedef int (A::*padm_t)[2]; + +struct B { padm_t a[2]; }; +template struct Y { }; + +void g__ (Y) { } +// { dg-final { scan-assembler "_Z3g__1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } } + +void g0_ (Y) { } +// { dg-final { scan-assembler "_Z3g0_1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } } + +void g00 (Y) { } +// { dg-final { scan-assembler "_Z3g001YIXtl1BtlA2_M1AA2_iLS3_0EEEEE" } } + +void g0x (Y) { } +// FIXME: This needs to mangle differently from g00. The space at +// the end is intentional to make the directive fail so that the xfail +// can be reminder to change this once the mangling is fixed. +// { dg-final { scan-assembler "_Z3g0x1YIXtl1BtlA2_M1AA2_iLS3_0EEEEE " { xfail *-*-* } } } + +void gx_ (Y) { } +// { dg-final { scan-assembler "_Z3gx_1YIXtl1BtlA2_M1AA2_iLS3_0ELS3_0EEEEE" } } + + +struct C { padm_t a[3]; }; +template struct Z { }; + +void h___ (Z) { } +// { dg-final { scan-assembler "_Z4h___1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } } + +void h0__ (Z) { } +// { dg-final { scan-assembler "_Z4h0__1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } } + +void h00_ (Z) { } +// { dg-final { scan-assembler "_Z4h00_1ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } } + +void h000 (Z) { } +// { dg-final { scan-assembler "_Z4h0001ZIXtl1CtlA3_M1AA2_iLS3_0EEEEE" } } + +void h00x (Z) { } +// FIXME: This needs to mangle differently from hx0_ and hx__. +// { dg-final { scan-assembler "_Z4h00x1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-*} } } + +void h0x0 (Z) { } +// { dg-final { scan-assembler "_Z4h0x01ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0ELS3_0EEEEE" } } + +void h0x_ (Z) { } +// { dg-final { scan-assembler "_Z4h0x_1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0ELS3_0EEEEE" } } + +void hx0_ (Z) { } +// FIXME: This needs to mangle differently from h00x and hx__. +// { dg-final { scan-assembler "_Z4hx0_1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-*} } } + +void hx__ (Z) { } +// FIXME: This needs to mangle differently from h00x and hx0_. +// { dg-final { scan-assembler "_Z4hx__1ZIXtl1CtlA3_M1AA2_iLS3_0ELS3_0EEEEE " { xfail *-*-* } } } + + +// Exercise arrays of pointers to function members. + +struct AF { void f (); }; +typedef void (AF::*pafm_t)(); + +struct D { pafm_t a[2]; }; +template struct F { }; + +void k__ (F) { } +// { dg-final { scan-assembler "_Z3k__1FIXtl1DEEE" } } + +void k0_ (F) { } +// { dg-final { scan-assembler "_Z3k0_1FIXtl1DEEE" } } + +void k00 (F) { } +// { dg-final { scan-assembler "_Z3k001FIXtl1DEEE" } } + +void k0x (F) { } +// { dg-final { scan-assembler "_Z3k0x1FIXtl1DtlA2_M2AFFvvEtlS3_EtlS3_adL_ZNS1_1fEvEEEEEE" } } + +void kx_ (F) { } +// { dg-final { scan-assembler "_Z3kx_1FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEEEEE" } } + +void kx0 (F) { } +// { dg-final { scan-assembler "_Z3kx01FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEEEEE" } } + +void kxx (F) { } +// { dg-final { scan-assembler "_Z3kxx1FIXtl1DtlA2_M2AFFvvEtlS3_adL_ZNS1_1fEvEEtlS3_adL_ZNS1_1fEvEEEEEE" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C new file mode 100644 index 00000000000..f7e5d352d88 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C @@ -0,0 +1,137 @@ +// PR c++/89833 +// Test to verify that constant array elements initialized to zero +// evaluate to zero regardless of the form of their initilizer, +// and irrespective whether it's explicit or implicit. + +// { dg-do compile { target c++11 } } +// { dg-options "-Wall" } + +static const char all_zero[1024] = { }; + +namespace test_int +{ +constexpr int a[][3] = { { 0, 0 }, { 0 }, { } }; + +static_assert (sizeof a == sizeof (int) * 3 * 3); + +static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0 + && a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0 + && a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0); + +constexpr int b[3][3] = { { 0, 0 }, { 0 } }; + +static_assert (sizeof b == sizeof (int) * 3 * 3); + +static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0 + && b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0 + && b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0); + +constexpr int c[3][3] = { { } }; + +static_assert (sizeof c == sizeof (int) * 3 * 3); + +static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0 + && c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0 + && c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0); + +} + +namespace test_char +{ +constexpr char a[][3] = { { 0, 0 }, { 0 }, { } }; + +static_assert (sizeof a == sizeof (char) * 3 * 3); + +static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0 + && a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0 + && a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0); + +constexpr char b[3][3] = { { 0, 0 }, { 0 } }; + +static_assert (sizeof b == sizeof (char) * 3 * 3); + +static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0 + && b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0 + && b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0); + +constexpr char c[3][3] = { { } }; + +static_assert (sizeof c == sizeof (char) * 3 * 3); + +static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0 + && c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0 + && c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0); +} + +namespace test_string +{ +constexpr char a[][3] = { "\0", "", { } }; + +static_assert (sizeof a == sizeof (char) * 3 * 3); + +static_assert ( a[0][0] == 0 && a[0][1] == 0 && a[0][2] == 0 + && a[1][0] == 0 && a[1][1] == 0 && a[1][2] == 0 + && a[2][0] == 0 && a[2][1] == 0 && a[2][2] == 0); + +constexpr char b[3][3] = { "\0", "" }; + +static_assert (sizeof b == sizeof (char) * 3 * 3); + +static_assert ( b[0][0] == 0 && b[0][1] == 0 && b[0][2] == 0 + && b[1][0] == 0 && b[1][1] == 0 && b[1][2] == 0 + && b[2][0] == 0 && b[2][1] == 0 && b[2][2] == 0); + +constexpr char c[3][3] = { }; + +static_assert (sizeof c == sizeof (char) * 3 * 3); + +static_assert ( c[0][0] == 0 && c[0][1] == 0 && c[0][2] == 0 + && c[1][0] == 0 && c[1][1] == 0 && c[1][2] == 0 + && c[2][0] == 0 && c[2][1] == 0 && c[2][2] == 0); +} + +namespace test_string_member +{ +struct B { struct A { char a[5]; } a[2]; }; + +constexpr B b[3] = + { + /* [0] */ + { + /* a = */ + { + /* a[0] */ { { 0, 0, 0, 0, 0 } }, + /* a[1] */ { { 0, 0 } } + } + }, + /* [1] */ + { + /* a */ + { + /* a[0] */ { "\0\0\0\0" }, + /* a[0] */ { "" } + } + }, + }; + +static_assert ( b[0].a[0].a[0] == 0 + && b[0].a[0].a[1] == 0 + && b[0].a[0].a[2] == 0 + && b[0].a[0].a[3] == 0 + && b[0].a[0].a[4] == 0 + && b[0].a[1].a[0] == 0 + && b[0].a[1].a[1] == 0 + && b[0].a[1].a[2] == 0 + && b[0].a[1].a[3] == 0 + && b[0].a[1].a[4] == 0 + && b[1].a[0].a[0] == 0 + && b[1].a[0].a[1] == 0 + && b[1].a[0].a[2] == 0 + && b[1].a[0].a[3] == 0 + && b[1].a[0].a[4] == 0 + && b[2].a[0].a[0] == 0 + && b[2].a[0].a[1] == 0 + && b[2].a[0].a[2] == 0 + && b[2].a[0].a[3] == 0 + && b[2].a[0].a[4] == 0); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class15.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class15.C new file mode 100644 index 00000000000..d684785a77f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class15.C @@ -0,0 +1,222 @@ +// PR c++/89833 +// Test to verify that the same specializations on non-type template +// parameters of class types are in fact treated as the same. +// { dg-do compile { target c++2a } } + +struct A1 { char c[5]; }; + +template struct B { }; + +// All of the following name the same type. +typedef B A______; +typedef B A_Z____; +typedef B A_ZZ___; +typedef B A_ZZZ__; +typedef B A_ZZZZ_; +typedef B A_ZZZZZ; + +// Verify the types are indeed the same by redeclaring the same identifier +// of each of them. +extern A______ same_type_B_A1; +extern A_Z____ same_type_B_A1; +extern A_ZZ___ same_type_B_A1; +extern A_ZZZ__ same_type_B_A1; +extern A_ZZZZ_ same_type_B_A1; +extern A_ZZZZZ same_type_B_A1; + + +// All of the following use a string to initialize the array but +// also name the same type as the above. +typedef B S_z____; +typedef B S_Zz___; +typedef B S_ZZz__; +typedef B S_ZZZz_; +typedef B S_ZZZZz; + +// Verify the types are indeed the same by redeclaring the same identifier +// of each of them. +extern S_z____ same_type_B_A1; +extern S_Zz___ same_type_B_A1; +extern S_Zz___ same_type_B_A1; +extern S_ZZz__ same_type_B_A1; +extern S_ZZZz_ same_type_B_A1; +extern S_ZZZZz same_type_B_A1; + + +// All of the following also name the same type (distinct from +// the above). +typedef B A_A____; +typedef B A_AZ___; +typedef B A_AZZ__; +typedef B A_AZZZ_; +typedef B A_AZZZZ; + +extern A_A____ same_type_B_A1_A; +extern A_AZ___ same_type_B_A1_A; +extern A_AZZ__ same_type_B_A1_A; +extern A_AZZZ_ same_type_B_A1_A; +extern A_AZZZZ same_type_B_A1_A; + + +struct A3 { char a[5], b[5], c[5]; }; +template struct B3 { }; + +// These all name the same type. +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; + +// These all name the same type. +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; +typedef B3 B3_A3_AB________IJKL_; + +// Types with the same name must be the same (and so redefinitions +// must be accepted). Likewise, overloads on distinct types must +// be accepted. +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3_______________1; +typedef B3 B3_A3______________1_; +typedef B3 B3_A3______________1_; +typedef B3 B3_A3_____________1__; +typedef B3 B3_A3_____________1__; +typedef B3 B3_A3____________1___; +typedef B3 B3_A3____________1___; +typedef B3 B3_A3___________1____; +typedef B3 B3_A3__________1_____; +typedef B3 B3_A3__________1_____; +typedef B3 B3_A3__________1_____; +typedef B3 B3_A3_________1______; +typedef B3 B3_A3________1_______; +typedef B3 B3_A3_______1________; +typedef B3 B3_A3______1_________; +typedef B3 B3_A3_____1__________; +typedef B3 B3_A3_____1__________; +typedef B3 B3_A3_____1__________; +typedef B3 B3_A3____1___________; +typedef B3 B3_A3___1____________; +typedef B3 B3_A3__1_____________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; +typedef B3 B3_A3_1______________; + +typedef B3 B3_A3_1_____________1; +typedef B3 B3_A3_1_____________1; +typedef B3 B3_A3_1_____________1; +typedef B3 B3_A3__1___________1_; +typedef B3 B3_A3__1___________1_; +typedef B3 B3_A3__1___________1_; + +// Same as above. +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; +typedef B3 B3_A3________________; + +typedef B3 B3_A3_______________1; +typedef B3 B3_A3______________1_; +typedef B3 B3_A3_____________1__; +typedef B3 B3_A3____________1___; +typedef B3 B3_A3___________1____; +typedef B3 B3_A3__________1_____; +typedef B3 B3_A3_________1______; +typedef B3 B3_A3________1_______; +typedef B3 B3_A3_______1________; +typedef B3 B3_A3______1_________; +typedef B3 B3_A3_____1__________; +typedef B3 B3_A3____1___________; +typedef B3 B3_A3___1____________; +typedef B3 B3_A3__1_____________; +typedef B3 B3_A3_1______________; + +typedef B3 B3_A3_1_____________1; +typedef B3 B3_A3_1_____________1; +typedef B3 B3_A3__1___________1_; +typedef B3 B3_A3__1___________1_; +typedef B3 B3_A3__1___________1_; + +void f_b3_a3 (B3_A3________________) { } +void f_b3_a3 (B3_A3_______________1) { } +void f_b3_a3 (B3_A3______________1_) { } +void f_b3_a3 (B3_A3_____________1__) { } +void f_b3_a3 (B3_A3____________1___) { } +void f_b3_a3 (B3_A3___________1____) { } +void f_b3_a3 (B3_A3__________1_____) { } +void f_b3_a3 (B3_A3_________1______) { } +void f_b3_a3 (B3_A3________1_______) { } +void f_b3_a3 (B3_A3_______1________) { } +void f_b3_a3 (B3_A3______1_________) { } +void f_b3_a3 (B3_A3_____1__________) { } +void f_b3_a3 (B3_A3____1___________) { } +void f_b3_a3 (B3_A3___1____________) { } +void f_b3_a3 (B3_A3__1_____________) { } +void f_b3_a3 (B3_A3_1______________) { } +void f_b3_a3 (B3_A3_1_____________1) { } +void f_b3_a3 (B3_A3__1___________1_) { } + +typedef B3 B3_A3_ABZDZZZZZZIJKLZ; +typedef B3 B3_A3_ABZDZZZ1ZZIJKLZ; +typedef B3 B3_A3_ABZDZZ1ZZZIJKLZ; + +void f (B3_A3_ABZDZZZZZZIJKLZ) { } +void f (B3_A3_ABZDZZZ1ZZIJKLZ) { } +void f (B3_A3_ABZDZZ1ZZZIJKLZ) { } diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class16.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class16.C new file mode 100644 index 00000000000..3afb5d24261 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class16.C @@ -0,0 +1,57 @@ +// PR c++/89833 +// Test to verify that arrays of null pointer to members used as +// non-type template arguments are interprested as null regardless +// of the form of their initialization. +// { dg-do compile { target c++2a } } +// { dg-options "-O2 -Wall -fdump-tree-optimized" } + +struct A { int i; }; + +typedef int A::*pam_t; + +struct B { pam_t a[2]; }; +template struct C { static constexpr B b = x; }; + +B f__ () { return B{ }; } +B f0_ () { return B{ 0 }; } +B f00 () { return B{ 0, 0 }; } + +typedef C X__; +typedef C X0_; +typedef C X00; + +B g__ () { return X__::b; } +B g0_ () { return X0_::b; } +B g00 () { return X00::b; } + +const B b__{ }; +const B b0_{ 0 }; +const B b00{ 0, 0 }; + +const pam_t apam__[2] = { }; +const pam_t apam0_[2] = { 0 }; +const pam_t apam00[2] = { 0, 0 }; + +#define assert(expr) \ + (expr) ? (void)0 : __builtin_abort () + +void test () +{ + assert (f__ ().a[0] == nullptr && f__ ().a[1] == nullptr); + assert (f0_ ().a[0] == nullptr && f0_ ().a[1] == nullptr); + assert (f00 ().a[0] == nullptr && f00 ().a[1] == nullptr); + + assert (g__ ().a[0] == nullptr && g__ ().a[1] == nullptr); + assert (g0_ ().a[0] == nullptr && g0_ ().a[1] == nullptr); + assert (g00 ().a[0] == nullptr && g00 ().a[1] == nullptr); + + assert (b__.a[0] == nullptr && b__.a[1] == nullptr); + assert (b0_.a[0] == nullptr && b0_.a[1] == nullptr); + assert (b00.a[0] == nullptr && b00.a[1] == nullptr); + + assert (apam__[0] == nullptr && apam__[1] == nullptr); + assert (apam0_[0] == nullptr && apam0_[1] == nullptr); + assert (apam00[0] == nullptr && apam00[1] == nullptr); +} + +// { dg-final { scan-tree-dump-not "abort" "optimized" } } diff --git a/gcc/testsuite/g++.dg/init/array51.C b/gcc/testsuite/g++.dg/init/array51.C new file mode 100644 index 00000000000..2a90088953c --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array51.C @@ -0,0 +1,86 @@ +// PR c++/89833 +// Anal test to verify that arrays of null pointer to members are +// treated as null regardless of the form of their initialization, +// and have all bits set in their representation. +// { dg-do run { target c++11 } } +// { dg-options "-O2 -Wall" } + +#define NOIPA __attribute__ ((noipa)) + +struct A { int i; }; + +typedef int A::*pam_t; + +pam_t apam__[2] = { }; +pam_t apam0_[2] = { 0 }; +pam_t apam00[2] = { 0, 0 }; + +struct B { pam_t a[2]; }; + +NOIPA B f__ () { return B{ }; } +NOIPA B f0_ () { return B{ 0 }; } +NOIPA B f00 () { return B{ 0, 0 }; } + +const B c__{ }; +const B c0_{ 0 }; +const B c00{ 0, 0 }; + +B b__{ }; +B b0_{ 0 }; +B b00{ 0, 0 }; + +#define assert(expr) \ + (expr) ? (void)0 : __builtin_abort () + +signed char allones[2 * sizeof (pam_t)]; + +#define assert_rep(mp, n) \ + assert (!test_allones (mp, n)) + +NOIPA void init_allones () +{ + __builtin_memset (allones, -1, sizeof allones); +} + +NOIPA int test_allones (const pam_t *p, unsigned n) +{ + return __builtin_memcmp (allones, p, sizeof *p * n); +} + +int main () +{ + init_allones (); + + assert (apam__[0] == nullptr && apam__[1] == nullptr); + assert (apam0_[0] == nullptr && apam0_[1] == nullptr); + assert (apam00[0] == nullptr && apam00[1] == nullptr); + + assert (f__ ().a[0] == nullptr && f__ ().a[1] == nullptr); + assert (f0_ ().a[0] == nullptr && f0_ ().a[1] == nullptr); + assert (f00 ().a[0] == nullptr && f00 ().a[1] == nullptr); + + assert (b__.a[0] == nullptr && b__.a[1] == nullptr); + assert (b0_.a[0] == nullptr && b0_.a[1] == nullptr); + assert (b00.a[0] == nullptr && b00.a[1] == nullptr); + + assert (c__.a[0] == nullptr && c__.a[1] == nullptr); + assert (c0_.a[0] == nullptr && c0_.a[1] == nullptr); + assert (c00.a[0] == nullptr && c00.a[1] == nullptr); + + assert_rep (apam__, 2); + assert_rep (apam0_, 2); + assert_rep (apam00, 2); + + assert_rep (f__ ().a, 2); + assert_rep (f0_ ().a, 2); + assert_rep (f0_ ().a, 2); + assert_rep (f00 ().a, 2); + + assert_rep (b__.a, 2); + assert_rep (b0_.a, 2); + assert_rep (b00.a, 2); + + assert_rep (c__.a, 2); + assert_rep (c0_.a, 2); + assert_rep (c00.a, 2); +} diff --git a/gcc/testsuite/g++.dg/template/nontype29.C b/gcc/testsuite/g++.dg/template/nontype29.C new file mode 100644 index 00000000000..18a3058e7e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/nontype29.C @@ -0,0 +1,81 @@ +// PR c++/47488 - sorry, unimplemented: string literal in function +// template signature +// { dg-do compile } +// { dg-options "-Wall" } + +#if __cpluspls >= 201103L + +// C++ 11 test case from comment #0. +namespace comment_0 { + +template +int f (const T&, const char *); + +template +decltype (f (T (), "")) g (const T &); + +void h () +{ + g (0); +} + +} // comment_0 + +#endif + +// C++ 98 test case from comment #1. +namespace comment_1 { + +template +int f(const T&, const char *); + +template struct N { }; + +template +N g (const T&); + +void h () +{ + g (0); +} + +} // comment_1 + +// C++ 98 test case from comment #2. +namespace comment_2 { + +template +int f (const char *); + +template struct N { }; + +template +N(""))> g (const T &); + +void h () +{ + g (0); +} + +} // comment_2 + + +#if __cpluspls >= 201103L + +// C++ 11 test case from comment #5. +namespace comment_5 { + +template constexpr T f(const T* p) { return p[0]; } +template struct N { }; +template void g (T, N) { } +template void g (T, N) { } + +void h () +{ + g ('1', N<'1'>()); + g ('2', N<'2'>()); +} + +} + +#endif -- 2.30.2