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.

Reply via email to