diff options
author | Martin Sebor <msebor@redhat.com> | 2019-04-04 23:10:23 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2019-04-04 17:10:23 -0600 |
commit | 187c6369c0b4c7e013fdbe9eb08d098166359056 (patch) | |
tree | 7594a3b21feb39a649170bfa6daa218b1fdd8396 /gcc/cp | |
parent | 1a9b15a7d76ee3ee2cd960698a84e34ec10c2bf0 (diff) | |
download | gcc-187c6369c0b4c7e013fdbe9eb08d098166359056.zip gcc-187c6369c0b4c7e013fdbe9eb08d098166359056.tar.gz gcc-187c6369c0b4c7e013fdbe9eb08d098166359056.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/cp/decl.c | 22 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 79 |
3 files changed, 106 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 888b431..729b773 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2019-04-04 Martin Sebor <msebor@redhat.com> + + 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 <jason@redhat.com> PR c++/81866 - ICE with member template and default targ. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c46a3966..400e1a2 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 f40c3e1..a5fd66f 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -3136,18 +3136,48 @@ write_expression (tree expr) } else if (code == CONSTRUCTOR) { - vec<constructor_elt, va_gc> *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<constructor_elt, va_gc> *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 (); |