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().