c++/69277 reports an ICE when mangling a template specialization involving flexible array member. Debugging the problem revealed that GCC (prior to the ICE), due to treating flexible array members the same as zero-length arrays, produced the wrong mangling for the former.
The attached patch fixes the ICE and also corrects the mangling (which now also matches Clang's). Tested on x86_64. Martin
gcc/testsuite/ChangeLog: 2016-01-14 Martin Sebor <mse...@redhat.com> PR c++/69277 * g++.dg/ext/flexarray-mangle-2.C: New test. * g++.dg/ext/flexarray-mangle.C: New test. gcc/cp/ChangeLog: 2016-01-14 Martin Sebor <mse...@redhat.com> PR c++/69277 * mangle.c (write_array_type): Mangle flexible array members the same as arrays with an unspecified size. Index: gcc/cp/mangle.c =================================================================== --- gcc/cp/mangle.c (revision 232296) +++ gcc/cp/mangle.c (working copy) @@ -3280,8 +3280,10 @@ write_template_template_arg (const tree ::= A <expression> _ </element/ type> "Array types encode the dimension (number of elements) and the - element type. For variable length arrays, the dimension (but not - the '_' separator) is omitted." */ + element type. For variable length arrays, the dimension (but not + the '_' separator) is omitted." + Note that for flexible array members, like for other arrays of + unspecified size, the dimension is also omitted. */ static void write_array_type (const tree type) @@ -3290,29 +3292,31 @@ write_array_type (const tree type) if (TYPE_DOMAIN (type)) { tree index_type; - tree max; index_type = TYPE_DOMAIN (type); - /* The INDEX_TYPE gives the upper and lower bounds of the - array. */ - max = TYPE_MAX_VALUE (index_type); - if (TREE_CODE (max) == INTEGER_CST) + /* The INDEX_TYPE gives the upper and lower bounds of the array. + It's null for flexible array members which have no upper bound + (this is a change from GCC 5 and prior where such members were + incorrectly mangled as zero-length arrays). */ + if (tree max = TYPE_MAX_VALUE (index_type)) { - /* The ABI specifies that we should mangle the number of - elements in the array, not the largest allowed index. */ - offset_int wmax = wi::to_offset (max) + 1; - /* Truncate the result - this will mangle [0, SIZE_INT_MAX] - number of elements as zero. */ - wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max))); - gcc_assert (wi::fits_uhwi_p (wmax)); - write_unsigned_number (wmax.to_uhwi ()); + if (TREE_CODE (max) == INTEGER_CST) + { + /* The ABI specifies that we should mangle the number of + elements in the array, not the largest allowed index. */ + offset_int wmax = wi::to_offset (max) + 1; + /* Truncate the result - this will mangle [0, SIZE_INT_MAX] + number of elements as zero. */ + wmax = wi::zext (wmax, TYPE_PRECISION (TREE_TYPE (max))); + gcc_assert (wi::fits_uhwi_p (wmax)); + write_unsigned_number (wmax.to_uhwi ()); + } + else + { + max = TREE_OPERAND (max, 0); + write_expression (max); + } } - else - { - max = TREE_OPERAND (max, 0); - write_expression (max); - } - } write_char ('_'); write_type (TREE_TYPE (type)); Index: gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C (revision 0) +++ gcc/testsuite/g++.dg/ext/flexarray-mangle-2.C (working copy) @@ -0,0 +1,46 @@ +// PR c++/69277 - [6 Regression] ICE mangling a flexible array member +// { dg-do compile { target c++11 } } + +struct A { + int n; + char a []; +}; + +// Declare but do not define function templates. +template <class T> +void foo (); + +template <typename T> +void fooref (T&); + +// Rvalue references are a C++ 11 feature. +template <typename T> +void foorefref (T&&); + +void bar (A a) +{ + // Decltype is also a C++ 11 feature. + // Verify that decltype gets the right type and that foo is + // mangled correctly. + foo<decltype (a.a)>(); + + // Verify that function templates taking a reference and an rvalue + // references (as in PR c++/69277) are also mangled correctly. + fooref (a.a); + foorefref (a.a); +} + +// In G++ versions prior to 6, flexible array members were incorrectly +// mangled as arrays of zero elements. Verify that flexible array +// members are mangled correctly as arrays of an unspecified number +// of elements. + +// void foo<char []>(): +// { dg-final { scan-assembler _Z3fooIA_cEvv } } + +// The following is derived from PR c++/69277: +// void fooref<char []>(char (&) []) +// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } } + +// void foorefref<char (&) []>(char (&) []) +// { dg-final { scan-assembler _Z9foorefrefIRA_cEvOT_ } } Index: gcc/testsuite/g++.dg/ext/flexarray-mangle.C =================================================================== --- gcc/testsuite/g++.dg/ext/flexarray-mangle.C (revision 0) +++ gcc/testsuite/g++.dg/ext/flexarray-mangle.C (working copy) @@ -0,0 +1,24 @@ +// PR c++/69277 - [6 Regression] ICE mangling a flexible array member +// { dg-do compile } + +struct A { + int n; + char a []; +}; + +// Declare but do not define function templates. +template <typename T> +void fooref (T&); + +void bar (A a) +{ + fooref (a.a); +} + +// In G++ versions prior to 6, flexible array members were incorrectly +// mangled as arrays of zero elements. Verify that flexible array +// members are mangled correctly as arrays of an unspecified number +// of elements. + +// void fooref<char []>(char (&) []) +// { dg-final { scan-assembler _Z6foorefIA_cEvRT_ } }