The following valid test case (extracted from bug 70248) is accepted by GCC 7 (and Clang and ICC) but rejected by GCC 8: $ cat pr70248.C && gcc -S -Wall pr70248.C struct A {}; struct B : A { int x; }; constexpr int A::*bx = static_cast<int(A::*)>(&B::x); pr70248.C:4:24: error: a reinterpret_cast is not a constant expression constexpr int A::*bx = static_cast<int(A::*)>(&B::x); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The first revision to reject the test case is r249088: Overhaul pointer-to-member conversion and template argument handling. * call.c (standard_conversion): Avoid creating ck_pmem when the class type is the same. * cvt.c (can_convert_qual): Split from perform_qualification_conversions. * constexpr.c (cxx_eval_constant_expression): Check it. * typeck.c (convert_ptrmem): Only cplus_expand_constant if adjustment is necessary. * pt.c (check_valid_ptrmem_cst_expr): Compare class types. (convert_nontype_argument): Avoid redundant error.
Confirmed.
*** Bug 85438 has been marked as a duplicate of this bug. ***
convert_ptrmem here creates a NOP_EXPR around the PTRMEM_CST, even when it is for a static cast rather than reinterpret_cast. The OFFSET_TYPEs are different, but they have the same TREE_TYPE etc. Then constexpr.c doesn't consider that cast to be usable in constant expressions and because it is called with allow_non_constant, it wraps the new PTRMEM_CST with another NOP_EXPR and that is where following constexpr.c call errors on.
(gdb) p debug_tree (type) <offset_type 0x7fffefd9d150 type <integer_type 0x7fffefc625e8 int public type_6 SI size <integer_cst 0x7fffefc650c0 constant 32> unit-size <integer_cst 0x7fffefc650d8 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefc625e8 precision:32 min <integer_cst 0x7fffefc65078 -2147483648> max <integer_cst 0x7fffefc65090 2147483647> pointer_to_this <pointer_type 0x7fffefc6aa80>> DI size <integer_cst 0x7fffefc45e70 type <integer_type 0x7fffefc620a8 bitsizetype> constant 64> unit-size <integer_cst 0x7fffefc45e88 type <integer_type 0x7fffefc62000 sizetype> constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefd9d150 basetype <record_type 0x7fffefd88150 A>> $4 = void (gdb) p debug_tree (op->typed.type) <offset_type 0x7fffefd9d3f0 type <integer_type 0x7fffefc625e8 int public type_6 SI size <integer_cst 0x7fffefc650c0 constant 32> unit-size <integer_cst 0x7fffefc650d8 constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefc625e8 precision:32 min <integer_cst 0x7fffefc65078 -2147483648> max <integer_cst 0x7fffefc65090 2147483647> pointer_to_this <pointer_type 0x7fffefc6aa80>> DI size <integer_cst 0x7fffefc45e70 type <integer_type 0x7fffefc620a8 bitsizetype> constant 64> unit-size <integer_cst 0x7fffefc45e88 type <integer_type 0x7fffefc62000 sizetype> constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7fffefd9d3f0 basetype <record_type 0x7fffefd889d8 B>> Ah, one has basetype A, the other B, and both: 4600 if (same_type_ignoring_top_level_qualifiers_p (type, 4601 TREE_TYPE (op)) 4602 || can_convert_qual (type, op)) tests fail in this case.
FTR, there's a patch with various caveats at https://gcc.gnu.org/ml/gcc-patches/2018-04/msg00852.html
Author: jakub Date: Wed Apr 25 07:10:16 2018 New Revision: 259629 URL: https://gcc.gnu.org/viewcvs?rev=259629&root=gcc&view=rev Log: PR c++/85437 PR c++/49171 * cp-tree.h (REINTERPRET_CAST_P): New. * constexpr.c (cxx_eval_constant_expression) <case NOP_EXPR>: Reject REINTERPET_CAST_P conversions. Use cplus_expand_constant for non-trivial PTRMEM_CST cases. * typeck.c (build_nop_reinterpret): New. (build_reinterpret_cast_1): Use it. Set REINTERPRET_CAST_P on NOP_EXPRs returned by cp_convert. * g++.dg/cpp0x/addressof1.C: Make reinterpret cases runtime checks. * g++.dg/cpp0x/constexpr-cast.C: Remove xfails * g++.dg/cpp0x/constexpr-nullptr-2.C: Likewise. * g++.dg/cpp0x/constexpr-pmf1.C: Check when optimized. * g++.dg/cpp0x/pr85437-1.C: New. * g++.dg/cpp0x/pr85437-2.C: New. * g++.dg/cpp0x/pr85437-3.C: New. * g++.dg/cpp0x/pr85437-4.C: New. Added: trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-1.C trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-2.C trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-3.C trunk/gcc/testsuite/g++.dg/cpp0x/pr85437-4.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/cp/cp-tree.h trunk/gcc/cp/typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/cpp0x/addressof1.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-cast.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-pmf1.C
Fixed by Nathan.