On Thu, Apr 27, 2023 at 8:19 AM Thiago Macieira <thiago@macieira.org> wrote:
On Wednesday, 26 April 2023 16:19:26 PDT Myria via Std-Discussion wrote:
> C++ says that reinterpret_casting an object pointer to a function pointer
> is conditionally supported.  However, there seems to be implementation
> divergence on what happens if the object pointer is cv-qualified.  GCC
> allows casts from cv object * to function pointer, but Clang and Visual C++
> do not.

Hello Myria


I think this should not be considered a defect in the standard. Instead, it
should be a considered a defect in GCC for allowing it, because it allows for
discarding a const qualifier without a const_cast, permitting this:

    const void *cptr = &i;
    auto fptr = reinterpret_cast<void (*)()>(cptr);
    auto ptr = reinterpret_cast<int *>(fptr);
    *ptr = 1;

(don't ask me what MSVC is doing there)

Perhaps the request should be editorial to put notes clarifying that this case is ill-formed, because function types aren't const?

As for MSVC, I'll look into that one; it may be a compiler bug, or may be a reaction to undefined behavior (writing to a const object).

I don't think there's any way to get to a standards-bounded situation where
the problem arises in the first place. You always need some level of platform-
specific knowledge.

Within the C++ Standard, yes.  The POSIX Standard does require that void* to function pointer type work because of dlsym(), but that's also not const.

I just remembered another aspect to this whole thing, though: C-style casts.

If instead of reinterpret_cast, we do this:

int result = ((int (*)()) s_code)();

Clang and GCC allow it, but MSVC does not.  It sounds like MSVC is correct in considering this ill-formed, because of the definition of C-style casts ([expr.cast]/4) :

The conversions performed by
  • a const_cast
  • a static_cast
  • a static_cast followed by a const_cast,
  • a reinterpret_cast, or
  • a reinterpret_cast followed by a const_cast,
can be performed using the cast notation of explicit type conversion.

The C-style cast appears to be ill-formed because there is no valid reinterpret_cast that would make this legal even with a const_cast after it.  It is counterintuitive that a C-style cast could be ill-formed due to removing const.