On 2/12/20 9:21 PM, Martin Sebor wrote:
On 2/11/20 5:28 PM, Jason Merrill wrote:
On 2/11/20 9:00 PM, Martin Sebor wrote:
r270155, committed in GCC 9, introduced a transformation that strips
redundant trailing zero initializers from array initializer lists in
order to support string literals as template arguments.
The transformation neglected to consider the case of array elements
of trivial class types with user-defined conversion ctors and either
defaulted or deleted default ctors. (It didn't occur to me that
those qualify as trivial types despite the user-defined ctors.) As
a result, some valid initialization expressions are rejected when
the explicit zero-initializers are dropped in favor of the (deleted)
default ctor,
Hmm, a type with only a deleted default constructor is not trivial,
that should have been OK already.
For Marek's test case:
struct A { A () == delete; A (int) = delete; };
trivial_type_p() returns true (as does __is_trivial (A) in both GCC
and Clang).
[class.prop] says that
A trivial class is a class that is trivially copyable and has one
or more default constructors (10.3.4.1), all of which are either
trivial or deleted and at least one of which is not deleted.
That sounds like A above is not trivial because it doesn't have
at least one default ctor that's not deleted, but both GCC and
Clang say it is. What am I missing? Is there some other default
constructor hiding in there that I don't know about?
and others are eliminated in favor of the defaulted
ctor instead of invoking a user-defined conversion ctor, leading to
wrong code.
This seems like a bug in type_initializer_zero_p; it shouldn't treat 0
as a zero initializer for any class.
That does fix it, and it seems like the right solution to me as well.
Thanks for the suggestion. I'm a little unsure about the condition
I put in place though.
Attached is an updated patch rested on x86_64-linux.
- if (sized_array_p && trivial_type_p (elt_type))
+ if (sized_array_p
+ && trivial_type_p (elt_type)
+ && !TYPE_NEEDS_CONSTRUCTING (elt_type))
Do we still need this change? If so, please add a comment about the
trivial_type_p bug.
if (TREE_CODE (init) != CONSTRUCTOR
I might change this to
if (!CP_AGGREGATE_TYPE_P (type))
return initializer_zerop (init);
else if (TREE_CODE (init) != CONSTRUCTOR)
return false;
and then remove the
if (TYPE_NON_AGGREGATE_CLASS (type))
return false;
later in the function.
More generally, this function could recognize when the initializer is
equivalent to {}-initialization and return true in that case, but that
sounds probably too tricky for stage 4.
Jason