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.