[PATCH] avoid user-constructible types in reshape_init_array (PR 90938)
Jason Merrill
jason@redhat.com
Thu Feb 13 22:59:00 GMT 2020
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
More information about the Gcc-patches
mailing list