public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Patrick Palka <ppalka@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: problematic assert in reference_binding [PR113141]
Date: Fri, 12 Apr 2024 15:38:11 -0400	[thread overview]
Message-ID: <6176154c-bffe-4544-8f5f-aca2b99cc261@redhat.com> (raw)
In-Reply-To: <1fdcd7f8-9862-19ba-7712-d59897b6bc38@idea>

On 3/26/24 09:44, Patrick Palka wrote:
> On Thu, 7 Mar 2024, Jason Merrill wrote:
> 
>> On 1/29/24 17:42, Patrick Palka wrote:
>>> On Mon, 29 Jan 2024, Patrick Palka wrote:
>>>
>>>> On Fri, 26 Jan 2024, Jason Merrill wrote:
>>>>
>>>>> On 1/26/24 17:11, Jason Merrill wrote:
>>>>>> On 1/26/24 16:52, Jason Merrill wrote:
>>>>>>> On 1/25/24 14:18, Patrick Palka wrote:
>>>>>>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
>>>>>>>> OK for trunk/13?  This isn't a very satisfactory fix, but at least
>>>>>>>> it safely fixes these testcases I guess.  Note that there's
>>>>>>>> implementation disagreement about the second testcase, GCC always
>>>>>>>> accepted it but Clang/MSVC/icc reject it.
>>>>>>>
>>>>>>> Because of trying to initialize int& from {c}; removing the extra
>>>>>>> braces
>>>>>>> makes it work everywhore.
>>>>>>>
>>>>>>> https://eel.is/c++draft/dcl.init#list-3.10 says that we always
>>>>>>> generate a
>>>>>>> prvalue in this case, so perhaps we shouldn't recalculate if the
>>>>>>> initializer is an init-list?
>>>>>>
>>>>>> ...but it seems bad to silently bind a const int& to a prvalue instead
>>>>>> of
>>>>>> directly to the reference returned by the operator, as clang does if
>>>>>> we add
>>>>>> const to the second testcase, so I think there's a defect in the
>>>>>> standard
>>>>>> here.
>>>>>
>>>>> Perhaps bullet 3.9 should change to "...its referenced type is
>>>>> reference-related to E <ins>or scalar</ins>, ..."
>>>>>
>>>>>> Maybe for now also disable the maybe_valid heuristics in the case of
>>>>>> an
>>>>>> init-list?
>>>>>>
>>>>>>> The first testcase is special because it's a C-style cast; seems
>>>>>>> like the
>>>>>>> maybe_valid = false heuristics should be disabled if c_cast_p.
>>>>
>>>> Thanks a lot for the pointers.  IIUC c_cast_p and
>>>> LOOKUP_SHORTCUT_BAD_CONVS
>>>> should already be mutually exclusive, since the latter is set only when
>>>> computing argument conversions, so it shouldn't be necessary to check
>>>> c_cast_p.
>>>>
>>>> I suppose we could disable the heuristic for init-lists, but after some
>>>> digging I noticed that the heuristics were originally in same spot they
>>>> are now until r5-601-gd02f620dc0bb3b moved them to get checked after
>>>> the recursive recalculation case in reference_binding, returning a bad
>>>> conversion instead of NULL.  (Then in r13-1755-g68f37670eff0b872 I moved
>>>> them back; IIRC that's why I felt confident that moving the checks was
>>>> safe.)
>>>> Thus we didn't always accept the second testcase, we only started doing so
>>>> in
>>>> GCC 5: https://godbolt.org/z/6nsEW14fh (sorry for missing this and saying
>>>> we
>>>> always accepted it)
>>>>
>>>> And indeed the current order of checks seems consistent with that of
>>>> [dcl.init.ref]/5.  So I wonder if we don't instead want to "complete"
>>>> the NULL-to-bad-conversion adjustment in r5-601-gd02f620dc0bb3b and
>>>> do:
>>>>
>>>> gcc/cp/ChangeLog:
>>>>
>>>> 	* call.cc (reference_binding): Set bad_p according to
>>>> 	maybe_valid_p in the recursive case as well.  Remove
>>>> 	redundant gcc_assert.
>>>>
>>>> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
>>>> index 9de0d77c423..c4158b2af37 100644
>>>> --- a/gcc/cp/call.cc
>>>> +++ b/gcc/cp/call.cc
>>>> @@ -2033,8 +2033,8 @@ reference_binding (tree rto, tree rfrom, tree expr,
>>>> bool c_cast_p, int flags,
>>>>    				   sflags, complain);
>>>>    	    if (!new_second)
>>>>    	      return bad_direct_conv ? bad_direct_conv : nullptr;
>>>> +	    t->bad_p = !maybe_valid_p;
>>>
>>> Oops, that should be |= not =.
>>>
>>>>> Perhaps bullet 3.9 should change to "...its referenced type is
>>>>> reference-related to E <ins>or scalar</ins>, ..."
>>>>    	    conv = merge_conversion_sequences (t, new_second);
>>>> -	    gcc_assert (maybe_valid_p || conv->bad_p);
>>>>    	    return conv;
>>>>    	  }
>>>>        }
>>>>
>>>> This'd mean we'd go back to rejecting the second testcase (only the
>>>> call, not the direct-init, interestingly enough), but that seems to be
>>>
>>> In the second testcase, with the above fix initialize_reference silently
>>> returns error_mark_node for the direct-init without issuing a
>>> diagnostic, because in the error path convert_like doesn't find anything
>>> wrong with the bad conversion.  So more changes need to be made if we
>>> want to set bad_p in the recursive case of reference_binding it seems;
>>> dunno if that's the path we want to go down?
>>>
>>> On the other hand, disabling the badness checks in certain cases seems
>>> to be undesirable as well, since AFAICT their current position is
>>> consistent with [dcl.init.ref]/5?
>>>
>>> So I wonder if we should just go with the safest thing at this stage,
>>> which would be the original patch that removes the problematic assert?
>>
>> I still think the assert is correct, and the problem is that maybe_valid_p is
>> wrong; these cases turn out to be valid, so maybe_valid_p should be true.
> 
> I'm afraid then I don't know how we can statically identify these cases
> without actually performing the conversion, in light of the recursion :/
> Do you mind taking this PR?  I don't feel well-versed enough with the
> reference binding rules to tackle this adequately..

That ended up being a surprisingly deep dive, but I've now checked in 
separate fixes for the two cases.

Jason


  reply	other threads:[~2024-04-12 19:38 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-25 19:18 Patrick Palka
2024-01-26 21:52 ` Jason Merrill
2024-01-26 22:11   ` Jason Merrill
2024-01-26 22:20     ` Jason Merrill
2024-01-29 20:48       ` Patrick Palka
2024-01-29 22:42         ` Patrick Palka
2024-03-07 21:05           ` Patrick Palka
2024-03-07 23:31           ` Jason Merrill
2024-03-26 13:44             ` Patrick Palka
2024-04-12 19:38               ` Jason Merrill [this message]
2024-04-12 20:22                 ` Patrick Palka
2024-05-01 20:37                   ` Jason Merrill
2024-05-01 20:41                     ` Patrick Palka
2024-05-01 22:17                       ` Patrick Palka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6176154c-bffe-4544-8f5f-aca2b99cc261@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ppalka@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).