Hi,

On 24 Jan 2025, at 17:50, Jason Merrill wrote:

> On 1/23/25 12:20 PM, Simon Martin wrote:
>> Hi Jason,
>>
>> On 21 Jan 2025, at 22:51, Jason Merrill wrote:
>>
>>> On 1/3/25 3:00 PM, Simon Martin wrote:
>>>> We currently accept this code with c++ <= 17 even though it's 
>>>> invalid
>>>> since the base is not initialized (we properly reject it with c++ 
>>>> >=
>>>> 20)
>>>>
>>>> === cut here ===
>>>> struct NoMut1 { int a, b; };
>>>> struct NoMut3 : NoMut1 {
>>>>     constexpr NoMut3(int a, int b) {}
>>>> };
>>>> void mutable_subobjects() {
>>>>     constexpr NoMut3 nm3(1, 2);
>>>> }
>>>> === cut here ===
>>>>
>>>> This is a fallout of r0-118700-gc2b3ec18a494e3, that ignores all
>>>> fields
>>>> with DECL_ARTIFICIAL in cx_check_missing_mem_inits, including those
>>>> that
>>>> represent base classes, and need to be checked.
>>>>
>>>> This patch makes sure that we only skip fields that have
>>>> DECL_ARTIFICIAL
>>>> if they don't have DECL_FIELD_IS_BASE.
>>>>
>>>> Successfully tested on x86_64-pc-linux-gnu.
>>>>
>>>>    PR c++/118239
>>>>
>>>> gcc/cp/ChangeLog:
>>>>
>>>>    * constexpr.cc (cx_check_missing_mem_inits): Don't skip fields
>>>>    with DECL_FIELD_IS_BASE.
>>>>
>>>> gcc/testsuite/ChangeLog:
>>>>
>>>>    * g++.dg/cpp0x/constexpr-base8.C: New test.
>>>>
>>>> ---
>>>>    gcc/cp/constexpr.cc                          |  8 +++----
>>>>    gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C | 24
>>>> ++++++++++++++++++++
>>>>    2 files changed, 28 insertions(+), 4 deletions(-)
>>>>    create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-base8.C
>>>>
>>>> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
>>>> index c8be5a525ee..e11444438d3 100644
>>>> --- a/gcc/cp/constexpr.cc
>>>> +++ b/gcc/cp/constexpr.cc
>>>> @@ -839,9 +839,8 @@ cx_check_missing_mem_inits (tree ctype, tree
>>>> body, bool complain)
>>>>          if (i < nelts)
>>>>            {
>>>>              index = CONSTRUCTOR_ELT (body, i)->index;
>>>> -    /* Skip base and vtable inits.  */
>>>> -    if (TREE_CODE (index) != FIELD_DECL
>>>> -        || DECL_ARTIFICIAL (index))
>>>> +    /* Skip vtable inits.  */
>>>> +    if (TREE_CODE (index) != FIELD_DECL)
>>>>                continue;
>>>
>>> The code after your change no longer skips vtable inits; this should
>>> make the same DECL_FIELD_IS_BASE adjustment as below.
>> Ouch, thanks for catching this! I hate that I could break things like
>> this, so I tried to craft a test case that would have failed, but was
>> not able to so far :-(
>>
>> I can see that you added this DECL_ARTIFICIAL check via
>> 93a85785e0d08d149077f342201b9952a84669a7, and obviously the tests 
>> that
>> you’d added at that time worked even with my mistake. Do you have 
>> any
>> suggestion about what kind of construct could hit this code I broke, 
>> so
>> that I add a test case along with my next patch revision?
>
> Well, I'm not sure there is such a testcase.  The earlier checks skip 
> actual initializers, while the later checks skip members without 
> corresponding initializers.  So if we see a vptr initializer and no 
> longer skip it early, as long as its initializer's position in the 
> CONSTRUCTOR matches the position of the vptr in TYPE_FIELDS, we'll 
> continue through the loop normally.
>
> The case where this could cause a problem would be if the CONSTRUCTOR 
> order doesn't match the TYPE_FIELDS order for some reason.  I think 
> that this shouldn't ever happen currently, because a class with 
> virtual bases can't have a constexpr constructor, and non-virtual 
> bases are laid out in order.  If C++ ever supports constexpr virtual 
> bases, we'll need to handle them specially here.
>
> So actually I think your change is fine.  I'd just clarify the comment 
> to say "Skip vptr adjustment represented with a COMPONENT_REF."
>
> OK with that change.
Thanks Jason. Pushed to trunk as r15-7209-gbee1910b891f89; I don’t 
plan to backport.

Simon

Reply via email to