https://gcc.gnu.org/g:8d9d583484006a75bc3ed3b3badb585f3a0bb546
commit r15-6917-g8d9d583484006a75bc3ed3b3badb585f3a0bb546 Author: Jakub Jelinek <ja...@redhat.com> Date: Wed Jan 15 17:04:31 2025 +0100 c++: Implement mangling of RAW_DATA_CST [PR118278] As the following testcases show (mangle80.C only after reversion of the temporary reversion of C++ large array speedup commit), RAW_DATA_CST can be seen during mangling of some templates and we ICE because the mangler doesn't handle it. The following patch handles it and mangles it the same as a sequence of INTEGER_CSTs that were used previously instead. The only slight complication is that if ce->value is the last nonzero element, we need to skip the zeros at the end of RAW_DATA_CST. 2025-01-03 Jakub Jelinek <ja...@redhat.com> PR c++/118278 * mangle.cc (write_expression): Handle RAW_DATA_CST. * g++.dg/abi/mangle80.C: New test. * g++.dg/cpp/embed-19.C: New test. Diff: --- gcc/cp/mangle.cc | 37 ++++++++++++++++++-- gcc/testsuite/g++.dg/abi/mangle80.C | 67 +++++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp/embed-19.C | 18 ++++++++++ 3 files changed, 120 insertions(+), 2 deletions(-) diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 170dafd52c17..114e4a0d7c59 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -3748,8 +3748,41 @@ write_expression (tree expr) unsigned reps = 1; if (ce->index && TREE_CODE (ce->index) == RANGE_EXPR) reps = range_expr_nelts (ce->index); - for (unsigned j = 0; j < reps; ++j) - write_expression (ce->value); + if (TREE_CODE (ce->value) == RAW_DATA_CST) + { + gcc_assert (reps == 1); + unsigned int len = RAW_DATA_LENGTH (ce->value); + /* If this is the last non-zero element, skip + zeros at the end. */ + if (i == last_nonzero) + while (len) + { + if (RAW_DATA_POINTER (ce->value)[len - 1]) + break; + --len; + } + tree valtype = TREE_TYPE (ce->value); + for (unsigned int i = 0; i < len; ++i) + { + write_char ('L'); + write_type (valtype); + unsigned HOST_WIDE_INT v; + if (!TYPE_UNSIGNED (valtype) + && TYPE_PRECISION (valtype) == BITS_PER_UNIT + && RAW_DATA_SCHAR_ELT (ce->value, i) < 0) + { + write_char ('n'); + v = -RAW_DATA_SCHAR_ELT (ce->value, i); + } + else + v = RAW_DATA_UCHAR_ELT (ce->value, i); + write_unsigned_number (v); + write_char ('E'); + } + } + else + for (unsigned j = 0; j < reps; ++j) + write_expression (ce->value); } } else diff --git a/gcc/testsuite/g++.dg/abi/mangle80.C b/gcc/testsuite/g++.dg/abi/mangle80.C new file mode 100644 index 000000000000..e4f6934b431e --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle80.C @@ -0,0 +1,67 @@ +// PR c++/118278 +// Verify that class literals are mangled the same way regardless +// of the underlying type. +// { dg-do compile { target c++20 } } +// { dg-additional-options -fabi-compat-version=0 } + +struct I { int a[5], b[5], c[144]; }; +template <I> struct X { }; + +typedef X<I{ {1,2}, {}, { +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }> Ti; +void f (Ti) { } +// { dg-final { scan-assembler "_Z1f1XIXtl1ItlA5_iLi1ELi2EEtlS1_EtlA144_i(?:Li101ELi102ELi103ELi104ELi105ELi106ELi255ELi254ELi253ELi252ELi251ELi0ELi1ELi2ELi3ELi4E){8}Li101ELi102EEEEE" } } + +struct C { unsigned char a[5], b[5], c[144]; }; +template <C> struct Y { }; + +typedef Y<C{ {1,2}, {}, { +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }> Tca; +void g (Tca) { } +// { dg-final { scan-assembler "_Z1g1YIXtl1CtlA5_hLh1ELh2EEtlS1_EtlA144_h(?:Lh101ELh102ELh103ELh104ELh105ELh106ELh255ELh254ELh253ELh252ELh251ELh0ELh1ELh2ELh3ELh4E){8}Lh101ELh102EEEEE" } } + +typedef Y<C{ "\1\2", "", { +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,103,104,105,106,255,254,253,252,251,0,1,2,3,4, +101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }> Tcs; +void h (Tcs) { } +// { dg-final { scan-assembler "_Z1h1YIXtl1CtlA5_hLh1ELh2EEtlS1_EtlA144_h(?:Lh101ELh102ELh103ELh104ELh105ELh106ELh255ELh254ELh253ELh252ELh251ELh0ELh1ELh2ELh3ELh4E){8}Lh101ELh102EEEEE" } } + +struct S { signed char a[5], b[5], c[144]; }; +template <S> struct Z { }; + +typedef Z<S{ {1,2}, {}, { +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,103,104,105,106,95,94,93,92,91,0,1,2,3,4, +101,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }> Tsc; + +void i (Tsc) { } +// { dg-final { scan-assembler "_Z1i1ZIXtl1StlA5_aLa1ELa2EEtlS1_EtlA144_a(?:La101ELa102ELa103ELa104ELa105ELa106ELa95ELa94ELa93ELa92ELa91ELa0ELa1ELa2ELa3ELa4E){8}La101ELa102EEEEE" } } diff --git a/gcc/testsuite/g++.dg/cpp/embed-19.C b/gcc/testsuite/g++.dg/cpp/embed-19.C new file mode 100644 index 000000000000..bd7b9fa0e496 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/embed-19.C @@ -0,0 +1,18 @@ +// PR c++/118278 +// { dg-do compile { target c++20 } } +// { dg-options "-fabi-compat-version=0" } + +struct C { unsigned char a[5], b[5], c[128]; }; +template <C> struct Y { }; + +typedef Y<C{ {1,2}, {}, { +#embed __FILE__ __limit__ (128) +} }> Tca; +void g (Tca) { } +// { dg-final { scan-assembler "_Z1g1YIXtl1CtlA5_hLh1ELh2EEtlS1_EtlA128_h(?:Lh\[0-9]*E){128}EEEE" } } + +typedef Y<C{ "\1\2", "", { +#embed __FILE__ __limit__ (128) +} }> Tcs; +void h (Tcs) { } +// { dg-final { scan-assembler "_Z1h1YIXtl1CtlA5_hLh1ELh2EEtlS1_EtlA128_h(?:Lh\[0-9]*E){128}EEEE" } }