https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84704

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Ugh, this one is really nasty.
If a statement-expression has side-effects, like for:
a[({ i++; 0; })] %= 5;
the FE wraps the statement expression with a SAVE_EXPR:
# DEBUG BEGIN STMT;
<<cleanup_point <<< Unknown tree: expr_stmt
  (void) (a[SAVE_EXPR <# DEBUG BEGIN STMT;
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) i++  >>>>>;
  # DEBUG BEGIN STMT;
  0>] = a[SAVE_EXPR <# DEBUG BEGIN STMT;
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) i++  >>>>>;
  # DEBUG BEGIN STMT;
  0>] % 5) >>>>>;
But as it doesn't have side-effects in this case, it isn't duplicated, and
unshare_expr/unshare_body uses mostly_copy_tree_r, which actually doesn't copy
STATEMENT_LISTs; and the gimplifier is destructive, so when the STATEMENT_LISTs
are shared by both ARRAY_REFs (which were unshared by unshare_body), the first
ARRAY_REF's index is gimplified fine, but turns the STATEMENT_LIST into void
typed one that only holds the DEBUG_BEGIN_STMT, and moves the constant out into
a temporary's initializer (which also looks problematic for -fcompare-debug)
and when we gimplify the second ARRAY_REF, we ICE, because ARRAY_REF index
really shouldn't have void type.

Reply via email to