Why is (int&)0 ill-formed?
Asked Answered
R

1

27

According to [expr.cast]/4, a C-style cast tries the following casts in order:

  1. const_cast
  2. static_cast
  3. static_cast followed by const_cast
  4. reinterpret_cast
  5. reinterpret_cast followed by const_cast

The following cast is well-formed:

const_cast<int&>(static_cast<const int&>(0))

Yet both GCC and Clang reject the cast (int&)0. Why?

Recriminate answered 30/3, 2018 at 21:47 Comment(18)
What would you want it to mean?Carcajou
@NeilButterworth I'm not saying it should be well-formed; I'm saying the rules of the language appear to make it well-formed and I would like someone to point out the error in my reasoning.Recriminate
UPDATE: The first (well-formed) cast was not rejected by Clang on my machine. The second cast was rejected. Hmm. Making it a const int& it was not rejected. I'll have to ponder.Unset
@Justin • I had updated my comment. I cut-n-pasted the first (good) casts.Unset
@Unset Casting to const int& is fine because of lifetime extensionDoorkeeper
@Peter I disagree that this is a duplicate of that question. This question is focused around why the C-style cast doesn't succeed, not around why the const& worksDoorkeeper
Reopen-hammered :)Recriminate
You might as well ask why static_cast<int &>0 is rejected by the compiler, because that is what (int &)0 resolves to. And the question I linked to as a dup addresses that.Firefly
@Firefly No, that's not how it works. The compiler will accept float* p; (int*)p; even though the static cast would be rejected---because it interprets it as a reinterpret cast instead. But in my case, the (third) alternative interpretation is not used.Recriminate
I think this question shows the same bugs that your previous one showed. So in a way it's a duplicate.Critical
@SebastianRedl However, I'm not sure whether the committee would agree that this case (as opposed to the previous one) is supposed to be well-formed. Perhaps a wording change is needed.Recriminate
@Brian - I concur about the wording change. Hopefully to something that doesn't leave it open to "interpretation" (pun intended).Shorthanded
I posted to [email protected]Recriminate
In that context, the ampersand & creates an alias to (the name of) an lvalue. The number 0 is not a name or an lvalue.Rhynd
It says the first fashion from that list in which the cast “can be interpreted [...] is used, even if a cast resulting from that interpretation is ill-formed”. I suppose the interpretation as a bare static_cast is considered “possible” until [expr.static.cast]/1 forbids that it “cast away constness”. But that would seem to prevent ever using interpretation #3.Funke
Related, and possible duplicate: r-value Reference Casting and Temporary MaterializationSinistrocular
Possible duplicate of r-value Reference Casting and Temporary MaterializationIrreconcilable
Related/possible duplicate: #66817241Hirsutism
G
4

It is a bug in gcc and clang.

According to CWG 909, the "straightforward interpretation of the wording" should be used when generating cast sequences for C-style casts; there, the first cast invokes a conversion operator, but there is no reason to think that it should be any different when the first cast is reference binding a temporary.

I've posted a patch to the gcc mailing list, generated from this git branch, but it hasn't received any attention so far.

Gloat answered 2/3, 2022 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.