https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89285
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |accepts-invalid CC| |jason at gcc dot gnu.org Summary|[8 Regression] ICE after |[8/9 Regression] ICE after |casting the this pointer in |casting the this pointer in |the constructor in C++17 |the constructor in C++17 |mode |mode --- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Ok, so: struct A { int a {}; }; struct B { int b {}; constexpr B (A *x) { int *c = &x->a; while (*c) c = reinterpret_cast<int *>((reinterpret_cast<char *>(c) + *c)); *c = reinterpret_cast<char *>(this) - reinterpret_cast<char *>(c); } }; struct C : A { B bar {this}; }; constexpr C foo {}; would then be accepts-invalid. I've tried to fix that by doing: --- gcc/cp/cp-gimplify.c (revision 268765) +++ gcc/cp/cp-gimplify.c (working copy) @@ -2307,6 +2307,22 @@ cp_fold (tree x) && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0)) TREE_OVERFLOW (x) = false; + /* Preserve REINTERPRET_CAST_P. */ + if (code == NOP_EXPR && REINTERPRET_CAST_P (org_x)) + { + if (TREE_CODE (x) == NOP_EXPR && REINTERPRET_CAST_P (x)) + break; + if (TREE_CODE (x) == NOP_EXPR) + { + x = copy_node (x); + REINTERPRET_CAST_P (x) = 1; + } + else + { + x = build1_loc (loc, code, TREE_TYPE (x), x); + REINTERPRET_CAST_P (x) = 1; + } + } break; case INDIRECT_REF: and with that we reject the testcase again (like we've done in 8.x, so this part is [9 Regression] accepts-invalid). But that also means we ICE again on the: C bar {}; So, maybe we want to ignore that: if (REINTERPRET_CAST_P (t)) { if (!ctx->quiet) error_at (cp_expr_loc_or_loc (t, input_location), "a reinterpret_cast is not a constant expression"); *non_constant_p = true; return t; } for perhaps !ctx->manifestly_const_eval , as in when we really don't require constant expression. But we don't really call constexpr with zero manifestly_const_eval anyway.