https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105027

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
           Assignee|unassigned at gcc dot gnu.org      |redi at gcc dot gnu.org
             Status|UNCONFIRMED                 |ASSIGNED
   Target Milestone|---                         |11.3
   Last reconfirmed|                            |2022-03-23

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Ed Catmur from comment #0)
> #1 and #2 are erroneously accepted although the corresponding call to
> std::bit_cast would fail internally;

Yes, those checks are done by the compiler in __builtin_bit_cast but that means
they're the equivalent of "Mandates:" not "Constraints:".

> static_assert(BitCastable<long, int()>); // #3: see below
> int f();
> long l = std::bit_cast<long>(f); // #4
> 
> By my reading of [temp.deduct] #3 should be a hard error, since
> sizeof(int()) is not only invalid; it is not SFINAE.

[temp.deduct.general] p8 says "If a substitution results in an invalid type or
expression, type deduction fails. An invalid type or expression is one that
would be ill-formed, with a diagnostic required, if written in the same context
using the substituted arguments."

Substituting a function type for T in sizeof(T) creates an invalid expression,
so deduction fails. It's a substitution failure, not an error.

> However, compilers that
> allow it (gcc everywhere,

GCC allows it because of https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
but that extension is disabled in SFINAE contexts, so it's still a substitution
failure.

> MSVC and clang as SFINAE) should then reject
> either by SFINAE, or as having the incorrect size, or since function types
> are not trivially copyable; gcc/libstdc++ does not and also accepts #4,

GCC does reject it as a substitution failure, like MSVC and Clang do. The
reason #4 is accepted is because std::bit_cast isn't constrained. You don't get
a substitution failure for sizeof(int()) if there's no constraint using sizeof.

> decaying the function reference to a function pointer; clang/libstdc++
> rejects within its own __builtin_bit_cast.

Maybe __builtin_bit_cast should check that, but it won't matter once
std::bit_cast is properly constrained.

Reply via email to