https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97432
Bug ID: 97432 Summary: Casting away constness in the drafts [conv.qual] a cv-decomposition exists in the following examples but fails in gcc Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: peifeng2005 at gmail dot com Target Milestone: --- In C++, the concept of [casting away constness](https://timsong-cpp.github.io/cppwp/expr.const.cast#7) is rigorously defined by the standard. Casts such as `static_cast` and `reinterpret_cast` are not allowed to cast away constness in the explicit conversion. The definition of casting away constness heavily relies on the qualification conversion definition, which says that two types can perform a qualification conversion up to [similar](https://timsong-cpp.github.io/cppwp/conv.qual#2) type. `reinterpret_cast` can then perform the cast on the non-similar parts, for example. Here is an example also available in [godbolt](https://godbolt.org/z/Y7qEcY): ```c++ struct T{}; struct F{}; void f() { const int* const T::* const * const * const x {}; // pointer to array - works in clang (trunk), // works in gcc (trunk) reinterpret_cast<int* const T::* const (*) [2]>(x); // member pointer to pointer - works in clang (trunk), // fails in gcc (trunk) reinterpret_cast<int* const * const * const * const>(x); // member pointer to another member pointer type - fails in clang (trunk), // fails in gcc (trunk) reinterpret_cast<int* const F::* const * const * const>(x); } ``` Recall the definition of similar. The types at each level must be of the categories: > ... each Pi is “pointer to” ([dcl.ptr]), “pointer to member of class Ci of > type” ([dcl.mptr]), “array of Ni”, or “array of unknown bound of” > ([dcl.array]) To be similar, each Pi must belong to the same category: > ... corresponding Pi components are either the same or one is “array of Ni” > and the other is “array of unknown bound of” In the first case, array and pointers are NOT similar. GCC and clang correctly says that the types `X[]` and `X*` are not similar and thus `reinterpret_cast` kicks in to ignore any const qualifiers past the array (so `const int* const` could be converted to `int*`). Everything is good. In the second case, pointers and member pointers should NOT be similar. clang correctly says that the types are not similar and thus `reinterpret_cast` kicks in. *GCC says the types are similar and thus we are casting away constness*. I'm pretty sure GCC is wrong here. In the third case, we are comparing **two member pointers of different classes**. Both clang and GCC believes they are similar, but if we carefully look at the draft, it says **"pointer to member of class Ci of type"**. If they're of different types, shouldn't we consider them to be not-similar? Are both clang and gcc wrong here? By the way, MSVC allows all of the above with no warnings (x64 msvc 19.27 on godbolt).