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.