PR c++/89833 - sorry, unimplemented: string literal in function template signature gcc/cp/ChangeLog: PR c++/89833 * 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. Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 270037) +++ gcc/cp/decl.c (working copy) @@ -5799,6 +5799,9 @@ reshape_init_array_1 (tree elt_type, tree max_inde 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,28 @@ reshape_init_array_1 (tree elt_type, tree max_inde 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 && trivial_type_p (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; } Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 270037) +++ gcc/cp/mangle.c (working copy) @@ -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); } - FOR_EACH_CONSTRUCTOR_VALUE (elts, i, val) - write_expression (val); + + 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); + } + } write_char ('E'); } else if (code == LAMBDA_EXPR) @@ -3353,9 +3383,15 @@ 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. */ if (null_member_pointer_value_p (value)) @@ -3397,9 +3433,36 @@ 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. */ + tree strsizenode = TYPE_SIZE_UNIT (TREE_TYPE (value)); + unsigned strsize = tree_to_uhwi (strsizenode); + if (strsize > n) + strsize = n; + for (const char *p = str + strsize - 1; ; --p) + { + if (*p || p == str) + { + strsize -= str + strsize - !!*p - p; + break; + } + } + tree eltype = TREE_TYPE (valtype); + for (const char *p = str; strsize--; ++p) + { + write_char ('L'); + write_type (eltype); + write_unsigned_number (*(const unsigned char*)p); + write_string ("E"); + } + break; + } + default: gcc_unreachable (); } Index: gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C =================================================================== --- gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-array19.C (working copy) @@ -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); +} Index: gcc/testsuite/g++.dg/cpp2a/nontype-class15.C =================================================================== --- gcc/testsuite/g++.dg/cpp2a/nontype-class15.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp2a/nontype-class15.C (working copy) @@ -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) { } Index: gcc/testsuite/g++.dg/abi/mangle69.C =================================================================== --- gcc/testsuite/g++.dg/abi/mangle69.C (nonexistent) +++ gcc/testsuite/g++.dg/abi/mangle69.C (working copy) @@ -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" } } Index: gcc/testsuite/g++.dg/abi/mangle70.C =================================================================== --- gcc/testsuite/g++.dg/abi/mangle70.C (nonexistent) +++ gcc/testsuite/g++.dg/abi/mangle70.C (working copy) @@ -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" } } Index: gcc/testsuite/g++.dg/abi/mangle71.C =================================================================== --- gcc/testsuite/g++.dg/abi/mangle71.C (nonexistent) +++ gcc/testsuite/g++.dg/abi/mangle71.C (working copy) @@ -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" } }