[PATCH] c++: Allow new char[4]{"foo"} [PR77841]
Jason Merrill
jason@redhat.com
Tue Sep 1 21:33:43 GMT 2020
On 9/1/20 3:41 PM, Marek Polacek wrote:
> On Tue, Sep 01, 2020 at 03:27:36PM -0400, Jason Merrill via Gcc-patches wrote:
>> On 9/1/20 12:10 PM, Marek Polacek wrote:
>>> Currently, we allow new char[]{"foo"}, but not new char[4]{"foo"}.
>>> We should accept the latter too: [dcl.init.list]p3.3 says to treat
>>> this as [dcl.init.string].
>>>
>>> We were rejecting this code because we never called reshape_init before
>>> the digest_init in build_new_1. reshape_init handles [dcl.init.string]
>>> by unwrapping the STRING_CST from its enclosing { }, and digest_init
>>> assumes that reshape_init has been called for aggregates anyway, and an
>>> array is an aggregate.
>>>
>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> PR c++/77841
>>> * init.c (build_new_1): Call reshape_init.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> PR c++/77841
>>> * g++.dg/cpp0x/initlist-new4.C: New test.
>>> ---
>>> gcc/cp/init.c | 6 ++++++
>>> gcc/testsuite/g++.dg/cpp0x/initlist-new4.C | 6 ++++++
>>> 2 files changed, 12 insertions(+)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-new4.C
>>>
>>> diff --git a/gcc/cp/init.c b/gcc/cp/init.c
>>> index 360ab8c0b52..d4540db3605 100644
>>> --- a/gcc/cp/init.c
>>> +++ b/gcc/cp/init.c
>>> @@ -3575,6 +3575,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
>>> /* We'll check the length at runtime. */
>>> domain = NULL_TREE;
>>> arraytype = build_cplus_array_type (type, domain);
>>> + /* If we have new char[4]{"foo"}, we have to reshape
>>> + so that the STRING_CST isn't wrapped in { }. */
>>> + vecinit = reshape_init (arraytype, vecinit, complain);
>>> + /* The middle end doesn't cope with the location wrapper
>>> + around a STRING_CST. */
>>> + STRIP_ANY_LOCATION_WRAPPER (vecinit);
>>> vecinit = digest_init (arraytype, vecinit, complain);
>>> }
>>
>> This is OK, but now I wonder why your earlier addition,
>>
>>> /* This handles code like new char[]{"foo"}. */
>>> else if (len == 1
>>> && char_type_p (TYPE_MAIN_VARIANT (type))
>>> && TREE_CODE (tree_strip_any_location_wrapper ((**init)[0]))
>>> == STRING_CST)
>>> {
>>> vecinit = (**init)[0];
>>> STRIP_ANY_LOCATION_WRAPPER (vecinit);
>>> }
>>
>> isn't handled by the block you're changing in this patch. Why isn't
>> DIRECT_LIST_INIT_P true for new char[]{"foo"}?
>
> Yes, I was hoping this hunk would handle the new char[4]{"foo"} case too,
> but for new char[]{"foo"} DIRECT_LIST_INIT_P is false because earlier in
> build_new we called reshape_init:
>
> 4011 /* Otherwise we should have 'new T[]{e_0, ..., e_k}'. */
> 4012 if (BRACE_ENCLOSED_INITIALIZER_P (elt))
> 4013 elt = reshape_init (type, elt, complain);
>
> which unwraps the { } from {"foo"}, so it's no longer a list init.
Ah, I see.
> We
> won't get there with new char[4]{"foo"} because TREE_CODE (type) will
> not be ARRAY_TYPE; instead, nelts is set to INTEGER_CST 4 when we know
> the array bound.
>
> I could make it so that we call reshape_init in build_new for the [4]
> case too, but it was uglier than this fix.
>
> Should I go ahead with this patch as-is or would you prefer any changes?
Go ahead with this for now, but I notice that we also still don't support
new char[4](1,2,3,4);
because the handling of parenthesized-init is limited to the deduced
array size case.
It would be nice to find a way to combine the two places that we're
messing with array initializers.
Jason
More information about the Gcc-patches
mailing list