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

            Bug ID: 127524
           Summary: ICE: error_mark type from a conflicting redeclaration
                    reaches match.pd/fold during gimplification
                    (type_has_mode_precision_p, types_match,
                    array_ref_low_bound, ...)
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: error-recovery, ice-checking, ice-on-invalid-code
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: captainnemo9292 at gmail dot com
  Target Milestone: ---
            Target: x86_64-linux-gnu

When a file-scope variable is referenced inside a function body and the same
identifier is later redeclared as a different kind of symbol, the C front end
poisons the old VAR_DECL by setting its TREE_TYPE to error_mark_node
(r12-3278). Function bodies that were already parsed still reference that
decl, and since gimplification runs even after errors, whatever fold/gimplify
code touches the expression first trips over the error_mark type.

r14-2721 (PR110699) added a guard in gimplify_compound_lval, and
PR117380 / PR115489 track the get_unwidened and create_tmp_from_val sites.
Trunk still ICEs in several other places on the same shape of input:

1. match.pd via fold() during gimplification, -O2 (type_has_mode_precision_p):

  unsigned long long x, y;
  unsigned long long foo(void) { return y << ((y - x) * 3); }
  unsigned x(void) { return 0; }

  $ gcc -O2 -c t.c
  t.c:3:10: error: 'x' redeclared as different kind of symbol
  t.c:2:41: internal compiler error: tree check: expected class 'type', have
'exceptional' (error_mark) in type_has_mode_precision_p, at tree.h:7094
  tree_class_check_failed
  generic_simplify_CONVERT_EXPR
  fold_unary_loc
  fold_build1_loc
  fold_unary_loc
  fold
  c_gimplify_expr
  gimplify_expr
  https://godbolt.org/z/Y8KoKvKjx

2. match.pd via fold(), -O2 (types_match in generic_simplify_NE_EXPR):

  unsigned long long ull2;
  unsigned long long foo(void) { return 1061476057LL << ((ull2 && 7) +
38312125535ULL); }
  unsigned ull2(void) { return 0; }

  internal compiler error: tree check: expected class 'type', have
'exceptional' (error_mark) in types_match, at generic-match-head.cc:63
  generic_simplify_NE_EXPR <- fold_binary_loc <- fold <- c_gimplify_expr <-
gimplify_expr
  https://godbolt.org/z/xd9vaz795

3. fold_const_call on strlen (array_ref_low_bound, a path r14-2721 does not
cover), -O0:

  int a[];
  int b() { return __builtin_strlen(&a[5]); }
  int a() {}

  internal compiler error: tree check: expected array_type, have error_mark in
array_ref_low_bound, at tree.cc:13331
  get_addr_base_and_unit_offset_1 <- getbyterep <- fold_const_call <-
gimplify_expr
  https://godbolt.org/z/o1GMo496f

4. gimple_fold_indirect_ref (useless_type_conversion_p), -O0:

  void h() { e f; e g; *(float *)&g = *(float *)&f; float f = 0; }

  internal compiler error: tree check: expected class 'type', have
'exceptional' (error_mark) in useless_type_conversion_p, at gimple-expr.cc:84
  gimple_fold_indirect_ref <- gimplify_expr <- gimplify_stmt
  https://godbolt.org/z/beh7q4cvE

For reference, the two sites that are already tracked reproduce with the same
pattern:  1 << (a - 1)  with a later redeclared as a function -> get_unwidened
(PR117380, https://godbolt.org/z/jWYrqKj7Y);  a ^ d(c)  with c later redeclared
-> create_tmp_from_val (PR115489, https://godbolt.org/z/e6db34KK9).

All of these are gcc trunk (17.0.0 20260920, x86_64-linux-gnu). Since the
poisoning is deliberate, the fix is probably either to stop gimplifying a
function whose body references a poisoned decl, or to make gimplify_expr
bail out on error_mark types before calling fold().

Reply via email to