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