Hi! The following patch implements the C2Y https://www.open-std.org/jtc1/sc22/WG14/www/docs/n3705.htm - bit-precise enum paper. In c_parser_enum_specifier it allows {,signed,unsigned} _BitInt(N) types as fixed underlying type of enums for -std=c2y/-std=gnu2y and the rest of the patch deals with that, mostly by adjusting the preexisting BITINT_TYPE_P macro (which was just used in one spot though) to not just include BITINT_TYPE types, but ENUMERAL_TYPE with BITINT_TYPE as underlying type, and changing lots of places that use TREE_CODE (type) == BITINT_TYPE to BITINT_TYPE_P (type). Like normal ENUMERAL_TYPEs are uselessly convertible in GIMPLE with same precision/sign INTEGER_TYPEs, ENUMERAL_TYPEs with BITINT_TYPE as underlying type are uselessly convertible with same precision/sign BITINT_TYPE and vice versa, so that extends the number of spots that need to use BITINT_TYPE_P macros.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2026-05-26 Jakub Jelinek <[email protected]> gcc/ * tree.h (BITINT_TYPE_P): Return true also for ENUMERAL_TYPE with BITINT_TYPE as underlying type. * stor-layout.cc (finish_bitfield_representative): Use BITINT_TYPE_P macro. (layout_type): Likewise. Lay out ENUMERAL_TYPEs with BITINT_TYPE as underlying type the same as BITINT_TYPEs. * gimple-lower-bitint.cc (maybe_cast_middle_bitint): Use BITINT_TYPE_P macro. (mergeable_op, optimizable_arith_overflow, comparison_op, bitint_large_huge::handle_cast, bitint_large_huge::lower_shift_stmt, bitint_large_huge::lower_muldiv_stmt, bitint_large_huge::lower_mul_overflow, bitint_large_huge::lower_bit_query, bitint_large_huge::lower_call, bitint_large_huge::lower_asm, bitint_large_huge::lower_stmt, build_bitint_stmt_ssa_conflicts, arith_overflow_arg_kind, gimple_lower_bitint): Likewise. * gimple-expr.cc (useless_type_conversion_p): Likewise. * fold-const.cc (make_range_step): Likewise. (range_check_type): For ENUMERAL_TYPEs with BITINT_TYPE as underlying type use the underlying type. (extract_muldiv_1): Use BITINT_TYPE_P macro. (native_encode_wide_int): Likewise. (native_interpret_int): Likewise. * vr-values.cc (simplify_using_ranges::simplify_float_conversion_using_ranges): Likewise. * cfgexpand.cc (expand_debug_expr): Likewise. * convert.cc (convert_to_integer_1): Add special case for ENUMERAL_TYPE with underlying BITINT_TYPE. * tree-ssa-sccvn.cc (vn_walk_cb_data::push_partial_def): Use BITINT_TYPE_P macro. (vn_reference_lookup_3): Likewise. (eliminate_dom_walker::eliminate_stmt): Likewise. * match.pd (ctz(ext(X)) == ctz(X), popcount(zext(X)) == popcount(X), parity(zext(X)) == parity(X), a != 0 ? CLZ(a) : CST -> .CLZ(a), a != 0 ? CTZ(a) : CST -> .CTZ(a), ffs(ext(X)) == ffs(X)): Likewise. * builtins.cc (fold_builtin_bit_query): Likewise. * explow.cc (promote_function_mode): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type like BITINT_TYPE. (promote_mode): Likewise. * expr.cc (EXTEND_BITINT): Use BITINT_TYPE_P macro. (expand_expr_real_1): Likewise. * fold-const-call.cc (fold_const_call_ss): Likewise. * gimple-fold.cc (gimple_fold_builtin_memset): Likewise. (clear_padding_type_may_have_padding_p): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type like BITINT_TYPE. (type_has_padding_at_level_p): Likewise. (clear_padding_type): Likewise. * gimple-match-exports.cc (build_call_internal): Use BITINT_TYPE_P macro. * internal-fn.cc (expand_ubsan_result_store): Likewise. * tree-sra.cc (create_access): Likewise. (analyze_access_subtree): Likewise. * tree-ssa-phiopt.cc (cond_removal_in_builtin_zero_pattern): Likewise. * tree-ssa.cc (maybe_optimize_var): Likewise. * tree-switch-conversion.cc (switch_conversion::array_value_type): Likewise. (switch_conversion::build_arrays): Likewise. (jump_table_cluster::emit): Likewise. * ubsan.cc (ubsan_encode_value): Likewise. (ubsan_type_descriptor): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type like BITINT_TYPE. (instrument_si_overflow): Use BITINT_TYPE_P macro. * varasm.cc (output_constant): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type like BITINT_TYPE. * config/aarch64/aarch64.cc (aarch64_return_in_memory_1): Use BITINT_TYPE_P macro. (bitint_or_aggr_of_bitint_p): Likewise. (aarch64_composite_type_p): Likewise. * config/arm/arm.cc (arm_return_in_memory): Likewise. (arm_needs_doubleword_align): Likewise. * config/i386/i386.cc (classify_argument): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type like BITINT_TYPE. * config/loongarch/loongarch.h: Use BITINT_TYPE_P macro. gcc/c-family/ * c-attribs.cc (type_valid_for_vector_size): Use BITINT_TYPE_P macro. * c-common.cc (c_common_get_narrower): For ENUMERAL_TYPE with BITINT_TYPE as underlying type convert to the underlying type. (c_common_signed_or_unsigned_type): Use BITINT_TYPE_P macro. (sync_resolve_size): Likewise. (atomic_bitint_fetch_using_cas_loop): Likewise. (resolve_overloaded_builtin): Likewise. gcc/c/ * c-parser.cc (c_parser_enum_specifier): Implement C2Y N3705: bit-precise enum. Allow for flag_isoc2y enumerated types with BITINT_TYPE as underlying type. * c-lang.cc (LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE): Redefine. * c-tree.h (c_enum_underlying_base_type): Declare. * c-objc-common.cc (c_enum_underlying_base_type): New function. * c-decl.cc (finish_struct): Use BITINT_TYPE_P macro. gcc/testsuite/ * gcc.dg/bitint-133.c: New test. * gcc.dg/bitint-134.c: New test. * gcc.dg/bitint-135.c: New test. * gcc.dg/torture/bitint-99.c: New test. --- gcc/tree.h.jj 2026-05-19 13:38:49.964345640 +0200 +++ gcc/tree.h 2026-05-25 16:11:20.943419398 +0200 @@ -633,9 +633,14 @@ extern void omp_clause_range_check_faile || VECTOR_TYPE_P (TYPE)) \ && INTEGRAL_TYPE_P (TREE_TYPE (TYPE)))) -/* Nonzero if TYPE is bit-precise integer type. */ +/* Nonzero if TYPE is bit-precise integer type or enumeral type + with bit-precise integer type as underlying type. */ -#define BITINT_TYPE_P(TYPE) (TREE_CODE (TYPE) == BITINT_TYPE) +#define BITINT_TYPE_P(TYPE) \ + (TREE_CODE (TYPE) == BITINT_TYPE \ + || (TREE_CODE (TYPE) == ENUMERAL_TYPE \ + && TREE_TYPE (TYPE) \ + && TREE_CODE (TREE_TYPE (TYPE)) == BITINT_TYPE)) /* Nonzero if TYPE represents a non-saturating fixed-point type. */ --- gcc/stor-layout.cc.jj 2026-03-27 10:17:14.544324049 +0100 +++ gcc/stor-layout.cc 2026-05-26 09:51:50.647130308 +0200 @@ -2180,7 +2180,7 @@ finish_bitfield_representative (tree rep || GET_MODE_BITSIZE (mode) > maxbitsize || GET_MODE_BITSIZE (mode) > MAX_FIXED_MODE_SIZE) { - if (TREE_CODE (TREE_TYPE (field)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (field))) { struct bitint_info info; unsigned prec = TYPE_PRECISION (TREE_TYPE (field)); @@ -2459,15 +2459,19 @@ layout_type (tree type) case BOOLEAN_TYPE: case INTEGER_TYPE: case ENUMERAL_TYPE: - { - scalar_int_mode mode - = smallest_int_mode_for_size (TYPE_PRECISION (type)).require (); - SET_TYPE_MODE (type, mode); - TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode)); - /* Don't set TYPE_PRECISION here, as it may be set by a bitfield. */ - TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode)); - break; - } + if (TREE_CODE (type) != ENUMERAL_TYPE + || TREE_TYPE (type) == NULL_TREE + || TREE_CODE (TREE_TYPE (type)) != BITINT_TYPE) + { + scalar_int_mode mode + = smallest_int_mode_for_size (TYPE_PRECISION (type)).require (); + SET_TYPE_MODE (type, mode); + TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (mode)); + /* Don't set TYPE_PRECISION here, as it may be set by a bitfield. */ + TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode)); + break; + } + /* FALLTHRU */ case BITINT_TYPE: { @@ -2558,7 +2562,7 @@ layout_type (tree type) TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type)); if (TYPE_MODE (TREE_TYPE (type)) == BLKmode) { - gcc_checking_assert (TREE_CODE (TREE_TYPE (type)) == BITINT_TYPE); + gcc_checking_assert (BITINT_TYPE_P (TREE_TYPE (type))); SET_TYPE_MODE (type, BLKmode); TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (TREE_TYPE (type)), --- gcc/gimple-lower-bitint.cc.jj 2026-04-29 11:12:44.473480952 +0200 +++ gcc/gimple-lower-bitint.cc 2026-05-25 16:20:55.725489771 +0200 @@ -185,7 +185,7 @@ tree maybe_cast_middle_bitint (gimple_stmt_iterator *gsi, tree op, tree &type) { if (op == NULL_TREE - || TREE_CODE (TREE_TYPE (op)) != BITINT_TYPE + || !BITINT_TYPE_P (TREE_TYPE (op)) || bitint_precision_kind (TREE_TYPE (op)) != bitint_prec_middle) return op; @@ -244,8 +244,8 @@ mergeable_op (gimple *stmt) tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt)); tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME - && TREE_CODE (lhs_type) == BITINT_TYPE - && TREE_CODE (rhs_type) == BITINT_TYPE + && BITINT_TYPE_P (lhs_type) + && BITINT_TYPE_P (rhs_type) && bitint_precision_kind (lhs_type) >= bitint_prec_large && bitint_precision_kind (rhs_type) >= bitint_prec_large && (CEIL (TYPE_PRECISION (lhs_type), limb_prec) @@ -302,7 +302,7 @@ optimizable_arith_overflow (gimple *stmt if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) return 0; tree type = is_ubsan ? TREE_TYPE (lhs) : TREE_TYPE (TREE_TYPE (lhs)); - if (TREE_CODE (type) != BITINT_TYPE + if (!BITINT_TYPE_P (type) || bitint_precision_kind (type) < bitint_prec_large) return 0; @@ -356,7 +356,7 @@ optimizable_arith_overflow (gimple *stmt lhs2 = gimple_assign_lhs (use_stmt); if (!INTEGRAL_TYPE_P (TREE_TYPE (lhs2)) - || TREE_CODE (TREE_TYPE (lhs2)) == BITINT_TYPE) + || BITINT_TYPE_P (TREE_TYPE (lhs2))) return 0; cast = use_stmt; } @@ -415,7 +415,7 @@ comparison_op (gimple *stmt, tree *pop1, if (TREE_CODE_CLASS (code) != tcc_comparison) return ERROR_MARK; tree type = TREE_TYPE (op1); - if (TREE_CODE (type) != BITINT_TYPE + if (!BITINT_TYPE_P (type) || bitint_precision_kind (type) < bitint_prec_large) return ERROR_MARK; if (pop1) @@ -1369,8 +1369,8 @@ bitint_large_huge::handle_cast (tree lhs tree rhs_type = TREE_TYPE (rhs1); gimple *g; if ((TREE_CODE (rhs1) == SSA_NAME || TREE_CODE (rhs1) == INTEGER_CST) - && TREE_CODE (lhs_type) == BITINT_TYPE - && TREE_CODE (rhs_type) == BITINT_TYPE + && BITINT_TYPE_P (lhs_type) + && BITINT_TYPE_P (rhs_type) && bitint_precision_kind (lhs_type) >= bitint_prec_large && bitint_precision_kind (rhs_type) >= bitint_prec_large) { @@ -1737,7 +1737,7 @@ bitint_large_huge::handle_cast (tree lhs return t; } } - else if (TREE_CODE (lhs_type) == BITINT_TYPE + else if (BITINT_TYPE_P (lhs_type) && bitint_precision_kind (lhs_type) >= bitint_prec_large && INTEGRAL_TYPE_P (rhs_type)) { @@ -1755,7 +1755,7 @@ bitint_large_huge::handle_cast (tree lhs m_gsi = gsi_after_labels (gsi_bb (m_gsi)); else gsi_next (&m_gsi); - if (TREE_CODE (rhs_type) == BITINT_TYPE + if (BITINT_TYPE_P (rhs_type) && bitint_precision_kind (rhs_type) == bitint_prec_middle) { tree type = NULL_TREE; @@ -2424,7 +2424,7 @@ bitint_large_huge::handle_operand_addr ( location_t loc_save = m_loc; tree ret = NULL_TREE; int precs = 0; - if ((TREE_CODE (TREE_TYPE (op)) != BITINT_TYPE + if ((!BITINT_TYPE_P (TREE_TYPE (op)) || bitint_precision_kind (TREE_TYPE (op)) < bitint_prec_large) && TREE_CODE (op) != INTEGER_CST) { @@ -2432,7 +2432,7 @@ bitint_large_huge::handle_operand_addr ( *prec = range_to_prec (op, stmt); bitint_prec_kind kind = bitint_prec_small; gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (op))); - if (TREE_CODE (TREE_TYPE (op)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (op))) kind = bitint_precision_kind (TREE_TYPE (op)); if (kind == bitint_prec_middle) { @@ -2542,7 +2542,7 @@ bitint_large_huge::handle_operand_addr ( if (TREE_CODE (rhs1) == VIEW_CONVERT_EXPR) rhs1 = TREE_OPERAND (rhs1, 0); gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (rhs1))); - if (TREE_CODE (TREE_TYPE (rhs1)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (rhs1))) kind = bitint_precision_kind (TREE_TYPE (rhs1)); if (kind >= bitint_prec_large) { @@ -2625,12 +2625,12 @@ bitint_large_huge::handle_operand_addr ( if (mp == 0) mp = 1; if (mp >= (unsigned) TYPE_PRECISION (TREE_TYPE (op)) - && (TREE_CODE (TREE_TYPE (op)) == BITINT_TYPE + && (BITINT_TYPE_P (TREE_TYPE (op)) || TYPE_PRECISION (TREE_TYPE (op)) <= limb_prec)) type = TREE_TYPE (op); else type = build_bitint_type (mp, 1); - if (TREE_CODE (type) != BITINT_TYPE + if (!BITINT_TYPE_P (type) || bitint_precision_kind (type) == bitint_prec_small) { if (TYPE_PRECISION (type) <= limb_prec) @@ -2730,7 +2730,7 @@ bitint_large_huge::lower_mergeable_stmt type = TREE_TYPE (cmp_op1); else type = TREE_TYPE (gimple_assign_lhs (stmt)); - gcc_assert (TREE_CODE (type) == BITINT_TYPE); + gcc_assert (BITINT_TYPE_P (type)); bitint_prec_kind kind = bitint_precision_kind (type); gcc_assert (kind >= bitint_prec_large); gimple *g; @@ -2738,7 +2738,7 @@ bitint_large_huge::lower_mergeable_stmt tree rhs1, lhs_type = lhs ? TREE_TYPE (lhs) : NULL_TREE; if (lhs && TREE_CODE (lhs) == SSA_NAME - && TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (lhs)) && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large) { int p = var_to_partition (m_map, lhs); @@ -2836,7 +2836,7 @@ bitint_large_huge::lower_mergeable_stmt if (TREE_CODE (rhs1) == SSA_NAME && (m_names == NULL || !bitmap_bit_p (m_names, SSA_NAME_VERSION (rhs1))) - && TREE_CODE (TREE_TYPE (rhs1)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (rhs1)) && bitint_precision_kind (TREE_TYPE (rhs1)) >= bitint_prec_large && (CEIL ((unsigned) TYPE_PRECISION (TREE_TYPE (rhs1)), limb_prec) < CEIL (prec, limb_prec) @@ -3372,7 +3372,7 @@ bitint_large_huge::lower_comparison_stmt tree cmp_op1, tree cmp_op2) { tree type = TREE_TYPE (cmp_op1); - gcc_assert (TREE_CODE (type) == BITINT_TYPE); + gcc_assert (BITINT_TYPE_P (type)); bitint_prec_kind kind = bitint_precision_kind (type); gcc_assert (kind >= bitint_prec_large); gimple *g; @@ -3506,7 +3506,7 @@ bitint_large_huge::lower_shift_stmt (tre tree_code rhs_code = gimple_assign_rhs_code (stmt); tree type = TREE_TYPE (rhs1); gimple *final_stmt = gsi_stmt (m_gsi); - gcc_assert (TREE_CODE (type) == BITINT_TYPE + gcc_assert (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large); int prec = TYPE_PRECISION (type); tree n = gimple_assign_rhs2 (stmt), n1, n2, n3, n4; @@ -4082,7 +4082,7 @@ bitint_large_huge::lower_muldiv_stmt (tr tree lhs = gimple_assign_lhs (stmt); tree_code rhs_code = gimple_assign_rhs_code (stmt); tree type = TREE_TYPE (rhs1); - gcc_assert (TREE_CODE (type) == BITINT_TYPE + gcc_assert (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large); int prec = TYPE_PRECISION (type), prec1, prec2; bool ext_ms_limb = false; @@ -4426,7 +4426,7 @@ bitint_large_huge::finish_arith_overflow gimple *g; if (obj == NULL_TREE - && (TREE_CODE (type) != BITINT_TYPE + && (!BITINT_TYPE_P (type) || bitint_precision_kind (type) < bitint_prec_large)) { /* Add support for 3 or more limbs filled in from normal integral @@ -4435,7 +4435,7 @@ bitint_large_huge::finish_arith_overflow be needed. */ gcc_assert (TYPE_PRECISION (type) <= 2 * limb_prec); tree lhs_type = type; - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) == bitint_prec_middle) lhs_type = build_nonstandard_integer_type (TYPE_PRECISION (type), TYPE_UNSIGNED (type)); @@ -4781,7 +4781,7 @@ bitint_large_huge::lower_addsub_overflow tree var = NULL_TREE; tree orig_obj = obj; if (obj == NULL_TREE - && TREE_CODE (type) == BITINT_TYPE + && BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large && m_names && bitmap_bit_p (m_names, SSA_NAME_VERSION (lhs))) @@ -4792,7 +4792,7 @@ bitint_large_huge::lower_addsub_overflow if (TREE_TYPE (lhs) == type) orig_obj = obj; } - if (TREE_CODE (type) != BITINT_TYPE + if (!BITINT_TYPE_P (type) || bitint_precision_kind (type) < bitint_prec_large) { unsigned HOST_WIDE_INT nelts = CEIL (prec, limb_prec); @@ -5289,7 +5289,7 @@ bitint_large_huge::lower_mul_overflow (t tree orig_obj = obj; bool force_var = false; if (obj == NULL_TREE - && TREE_CODE (type) == BITINT_TYPE + && BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large && m_names && bitmap_bit_p (m_names, SSA_NAME_VERSION (lhs))) @@ -5316,7 +5316,7 @@ bitint_large_huge::lower_mul_overflow (t } if (obj == NULL_TREE || force_var - || TREE_CODE (type) != BITINT_TYPE + || !BITINT_TYPE_P (type) || bitint_precision_kind (type) < bitint_prec_large || prec2 > (CEIL (prec, limb_prec) * limb_prec * (orig_obj ? 1 : 2))) { @@ -5592,7 +5592,7 @@ bitint_large_huge::lower_bit_query (gimp return; } tree type = TREE_TYPE (arg0); - gcc_assert (TREE_CODE (type) == BITINT_TYPE); + gcc_assert (BITINT_TYPE_P (type)); bitint_prec_kind kind = bitint_precision_kind (type); gcc_assert (kind >= bitint_prec_large); enum internal_fn ifn = gimple_call_internal_fn (stmt); @@ -6143,7 +6143,7 @@ bitint_large_huge::lower_call (tree obj, { tree arg = gimple_call_arg (stmt, i); if (TREE_CODE (arg) != SSA_NAME - || TREE_CODE (TREE_TYPE (arg)) != BITINT_TYPE + || !BITINT_TYPE_P (TREE_TYPE (arg)) || bitint_precision_kind (TREE_TYPE (arg)) <= bitint_prec_middle) continue; if (SSA_NAME_IS_DEFAULT_DEF (arg) @@ -6176,7 +6176,7 @@ bitint_large_huge::lower_call (tree obj, tree lhs = gimple_call_lhs (stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME - && TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (lhs)) && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large) { int p = var_to_partition (m_map, lhs); @@ -6204,7 +6204,7 @@ bitint_large_huge::lower_asm (gimple *st tree t = gimple_asm_output_op (g, i); tree s = TREE_VALUE (t); if (TREE_CODE (s) == SSA_NAME - && TREE_CODE (TREE_TYPE (s)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (s)) && bitint_precision_kind (TREE_TYPE (s)) >= bitint_prec_large) { int part = var_to_partition (m_map, s); @@ -6217,7 +6217,7 @@ bitint_large_huge::lower_asm (gimple *st tree t = gimple_asm_input_op (g, i); tree s = TREE_VALUE (t); if (TREE_CODE (s) == SSA_NAME - && TREE_CODE (TREE_TYPE (s)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (s)) && bitint_precision_kind (TREE_TYPE (s)) >= bitint_prec_large) { if (SSA_NAME_IS_DEFAULT_DEF (s) @@ -6280,11 +6280,11 @@ bitint_large_huge::lower_stmt (gimple *s tree rhs1 = gimple_assign_rhs1 (stmt); if (TREE_CODE (rhs1) == VIEW_CONVERT_EXPR) rhs1 = TREE_OPERAND (rhs1, 0); - if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (lhs)) && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))) mergeable_cast_p = true; - else if (TREE_CODE (TREE_TYPE (rhs1)) == BITINT_TYPE + else if (BITINT_TYPE_P (TREE_TYPE (rhs1)) && bitint_precision_kind (TREE_TYPE (rhs1)) >= bitint_prec_large && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) || POINTER_TYPE_P (TREE_TYPE (lhs)) @@ -6368,7 +6368,7 @@ bitint_large_huge::lower_stmt (gimple *s } } } - else if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + else if (BITINT_TYPE_P (TREE_TYPE (lhs)) && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large && !INTEGRAL_TYPE_P (TREE_TYPE (rhs1)) && !POINTER_TYPE_P (TREE_TYPE (rhs1)) @@ -6480,7 +6480,7 @@ bitint_large_huge::lower_stmt (gimple *s boolean_false_node); gimple_assign_set_rhs1 (stmt, cond); lhs = gimple_assign_lhs (stmt); - gcc_assert (TREE_CODE (TREE_TYPE (lhs)) != BITINT_TYPE + gcc_assert (!BITINT_TYPE_P (TREE_TYPE (lhs)) || (bitint_precision_kind (TREE_TYPE (lhs)) <= bitint_prec_middle)); update_stmt (stmt); @@ -6501,7 +6501,7 @@ bitint_large_huge::lower_stmt (gimple *s be needed. */ gcc_assert (TYPE_PRECISION (lhs_type) <= 2 * limb_prec); gimple *g; - if ((TREE_CODE (lhs_type) == BITINT_TYPE + if ((BITINT_TYPE_P (lhs_type) && bitint_precision_kind (lhs_type) == bitint_prec_middle) || POINTER_TYPE_P (lhs_type)) lhs_type = build_nonstandard_integer_type (TYPE_PRECISION (lhs_type), @@ -6651,7 +6651,7 @@ bitint_dom_walker::before_dom_children ( tree lhs = gimple_get_lhs (stmt); if (lhs && TREE_CODE (lhs) == SSA_NAME - && TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (lhs)) && bitint_precision_kind (TREE_TYPE (lhs)) >= bitint_prec_large && !bitmap_bit_p (m_names, SSA_NAME_VERSION (lhs))) /* If lhs of stmt is large/huge _BitInt SSA_NAME not in m_names, @@ -6666,7 +6666,7 @@ bitint_dom_walker::before_dom_children ( FOR_EACH_SSA_USE_OPERAND (use_p, stmt, oi, SSA_OP_USE) { tree s = USE_FROM_PTR (use_p); - if (TREE_CODE (TREE_TYPE (s)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (s)) && bitint_precision_kind (TREE_TYPE (s)) >= bitint_prec_large) worklist.safe_push (s); } @@ -6683,7 +6683,7 @@ bitint_dom_walker::before_dom_children ( FOR_EACH_SSA_USE_OPERAND (use_p, g, oi, SSA_OP_USE) { tree s2 = USE_FROM_PTR (use_p); - if (TREE_CODE (TREE_TYPE (s2)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (s2)) && (bitint_precision_kind (TREE_TYPE (s2)) >= bitint_prec_large)) worklist.safe_push (s2); @@ -6778,7 +6778,7 @@ build_bitint_stmt_ssa_conflicts (gimple tree type = TREE_TYPE (lhs); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (!bitmap_bit_p (names, SSA_NAME_VERSION (lhs))) @@ -6856,7 +6856,7 @@ build_bitint_stmt_ssa_conflicts (gimple if (TREE_CODE (ltype) == COMPLEX_TYPE) muldiv_p = true; else if (TREE_CODE (lhs) == SSA_NAME - && TREE_CODE (ltype) == BITINT_TYPE + && BITINT_TYPE_P (ltype) && bitint_precision_kind (ltype) >= bitint_prec_large) { unsigned lnelts = CEIL (TYPE_PRECISION (ltype), limb_prec); @@ -6865,7 +6865,7 @@ build_bitint_stmt_ssa_conflicts (gimple tree type = TREE_TYPE (var); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (bitmap_bit_p (names, SSA_NAME_VERSION (var))) @@ -6892,7 +6892,7 @@ build_bitint_stmt_ssa_conflicts (gimple tree type = TREE_TYPE (var); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (bitmap_bit_p (names, SSA_NAME_VERSION (var))) @@ -6943,7 +6943,7 @@ build_bitint_stmt_ssa_conflicts (gimple tree type = TREE_TYPE (var); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (bitmap_bit_p (names, SSA_NAME_VERSION (var))) @@ -6961,7 +6961,7 @@ build_bitint_stmt_ssa_conflicts (gimple tree type = TREE_TYPE (var); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (bitmap_bit_p (names, SSA_NAME_VERSION (var))) @@ -6994,7 +6994,7 @@ arith_overflow_arg_kind (gimple *stmt) { tree a = gimple_call_arg (stmt, i); if (TREE_CODE (a) == INTEGER_CST - && TREE_CODE (TREE_TYPE (a)) == BITINT_TYPE) + && BITINT_TYPE_P (TREE_TYPE (a))) { bitint_prec_kind kind = bitint_precision_kind (TREE_TYPE (a)); ret = MAX (ret, kind); @@ -7030,7 +7030,7 @@ gimple_lower_bitint (void) break; type = TREE_TYPE (type); } - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) != bitint_prec_small) break; /* We need to also rewrite stores of large/huge _BitInt INTEGER_CSTs @@ -7041,7 +7041,7 @@ gimple_lower_bitint (void) if (is_gimple_assign (g) && gimple_store_p (g)) { tree t = gimple_assign_rhs1 (g); - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (t)) && (bitint_precision_kind (TREE_TYPE (t)) >= bitint_prec_large)) break; @@ -7056,7 +7056,7 @@ gimple_lower_bitint (void) { tree t = gimple_assign_rhs1 (g); if (TREE_CODE (t) == INTEGER_CST - && TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (t)) && (bitint_precision_kind (TREE_TYPE (t)) != bitint_prec_small)) break; @@ -7073,7 +7073,7 @@ gimple_lower_bitint (void) if (gswitch *swtch = safe_dyn_cast <gswitch *> (*gsi_last_bb (bb))) { tree idx = gimple_switch_index (swtch); - if (TREE_CODE (TREE_TYPE (idx)) != BITINT_TYPE + if (!BITINT_TYPE_P (TREE_TYPE (idx)) || bitint_precision_kind (TREE_TYPE (idx)) < bitint_prec_large) continue; @@ -7130,7 +7130,7 @@ gimple_lower_bitint (void) has_large_huge = true; type = TREE_TYPE (type); } - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (first_large_huge == ~0U) @@ -7339,7 +7339,7 @@ gimple_lower_bitint (void) if (is_gimple_assign (g) && gimple_store_p (g)) { tree t = gimple_assign_rhs1 (g); - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (t)) && (bitint_precision_kind (TREE_TYPE (t)) >= bitint_prec_large)) has_large_huge = true; @@ -7354,7 +7354,7 @@ gimple_lower_bitint (void) { tree t = gimple_assign_rhs1 (g); if (TREE_CODE (t) == INTEGER_CST - && TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (t)) && (bitint_precision_kind (TREE_TYPE (t)) >= bitint_prec_large)) has_large_huge = true; @@ -7369,7 +7369,7 @@ gimple_lower_bitint (void) tree type = TREE_TYPE (s); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { use_operand_p use_p; @@ -7452,7 +7452,7 @@ gimple_lower_bitint (void) goto force_name; /* FALLTHRU */ case MULT_EXPR: - if (TREE_CODE (TREE_TYPE (rhs1)) != BITINT_TYPE + if (!BITINT_TYPE_P (TREE_TYPE (rhs1)) || (bitint_precision_kind (TREE_TYPE (rhs1)) < bitint_prec_large)) continue; @@ -7485,7 +7485,7 @@ gimple_lower_bitint (void) default: break; } - if (TREE_CODE (TREE_TYPE (rhs1)) != BITINT_TYPE + if (!BITINT_TYPE_P (TREE_TYPE (rhs1)) || (bitint_precision_kind (TREE_TYPE (rhs1)) < bitint_prec_large)) continue; @@ -7519,7 +7519,7 @@ gimple_lower_bitint (void) not mergeable. */ tree rhs2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (rhs1)); - if (TREE_CODE (TREE_TYPE (rhs2)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (rhs2)) && (TYPE_PRECISION (TREE_TYPE (rhs1)) == TYPE_PRECISION (TREE_TYPE (rhs2)))) { @@ -7718,7 +7718,7 @@ gimple_lower_bitint (void) if (is_gimple_assign (g) && gimple_store_p (g)) { tree t = gimple_assign_rhs1 (g); - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (t)) && bitint_precision_kind (TREE_TYPE (t)) >= bitint_prec_large) has_large_huge = true; } @@ -7822,7 +7822,7 @@ gimple_lower_bitint (void) bitint_prec_kind kind = bitint_prec_small; tree t; FOR_EACH_SSA_TREE_OPERAND (t, stmt, iter, SSA_OP_ALL_OPERANDS) - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (t))) { bitint_prec_kind this_kind = bitint_precision_kind (TREE_TYPE (t)); @@ -7831,7 +7831,7 @@ gimple_lower_bitint (void) if (is_gimple_assign (stmt) && gimple_store_p (stmt)) { t = gimple_assign_rhs1 (stmt); - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (t))) { bitint_prec_kind this_kind = bitint_precision_kind (TREE_TYPE (t)); @@ -7842,7 +7842,7 @@ gimple_lower_bitint (void) && gimple_assign_rhs_code (stmt) == FLOAT_EXPR) { t = gimple_assign_rhs1 (stmt); - if (TREE_CODE (TREE_TYPE (t)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (t)) && TREE_CODE (t) == INTEGER_CST) { bitint_prec_kind this_kind @@ -7857,7 +7857,7 @@ gimple_lower_bitint (void) { bitint_prec_kind this_kind = arith_overflow_arg_kind (stmt); kind = MAX (kind, this_kind); - if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (TREE_TYPE (t)))) { this_kind = bitint_precision_kind (TREE_TYPE (TREE_TYPE (t))); @@ -7940,7 +7940,7 @@ gimple_lower_bitint (void) } } if (tree lhs = gimple_get_lhs (stmt)) - if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (lhs)) && (bitint_precision_kind (TREE_TYPE (lhs)) == bitint_prec_middle)) { @@ -7969,7 +7969,7 @@ gimple_lower_bitint (void) tree type = TREE_TYPE (lhs); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large && (large_huge.m_names == NULL || !bitmap_bit_p (large_huge.m_names, @@ -7986,7 +7986,7 @@ gimple_lower_bitint (void) { gphi *phi = gsi.phi (); tree lhs = gimple_phi_result (phi); - if (TREE_CODE (TREE_TYPE (lhs)) != BITINT_TYPE + if (!BITINT_TYPE_P (TREE_TYPE (lhs)) || bitint_precision_kind (TREE_TYPE (lhs)) < bitint_prec_large) continue; int p1 = var_to_partition (large_huge.m_map, lhs); @@ -8216,7 +8216,7 @@ gimple_lower_bitint (void) tree type = TREE_TYPE (s); if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) && bitint_precision_kind (type) >= bitint_prec_large) { if (large_huge.m_preserved --- gcc/gimple-expr.cc.jj 2026-03-27 10:17:14.161330299 +0100 +++ gcc/gimple-expr.cc 2026-05-25 16:21:39.899803673 +0200 @@ -116,8 +116,7 @@ useless_type_conversion_p (tree outer_ty body, we need to prevent changing BITINT_TYPE to INTEGER_TYPE of the same precision or vice versa when passed to functions, especially for varargs. */ - if ((TREE_CODE (inner_type) == BITINT_TYPE) - != (TREE_CODE (outer_type) == BITINT_TYPE)) + if (BITINT_TYPE_P (inner_type) != BITINT_TYPE_P (outer_type)) return false; /* We don't need to preserve changes in the types minimum or --- gcc/fold-const.cc.jj 2026-05-25 09:46:35.647977576 +0200 +++ gcc/fold-const.cc 2026-05-25 16:30:37.810449278 +0200 @@ -5426,7 +5426,7 @@ make_range_step (location_t loc, enum tr equiv_type = lang_hooks.types.type_for_mode (TYPE_MODE (arg0_type), TYPE_SATURATING (arg0_type)); - else if (TREE_CODE (arg0_type) == BITINT_TYPE) + else if (BITINT_TYPE_P (arg0_type)) equiv_type = arg0_type; else equiv_type @@ -5616,7 +5616,9 @@ range_check_type (tree etype) { /* First make sure that arithmetics in this type is valid, then make sure that it wraps around. */ - if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE) + if (TREE_CODE (etype) == ENUMERAL_TYPE && BITINT_TYPE_P (etype)) + etype = TREE_TYPE (etype); + else if (TREE_CODE (etype) == ENUMERAL_TYPE || TREE_CODE (etype) == BOOLEAN_TYPE) etype = lang_hooks.types.type_for_size (TYPE_PRECISION (etype), 1); if (TREE_CODE (etype) == INTEGER_TYPE && !TYPE_UNSIGNED (etype)) @@ -6572,8 +6574,7 @@ extract_muldiv_1 (tree t, tree c, enum t tree ctype = type; if (wide_type) { - if (TREE_CODE (type) == BITINT_TYPE - || TREE_CODE (wide_type) == BITINT_TYPE) + if (BITINT_TYPE_P (type) || BITINT_TYPE_P (wide_type)) { if (TYPE_PRECISION (wide_type) > TYPE_PRECISION (type)) ctype = wide_type; @@ -7455,7 +7456,7 @@ native_encode_wide_int (tree type, const unsigned char *ptr, int len, int off) { int total_bytes; - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { struct bitint_info info; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); @@ -8479,7 +8480,7 @@ static tree native_interpret_int (tree type, const unsigned char *ptr, int len) { int total_bytes; - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { struct bitint_info info; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); --- gcc/vr-values.cc.jj 2026-03-27 10:17:21.524210148 +0100 +++ gcc/vr-values.cc 2026-05-25 16:47:56.811399398 +0200 @@ -1561,7 +1561,7 @@ simplify_using_ranges::simplify_float_co /* The code below doesn't work for large/huge _BitInt, nor is really needed for those, bitint lowering does use ranges already. */ - if (TREE_CODE (TREE_TYPE (rhs1)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (rhs1)) && TYPE_MODE (TREE_TYPE (rhs1)) == BLKmode) return false; /* First check if we can use a signed type in place of an unsigned. */ --- gcc/cfgexpand.cc.jj 2026-03-27 10:17:13.733337283 +0100 +++ gcc/cfgexpand.cc 2026-05-25 17:23:28.271305196 +0200 @@ -4924,7 +4924,7 @@ expand_debug_expr (tree exp) /* Fall through. */ case INTEGER_CST: - if (TREE_CODE (TREE_TYPE (exp)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (exp)) && TYPE_MODE (TREE_TYPE (exp)) == BLKmode) return NULL; /* FALLTHRU */ --- gcc/convert.cc.jj 2026-03-27 10:17:13.997332975 +0100 +++ gcc/convert.cc 2026-05-26 10:39:49.517405462 +0200 @@ -704,6 +704,12 @@ convert_to_integer_1 (tree type, tree ex return maybe_fold_build1_loc (dofold, loc, code, type, expr); } + else if (TREE_CODE (type) == ENUMERAL_TYPE && BITINT_TYPE_P (type)) + { + expr = convert_to_integer_1 (TREE_TYPE (type), expr, dofold); + return maybe_fold_build1_loc (dofold, loc, NOP_EXPR, type, expr); + } + /* If TYPE is an enumeral type or a type with a precision less than the number of bits in its mode, do the conversion to the type corresponding to its mode, then do a nop conversion --- gcc/tree-ssa-sccvn.cc.jj 2026-05-19 13:38:49.962345673 +0200 +++ gcc/tree-ssa-sccvn.cc 2026-05-25 18:05:19.431251513 +0200 @@ -2349,7 +2349,7 @@ vn_walk_cb_data::push_partial_def (pd_da access size. */ if (INTEGRAL_TYPE_P (vr->type) && maxsizei != TYPE_PRECISION (vr->type)) { - if (TREE_CODE (vr->type) == BITINT_TYPE + if (BITINT_TYPE_P (vr->type) && maxsizei > MAX_FIXED_MODE_SIZE) type = build_bitint_type (maxsizei, TYPE_UNSIGNED (type)); else @@ -3285,7 +3285,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree && maxsizei != TYPE_PRECISION (vr->type)) { bool uns = TYPE_UNSIGNED (type); - if (TREE_CODE (vr->type) == BITINT_TYPE + if (BITINT_TYPE_P (vr->type) && maxsizei > MAX_FIXED_MODE_SIZE) type = build_bitint_type (maxsizei, uns); else @@ -7393,7 +7393,7 @@ eliminate_dom_walker::eliminate_stmt (ba || !DECL_BIT_FIELD_TYPE (TREE_OPERAND (lhs, 1))) && !type_has_mode_precision_p (TREE_TYPE (lhs))) { - if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (lhs)) && TYPE_PRECISION (TREE_TYPE (lhs)) > MAX_FIXED_MODE_SIZE) lookup_lhs = NULL_TREE; else if (TREE_CODE (lhs) == COMPONENT_REF --- gcc/match.pd.jj 2026-05-25 09:46:35.652977496 +0200 +++ gcc/match.pd 2026-05-25 18:06:35.743049923 +0200 @@ -10252,7 +10252,7 @@ (define_operator_list SYNC_FETCH_AND_AND && TYPE_PRECISION (TREE_TYPE (@1)) > TYPE_PRECISION (TREE_TYPE (@0))) (with { combined_fn cfn = CFN_LAST; tree type0 = TREE_TYPE (@0); - if (TREE_CODE (type0) == BITINT_TYPE) + if (BITINT_TYPE_P (type0)) { if (TYPE_PRECISION (type0) > MAX_FIXED_MODE_SIZE) cfn = CFN_CTZ; @@ -10392,7 +10392,7 @@ (define_operator_list SYNC_FETCH_AND_AND && TYPE_PRECISION (TREE_TYPE (@1)) > TYPE_PRECISION (TREE_TYPE (@0))) (with { combined_fn cfn = CFN_LAST; tree type0 = TREE_TYPE (@0); - if (TREE_CODE (type0) == BITINT_TYPE) + if (BITINT_TYPE_P (type0)) { if (TYPE_PRECISION (type0) > MAX_FIXED_MODE_SIZE) cfn = CFN_POPCOUNT; @@ -10494,7 +10494,7 @@ (define_operator_list SYNC_FETCH_AND_AND - TYPE_PRECISION (TREE_TYPE (@0))) & 1) == 0)) (with { combined_fn cfn = CFN_LAST; tree type0 = TREE_TYPE (@0); - if (TREE_CODE (type0) == BITINT_TYPE) + if (BITINT_TYPE_P (type0)) { if (TYPE_PRECISION (type0) > MAX_FIXED_MODE_SIZE) cfn = CFN_PARITY; @@ -10550,7 +10550,7 @@ (define_operator_list SYNC_FETCH_AND_AND (cond (ne @0 integer_zerop@1) (func (convert?@3 @0)) INTEGER_CST@2) (with { int val; internal_fn ifn = IFN_LAST; - if (TREE_CODE (TREE_TYPE (@3)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (@3))) { if (tree_fits_shwi_p (@2)) { @@ -10574,7 +10574,7 @@ (define_operator_list SYNC_FETCH_AND_AND (cond (ne @0 integer_zerop@1) (IFN_CLZ (convert?@3 @0) INTEGER_CST@2) @2) (with { int val; internal_fn ifn = IFN_LAST; - if (TREE_CODE (TREE_TYPE (@3)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (@3))) ifn = IFN_CLZ; else if (direct_internal_fn_supported_p (IFN_CLZ, TREE_TYPE (@3), OPTIMIZE_FOR_BOTH)) @@ -10589,7 +10589,7 @@ (define_operator_list SYNC_FETCH_AND_AND (cond (ne @0 integer_zerop@1) (func (convert?@3 @0)) INTEGER_CST@2) (with { int val; internal_fn ifn = IFN_LAST; - if (TREE_CODE (TREE_TYPE (@3)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (@3))) { if (tree_fits_shwi_p (@2)) { @@ -10613,7 +10613,7 @@ (define_operator_list SYNC_FETCH_AND_AND (cond (ne @0 integer_zerop@1) (IFN_CTZ (convert?@3 @0) INTEGER_CST@2) @2) (with { int val; internal_fn ifn = IFN_LAST; - if (TREE_CODE (TREE_TYPE (@3)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (@3))) ifn = IFN_CTZ; else if (direct_internal_fn_supported_p (IFN_CTZ, TREE_TYPE (@3), OPTIMIZE_FOR_BOTH)) @@ -10951,7 +10951,7 @@ (define_operator_list SYNC_FETCH_AND_AND && TYPE_PRECISION (TREE_TYPE (@1)) > TYPE_PRECISION (TREE_TYPE (@0))) (with { combined_fn cfn = CFN_LAST; tree type0 = TREE_TYPE (@0); - if (TREE_CODE (type0) == BITINT_TYPE) + if (BITINT_TYPE_P (type0)) { if (TYPE_PRECISION (type0) > MAX_FIXED_MODE_SIZE) cfn = CFN_FFS; --- gcc/builtins.cc.jj 2026-05-18 15:21:03.000000000 +0200 +++ gcc/builtins.cc 2026-05-26 09:19:41.128560612 +0200 @@ -10483,7 +10483,7 @@ fold_builtin_bit_query (location_t loc, /* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the value defined at zero during GIMPLE, or for large/huge _BitInt (which are then lowered during bitint lowering). */ - if (arg2 && TREE_CODE (TREE_TYPE (arg0)) != BITINT_TYPE) + if (arg2 && !BITINT_TYPE_P (TREE_TYPE (arg0))) { int val; if (fcode == BUILT_IN_CLZG) --- gcc/explow.cc.jj 2026-05-05 09:58:05.649433296 +0200 +++ gcc/explow.cc 2026-05-26 09:42:27.264306417 +0200 @@ -852,9 +852,8 @@ promote_function_mode (const_tree type, return mode; } - switch (TREE_CODE (type)) + if (BITINT_TYPE_P (type)) { - case BITINT_TYPE: if (TYPE_MODE (type) == BLKmode) return mode; @@ -865,10 +864,12 @@ promote_function_mode (const_tree type, if (!info.extended) return mode; - /* FALLTHRU */ + } + switch (TREE_CODE (type)) + { case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: - case POINTER_TYPE: case REFERENCE_TYPE: + case POINTER_TYPE: case REFERENCE_TYPE: case BITINT_TYPE: return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype, for_return); @@ -903,9 +904,8 @@ promote_mode (const_tree type ATTRIBUTE_ code = TREE_CODE (type); unsignedp = *punsignedp; - switch (code) + if (BITINT_TYPE_P (type)) { - case BITINT_TYPE: if (TYPE_MODE (type) == BLKmode) return mode; @@ -916,9 +916,12 @@ promote_mode (const_tree type ATTRIBUTE_ if (!info.extended) return mode; - /* FALLTHRU */ + } + switch (code) + { case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: + case BITINT_TYPE: /* Values of these types always have scalar mode. */ smode = as_a <scalar_mode> (mode); PROMOTE_MODE (smode, unsignedp, type); --- gcc/expr.cc.jj 2026-05-18 15:21:03.579030793 +0200 +++ gcc/expr.cc 2026-05-26 09:43:34.166216748 +0200 @@ -11397,7 +11397,7 @@ expand_expr_real_1 (tree exp, rtx target internally extend after arithmetic operations, we can avoid doing that when reading from SSA_NAMEs of vars. */ #define EXTEND_BITINT(expr) \ - ((TREE_CODE (type) == BITINT_TYPE \ + ((BITINT_TYPE_P (type) \ && !bitint_extended \ && reduce_bit_field \ && mode != BLKmode \ @@ -11410,7 +11410,7 @@ expand_expr_real_1 (tree exp, rtx target type = TREE_TYPE (exp); mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); - if (TREE_CODE (type) == BITINT_TYPE && bitint_extended == -1) + if (BITINT_TYPE_P (type) && bitint_extended == -1) { struct bitint_info info; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); @@ -11755,7 +11755,7 @@ expand_expr_real_1 (tree exp, rtx target case INTEGER_CST: { - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { unsigned int prec = TYPE_PRECISION (type); struct bitint_info info; --- gcc/fold-const-call.cc.jj 2026-05-16 10:50:50.312264525 +0200 +++ gcc/fold-const-call.cc 2026-05-26 09:44:30.042306668 +0200 @@ -1055,7 +1055,7 @@ fold_const_call_ss (wide_int *result, co int tmp; if (wi::ne_p (arg, 0)) tmp = wi::clz (arg); - else if (TREE_CODE (arg_type) == BITINT_TYPE) + else if (BITINT_TYPE_P (arg_type)) tmp = TYPE_PRECISION (arg_type); else if (!CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type), tmp)) @@ -1070,7 +1070,7 @@ fold_const_call_ss (wide_int *result, co int tmp; if (wi::ne_p (arg, 0)) tmp = wi::ctz (arg); - else if (TREE_CODE (arg_type) == BITINT_TYPE) + else if (BITINT_TYPE_P (arg_type)) tmp = TYPE_PRECISION (arg_type); else if (!CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (arg_type), tmp)) --- gcc/gimple-fold.cc.jj 2026-05-25 09:46:35.650977528 +0200 +++ gcc/gimple-fold.cc 2026-05-26 10:31:21.185647390 +0200 @@ -1485,7 +1485,7 @@ gimple_fold_builtin_memset (gimple_stmt_ if ((!INTEGRAL_TYPE_P (etype) && !POINTER_TYPE_P (etype)) - || TREE_CODE (etype) == BITINT_TYPE) + || BITINT_TYPE_P (etype)) return false; if (! var_decl_component_p (var)) @@ -4749,6 +4749,10 @@ clear_padding_type_may_have_padding_p (t return clear_padding_type_may_have_padding_p (TREE_TYPE (type)); case REAL_TYPE: return clear_padding_real_needs_padding_p (type); + case ENUMERAL_TYPE: + if (BITINT_TYPE_P (type)) + return clear_padding_bitint_needs_padding_p (type); + return false; case BITINT_TYPE: return clear_padding_bitint_needs_padding_p (type); default: @@ -4809,6 +4813,10 @@ type_has_padding_at_level_p (tree type) return false; case REAL_TYPE: return clear_padding_real_needs_padding_p (type); + case ENUMERAL_TYPE: + if (BITINT_TYPE_P (type)) + return clear_padding_bitint_needs_padding_p (type); + return false; case BITINT_TYPE: return clear_padding_bitint_needs_padding_p (type); default: @@ -5057,6 +5065,7 @@ clear_padding_type (clear_padding_struct buf->size += sz; break; case BITINT_TYPE: + do_bitint: { struct bitint_info info; bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (type), &info); @@ -5109,6 +5118,10 @@ clear_padding_type (clear_padding_struct } break; } + case ENUMERAL_TYPE: + if (BITINT_TYPE_P (type)) + goto do_bitint; + /* FALLTHRU */ default: gcc_assert ((size_t) sz <= clear_padding_unit); if ((unsigned HOST_WIDE_INT) sz + buf->size > clear_padding_buf_size) --- gcc/gimple-match-exports.cc.jj 2026-03-27 10:17:14.164330250 +0100 +++ gcc/gimple-match-exports.cc 2026-05-26 09:49:21.279563137 +0200 @@ -269,7 +269,7 @@ build_call_internal (internal_fn fn, gim /* For these 6 builtins large/huge _BitInt operand is ok before bitint lowering pass. */ if (res_op->num_ops >= 1 - && TREE_CODE (TREE_TYPE (res_op->ops[0])) == BITINT_TYPE + && BITINT_TYPE_P (TREE_TYPE (res_op->ops[0])) && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0])) > MAX_FIXED_MODE_SIZE) && cfun --- gcc/internal-fn.cc.jj 2026-05-18 15:21:03.580030776 +0200 +++ gcc/internal-fn.cc 2026-05-26 09:50:08.678791122 +0200 @@ -1131,7 +1131,7 @@ static void expand_ubsan_result_store (tree lhs, rtx target, scalar_int_mode mode, rtx res, rtx_code_label *do_error) { - if (TREE_CODE (TREE_TYPE (lhs)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (lhs)) && TYPE_PRECISION (TREE_TYPE (lhs)) < GET_MODE_PRECISION (mode)) { int uns = TYPE_UNSIGNED (TREE_TYPE (lhs)); --- gcc/tree-sra.cc.jj 2026-05-14 09:51:59.632624659 +0200 +++ gcc/tree-sra.cc 2026-05-26 09:53:06.026902562 +0200 @@ -968,8 +968,7 @@ create_access (tree expr, gimple *stmt, disqualify_candidate (base, "Encountered an access beyond the base."); return NULL; } - if (TREE_CODE (TREE_TYPE (expr)) == BITINT_TYPE - && size > WIDE_INT_MAX_PRECISION - 1) + if (BITINT_TYPE_P (TREE_TYPE (expr)) && size > WIDE_INT_MAX_PRECISION - 1) { disqualify_candidate (base, "Encountered too large _BitInt access."); return NULL; @@ -2951,7 +2950,7 @@ analyze_access_subtree (struct access *r tree rt = root->type; gcc_assert ((root->offset % BITS_PER_UNIT) == 0 && (root->size % BITS_PER_UNIT) == 0); - if (TREE_CODE (root->type) == BITINT_TYPE) + if (BITINT_TYPE_P (root->type)) root->type = build_bitint_type (root->size, TYPE_UNSIGNED (rt)); else root->type = build_nonstandard_integer_type (root->size, --- gcc/tree-ssa-phiopt.cc.jj 2026-05-25 09:46:35.656977431 +0200 +++ gcc/tree-ssa-phiopt.cc 2026-05-26 09:53:37.838384433 +0200 @@ -2594,7 +2594,7 @@ cond_removal_in_builtin_zero_pattern (ba if (INTEGRAL_TYPE_P (TREE_TYPE (arg))) { tree type = TREE_TYPE (arg); - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { if (gimple_call_num_args (call) == 1) { @@ -2624,7 +2624,7 @@ cond_removal_in_builtin_zero_pattern (ba if (INTEGRAL_TYPE_P (TREE_TYPE (arg))) { tree type = TREE_TYPE (arg); - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { if (gimple_call_num_args (call) == 1) { --- gcc/tree-ssa.cc.jj 2026-05-01 08:32:11.251216275 +0200 +++ gcc/tree-ssa.cc 2026-05-26 09:54:01.045006493 +0200 @@ -1811,7 +1811,7 @@ maybe_optimize_var (tree var, bitmap add fprintf (dump_file, "\n"); } } - else if (TREE_CODE (TREE_TYPE (var)) == BITINT_TYPE + else if (BITINT_TYPE_P (TREE_TYPE (var)) && (cfun->curr_properties & PROP_gimple_lbitint) != 0 && TYPE_PRECISION (TREE_TYPE (var)) > MAX_FIXED_MODE_SIZE) { --- gcc/tree-switch-conversion.cc.jj 2026-03-27 10:17:21.505210458 +0100 +++ gcc/tree-switch-conversion.cc 2026-05-26 09:54:40.509363891 +0200 @@ -894,7 +894,7 @@ switch_conversion::array_value_type (tre type = TYPE_MAIN_VARIANT (type); if (!INTEGRAL_TYPE_P (type) - || (TREE_CODE (type) == BITINT_TYPE + || (BITINT_TYPE_P (type) && (TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE || TYPE_MODE (type) == BLKmode))) return type; @@ -1086,7 +1086,7 @@ switch_conversion::build_arrays () utype = TREE_TYPE (m_index_expr); if (TREE_TYPE (utype)) utype = lang_hooks.types.type_for_mode (TYPE_MODE (TREE_TYPE (utype)), 1); - else if (TREE_CODE (utype) == BITINT_TYPE + else if (BITINT_TYPE_P (utype) && (TYPE_PRECISION (utype) > MAX_FIXED_MODE_SIZE || TYPE_MODE (utype) == BLKmode)) utype = unsigned_type_for (utype); @@ -1548,7 +1548,7 @@ jump_table_cluster::emit (tree index_exp /* For large/huge _BitInt, subtract low from index_expr, cast to unsigned DImode type (get_range doesn't support ranges larger than 64-bits) and subtract low from all case values as well. */ - if (TREE_CODE (TREE_TYPE (index_expr)) == BITINT_TYPE + if (BITINT_TYPE_P (TREE_TYPE (index_expr)) && TYPE_PRECISION (TREE_TYPE (index_expr)) > GET_MODE_PRECISION (DImode)) { bitint = true; --- gcc/ubsan.cc.jj 2026-03-27 10:17:21.519210229 +0100 +++ gcc/ubsan.cc 2026-05-26 09:57:23.522709528 +0200 @@ -127,7 +127,7 @@ tree ubsan_encode_value (tree t, enum ubsan_encode_value_phase phase) { tree type = TREE_TYPE (t); - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { if (TYPE_PRECISION (type) <= POINTER_SIZE) { @@ -374,8 +374,7 @@ ubsan_type_descriptor (tree type, enum u { /* Temporary hack for -fsanitize=shift with _BitInt(129) and more. libubsan crashes if it is not TK_Integer type. */ - if (TREE_CODE (type) == BITINT_TYPE - && TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE) + if (BITINT_TYPE_P (type) && TYPE_PRECISION (type) > MAX_FIXED_MODE_SIZE) type3 = build_qualified_type (type, TYPE_QUAL_CONST); if (type3 == type) pstyle = UBSAN_PRINT_NORMAL; @@ -432,7 +431,7 @@ ubsan_type_descriptor (tree type, enum u if (tname == NULL) { - if (TREE_CODE (type2) == BITINT_TYPE) + if (BITINT_TYPE_P (type2)) { snprintf (tname_bitint, sizeof (tname_bitint), "%s_BitInt(%d)", TYPE_UNSIGNED (type2) ? "unsigned " : "", @@ -506,10 +505,16 @@ ubsan_type_descriptor (tree type, enum u switch (TREE_CODE (eltype)) { case BOOLEAN_TYPE: - case ENUMERAL_TYPE: case INTEGER_TYPE: tkind = 0x0000; break; + case ENUMERAL_TYPE: + if (!BITINT_TYPE_P (eltype)) + { + tkind = 0x0000; + break; + } + /* FALLTHRU */ case BITINT_TYPE: if (TYPE_PRECISION (eltype) <= MAX_FIXED_MODE_SIZE) tkind = 0x0000; @@ -1667,7 +1672,7 @@ instrument_si_overflow (gimple_stmt_iter Also punt on bit-fields. */ if (!INTEGRAL_TYPE_P (lhsinner) || TYPE_OVERFLOW_WRAPS (lhsinner) - || (TREE_CODE (lhsinner) != BITINT_TYPE + || (!BITINT_TYPE_P (lhsinner) && maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (lhsinner)), TYPE_PRECISION (lhsinner)))) return; --- gcc/varasm.cc.jj 2026-03-27 10:17:21.523210164 +0100 +++ gcc/varasm.cc 2026-05-26 09:58:54.606226409 +0200 @@ -5530,9 +5530,12 @@ output_constant (tree exp, unsigned HOST Otherwise, break and ensure SIZE is the size written. */ switch (code) { + case ENUMERAL_TYPE: + if (BITINT_TYPE_P (TREE_TYPE (exp))) + goto do_bitint; + /* FALLTHRU */ case BOOLEAN_TYPE: case INTEGER_TYPE: - case ENUMERAL_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: @@ -5564,6 +5567,7 @@ output_constant (tree exp, unsigned HOST break; case BITINT_TYPE: + do_bitint: if (TREE_CODE (exp) != INTEGER_CST) error ("initializer for %<_BitInt(%d)%> value is not an integer " "constant", TYPE_PRECISION (TREE_TYPE (exp))); --- gcc/config/aarch64/aarch64.cc.jj 2026-05-22 10:14:59.567091379 +0200 +++ gcc/config/aarch64/aarch64.cc 2026-05-26 09:15:01.812112822 +0200 @@ -7399,7 +7399,7 @@ aarch64_return_in_memory_1 (const_tree t int count; if (!AGGREGATE_TYPE_P (type) - && TREE_CODE (type) != BITINT_TYPE + && !BITINT_TYPE_P (type) && TREE_CODE (type) != COMPLEX_TYPE && TREE_CODE (type) != VECTOR_TYPE) /* Simple scalar types always returned in registers. */ @@ -7573,7 +7573,7 @@ bitint_or_aggr_of_bitint_p (tree type) if (!type) return false; - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) return true; /* If ARRAY_TYPE, check it's element type. */ @@ -23480,7 +23480,7 @@ aarch64_composite_type_p (const_tree typ return true; if (type - && TREE_CODE (type) == BITINT_TYPE + && BITINT_TYPE_P (type) && int_size_in_bytes (type) > 16) return true; --- gcc/config/arm/arm.cc.jj 2026-04-15 17:20:57.266889450 +0200 +++ gcc/config/arm/arm.cc 2026-05-26 09:15:51.123309137 +0200 @@ -6134,7 +6134,7 @@ arm_return_in_memory (const_tree type, c some of the detail. */ if (!AGGREGATE_TYPE_P (type) /* A _BitInt(N) for N <= 64 is a simple, non-aggregate type. */ - && !(TREE_CODE (type) == BITINT_TYPE && size > 8) + && !(BITINT_TYPE_P (type) && size > 8) && TREE_CODE (type) != VECTOR_TYPE && TREE_CODE (type) != COMPLEX_TYPE) return false; @@ -6166,7 +6166,7 @@ arm_return_in_memory (const_tree type, c if (!AGGREGATE_TYPE_P (type) /* A _BitInt(N) for N <= 64 is a simple, non-aggregate type. */ - && !(TREE_CODE (type) == BITINT_TYPE && size > 8) + && !(BITINT_TYPE_P (type) && size > 8) && (TREE_CODE (type) != VECTOR_TYPE)) /* All simple types are returned in registers. */ return false; @@ -7227,7 +7227,7 @@ arm_needs_doubleword_align (machine_mode return GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY; /* For any _BitInt(N) where N > 32 the ABI demands double word alignment. */ - if (TREE_CODE (type) == BITINT_TYPE) + if (BITINT_TYPE_P (type)) { if (int_size_in_bytes (type) > 4) return 1; --- gcc/config/i386/i386.cc.jj 2026-05-14 09:51:59.560625898 +0200 +++ gcc/config/i386/i386.cc 2026-05-26 09:17:14.491950385 +0200 @@ -2272,7 +2272,7 @@ classify_argument (machine_mode mode, co } if (type && (AGGREGATE_TYPE_P (type) - || (TREE_CODE (type) == BITINT_TYPE && words > 1))) + || (BITINT_TYPE_P (type) && words > 1))) { int i; tree field; @@ -2422,6 +2422,7 @@ classify_argument (machine_mode mode, co break; case BITINT_TYPE: + case ENUMERAL_TYPE: /* _BitInt(N) for N > 64 is passed as structure containing (N + 63) / 64 64-bit elements. */ if (words > 2) --- gcc/config/loongarch/loongarch.h.jj 2026-05-06 17:43:14.665261714 +0200 +++ gcc/config/loongarch/loongarch.h 2026-05-26 09:17:39.710539369 +0200 @@ -271,7 +271,7 @@ along with GCC; see the file COPYING3. && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ { \ if ((MODE) == SImode \ - && !(TYPE && TREE_CODE (TYPE) == BITINT_TYPE \ + && !(TYPE && BITINT_TYPE_P (TYPE) \ && TYPE_PRECISION (TYPE) < 32)) \ (UNSIGNEDP) = 0; \ (MODE) = Pmode; \ --- gcc/c-family/c-attribs.cc.jj 2026-03-27 10:17:13.711337642 +0100 +++ gcc/c-family/c-attribs.cc 2026-05-25 16:36:35.280927341 +0200 @@ -4885,7 +4885,7 @@ type_valid_for_vector_size (tree type, t || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)) || TREE_CODE (type) == BOOLEAN_TYPE || hardbool_p - || TREE_CODE (type) == BITINT_TYPE) + || BITINT_TYPE_P (type)) { if (error_p) error ("invalid vector type for attribute %qE", atname); --- gcc/c-family/c-common.cc.jj 2026-05-14 09:51:59.541626225 +0200 +++ gcc/c-family/c-common.cc 2026-05-26 10:44:39.147709479 +0200 @@ -1380,6 +1380,9 @@ c_common_get_narrower (tree op, int *uns if (TREE_CODE (TREE_TYPE (op)) == ENUMERAL_TYPE && ENUM_IS_SCOPED (TREE_TYPE (op))) { + if (BITINT_TYPE_P (TREE_TYPE (op))) + return fold_convert (ENUM_UNDERLYING_TYPE (TREE_TYPE (op)), op); + /* C++0x scoped enumerations don't implicitly convert to integral type; if we stripped an explicit conversion to a larger type we need to replace it so common_type will still work. */ @@ -2818,7 +2821,7 @@ c_common_signed_or_unsigned_type (int un || TYPE_UNSIGNED (type) == unsignedp) return type; - if (TREE_CODE (type) == BITINT_TYPE + if (BITINT_TYPE_P (type) /* signed _BitInt(1) is invalid before C2Y, avoid creating that. */ && (unsignedp || flag_isoc2y || TYPE_PRECISION (type) > 1)) return build_bitint_type (TYPE_PRECISION (type), unsignedp); @@ -7747,7 +7750,7 @@ sync_resolve_size (tree function, vec<tr size = tree_to_uhwi (TYPE_SIZE_UNIT (type)); if (size == 16 - && TREE_CODE (type) == BITINT_TYPE + && BITINT_TYPE_P (type) && !targetm.scalar_mode_supported_p (TImode)) { if (fetch && !orig_format) @@ -7758,7 +7761,7 @@ sync_resolve_size (tree function, vec<tr if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16) return size; - if (fetch && !orig_format && TREE_CODE (type) == BITINT_TYPE) + if (fetch && !orig_format && BITINT_TYPE_P (type)) return -1; incompatible: @@ -8486,7 +8489,7 @@ atomic_bitint_fetch_using_cas_loop (loca tree nonatomic_lhs_type = TREE_TYPE (TREE_TYPE ((*orig_params)[0])); nonatomic_lhs_type = TYPE_MAIN_VARIANT (nonatomic_lhs_type); - gcc_assert (TREE_CODE (nonatomic_lhs_type) == BITINT_TYPE); + gcc_assert (BITINT_TYPE_P (nonatomic_lhs_type)); tree lhs_addr = (*orig_params)[0]; tree val = convert (nonatomic_lhs_type, (*orig_params)[1]); @@ -8879,7 +8882,7 @@ resolve_overloaded_builtin (location_t l if (new_return) { /* Cast function result from I{1,2,4,8,16} to the required type. */ - if (TREE_CODE (TREE_TYPE (new_return)) == BITINT_TYPE) + if (BITINT_TYPE_P (TREE_TYPE (new_return))) { struct bitint_info info; unsigned prec = TYPE_PRECISION (TREE_TYPE (new_return)); --- gcc/c/c-parser.cc.jj 2026-05-25 09:46:35.637977739 +0200 +++ gcc/c/c-parser.cc 2026-05-25 14:35:44.639940630 +0200 @@ -4182,7 +4182,8 @@ c_parser_enum_specifier (c_parser *parse if (specs->default_int_p) error_at (enum_loc, "no %<enum%> underlying type specified"); else if (TREE_CODE (specs->type) != INTEGER_TYPE - && TREE_CODE (specs->type) != BOOLEAN_TYPE) + && TREE_CODE (specs->type) != BOOLEAN_TYPE + && (!flag_isoc2y || TREE_CODE (specs->type) != BITINT_TYPE)) { error_at (enum_loc, "invalid %<enum%> underlying type"); specs->type = integer_type_node; --- gcc/c/c-lang.cc.jj 2026-03-27 10:17:13.727337381 +0100 +++ gcc/c/c-lang.cc 2026-05-25 17:38:15.563269487 +0200 @@ -39,6 +39,8 @@ enum c_language_kind c_language = clk_c; #define LANG_HOOKS_INIT c_objc_common_init #undef LANG_HOOKS_INIT_TS #define LANG_HOOKS_INIT_TS c_common_init_ts +#undef LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE +#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE c_enum_underlying_base_type #if CHECKING_P #undef LANG_HOOKS_RUN_LANG_SELFTESTS --- gcc/c/c-tree.h.jj 2026-05-15 08:39:43.999949487 +0200 +++ gcc/c/c-tree.h 2026-05-25 17:47:35.700324745 +0200 @@ -786,6 +786,7 @@ extern void c_initialize_diagnostics (di extern bool c_var_mod_p (tree x, tree fn); extern alias_set_type c_get_alias_set (tree); extern int c_type_dwarf_attribute (const_tree, int); +extern tree c_enum_underlying_base_type (const_tree); /* in c-typeck.cc */ extern int in_alignof; --- gcc/c/c-objc-common.cc.jj 2026-03-27 10:17:13.727337381 +0100 +++ gcc/c/c-objc-common.cc 2026-05-25 17:47:58.688956015 +0200 @@ -487,3 +487,18 @@ c_type_dwarf_attribute (const_tree type, return -1; } + +/* The C version of the enum_underlying_base_type langhook. */ + +tree +c_enum_underlying_base_type (const_tree type) +{ + tree underlying_type = ENUM_UNDERLYING_TYPE (type); + + if (! ENUM_FIXED_UNDERLYING_TYPE_P (type)) + underlying_type + = c_common_type_for_mode (TYPE_MODE (underlying_type), + TYPE_UNSIGNED (underlying_type)); + + return underlying_type; +} --- gcc/c/c-decl.cc.jj 2026-05-06 17:43:14.662261763 +0200 +++ gcc/c/c-decl.cc 2026-05-26 10:47:46.334677853 +0200 @@ -9847,8 +9847,8 @@ finish_struct (location_t loc, tree t, t } if (width != TYPE_PRECISION (type)) { - if (TREE_CODE (type) == BITINT_TYPE - && width >= (TYPE_UNSIGNED (type) ? 1 : 2)) + if (BITINT_TYPE_P (type) + && width >= ((TYPE_UNSIGNED (type) || flag_isoc2y) ? 1 : 2)) TREE_TYPE (field) = build_bitint_type (width, TYPE_UNSIGNED (type)); else --- gcc/testsuite/gcc.dg/bitint-133.c.jj 2026-05-26 09:12:14.519839382 +0200 +++ gcc/testsuite/gcc.dg/bitint-133.c 2026-05-26 09:12:05.951979020 +0200 @@ -0,0 +1,41 @@ +/* C2Y N3705: bit-precise enum. */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c2y" } */ + +#if __BITINT_MAXWIDTH__ >= 129 +enum A : unsigned _BitInt(3) { A0 = 0, A1 = 7 }; +enum B : unsigned _BitInt(67) { B0 = 0, B1 = 255 }; +enum C : _BitInt(4) { C0 = -8, C1 = 7 }; +enum D : signed _BitInt(129) { D0 = -61822874253726891040447382843909510144wb, D1 = 333265406300494622897688995893630121068wb }; +enum E : _BitInt(__BITINT_MAXWIDTH__) { E0 = -1, E1 = 1 }; +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 129 + int i = 0; + enum A a = A0; + _Generic (a, enum A: ++i); + _Generic (+a, unsigned _BitInt(3): ++i); + _Generic (a + a, unsigned _BitInt(3): ++i); + enum B b = B0; + _Generic (b, enum B: ++i); + _Generic (+b, unsigned _BitInt(67): ++i); + _Generic (b + b, unsigned _BitInt(67): ++i); + enum C c = C0; + _Generic (c, enum C: ++i); + _Generic (+c, _BitInt(4): ++i); + _Generic (c + c, _BitInt(4): ++i); + enum D d = D0; + _Generic (d, enum D: ++i); + _Generic (+d, signed _BitInt(129): ++i); + _Generic (d + d, signed _BitInt(129): ++i); + enum E e = E0; + _Generic (e, enum E: ++i); + _Generic (+e, signed _BitInt(__BITINT_MAXWIDTH__): ++i); + _Generic (e + e, signed _BitInt(__BITINT_MAXWIDTH__): ++i); + if (i != 15) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/bitint-134.c.jj 2026-05-26 10:23:55.739875260 +0200 +++ gcc/testsuite/gcc.dg/bitint-134.c 2026-05-26 10:24:20.876468958 +0200 @@ -0,0 +1,42 @@ +/* C2Y N3705: bit-precise enum. */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c2y -Wall" } */ + +enum E : unsigned _BitInt(1) { E1 = 0, E2 = 1 }; +#if __BITINT_MAXWITH__ >= 977 +enum F : _BitInt(976) { F1 = 1wb, F2 = 300670311812537087458442068171242480163042891902139164259644606340061247186864125993521170465570759574674133007538491713720385607199458367860097993945704706551423706008678936855195978990583102392208311054636025123775462104768336555710742464822135886690195218326330916446029087852132145116425130wb, F3 = ~(unsigned _BitInt(975)) 0 }; +#endif + +int +foo (enum E x) +{ + switch (x) + { + case E1: + return 1; + case E2: + return 2; + } +} + +#if __BITINT_MAXWITH__ >= 977 +_BitInt(977) +bar (enum F x) +{ + return x + 1; +} + +enum F +baz (enum F x) +{ + switch (x) + { + case F1: + return F2; + case F2: + return F3; + default: + return F1; + } +} +#endif --- gcc/testsuite/gcc.dg/bitint-135.c.jj 2026-05-26 10:25:23.294460055 +0200 +++ gcc/testsuite/gcc.dg/bitint-135.c 2026-05-26 10:30:15.429713536 +0200 @@ -0,0 +1,47 @@ +/* C2Y N3705: bit-precise enum. */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c2y" } */ + +#if __BITINT_MAXWIDTH__ >= 257 +enum A : unsigned _BitInt(7) { A0 = 0, A1 = 7 }; +enum B : unsigned _BitInt(79) { B0 = 0, B1 = 255 }; +enum C : _BitInt(25) { C0 = -8, C1 = 7 }; +enum D : signed _BitInt(182) { D0 = -61822874253726891040447382843909510144wb, D1 = 333265406300494622897688995893630121068wb }; +enum E : _BitInt(__BITINT_MAXWIDTH__) { E0 = -1, E1 = 1 }; +struct F { enum A a : 3; enum B b : 67; enum C c : 4; enum D d : 129; enum E e : 257; } f; +#endif + +[[gnu::noipa]] void +foo () +{ + if (f.a != A1 + || f.b != B1 + || f.c != C1 + || f.d != D1 + || f.e != E1) + __builtin_abort (); + f.a = A0; + f.b = B0; + f.c = C0; + f.d = D0; + f.e = E0; +} + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 257 + f.a = A1; + f.b = B1; + f.c = C1; + f.d = D1; + f.e = E1; + foo (); + if (f.a != A0 + || f.b != B0 + || f.c != C0 + || f.d != D0 + || f.e != E0) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/torture/bitint-99.c.jj 2026-05-26 10:55:30.236168312 +0200 +++ gcc/testsuite/gcc.dg/torture/bitint-99.c 2026-05-26 11:06:17.076902340 +0200 @@ -0,0 +1,58 @@ +/* C2Y N3705: bit-precise enum. */ +/* { dg-do compile { target bitint } } */ +/* { dg-options "-std=c2y -pedantic-errors" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#if __BITINT_MAXWIDTH__ >= 931 +enum A : unsigned _BitInt(931) { A0 = 0, A1 = ~(unsigned _BitInt(931)) 0 }; + +[[gnu::noipa]] enum A +foo (enum A x, enum A y) +{ + return x + y; +} + +[[gnu::noipa]] enum A +bar (enum A x, enum A y) +{ + return x * y; +} + +[[gnu::noipa]] enum A +baz (enum A x, int y) +{ + return x << y; +} + +[[gnu::noipa]] long double +qux (enum A x) +{ + return x; +} +#endif + +int +main () +{ + if (foo (6311375123928035423950285815103134911823756068469611777446526212940235067784850613353497329740063593697085797242982576864482320954041469603405692898785705968909387515267461870959824498259469495351851027191417268686507795153960941899524534819776605247652440362840005231043955863251uwb, + 14387261967519759057764126008098292183127782109485750598911399497161011642298676488973745200653245797159693794534840726810049655774169609382090435748786710789342570033603954826553305901144008614628394445814741866666472834301004639140374682209505172315237277433772283979289285215192uwb) + != ((unsigned _BitInt(931)) 6311375123928035423950285815103134911823756068469611777446526212940235067784850613353497329740063593697085797242982576864482320954041469603405692898785705968909387515267461870959824498259469495351851027191417268686507795153960941899524534819776605247652440362840005231043955863251uwb + + 14387261967519759057764126008098292183127782109485750598911399497161011642298676488973745200653245797159693794534840726810049655774169609382090435748786710789342570033603954826553305901144008614628394445814741866666472834301004639140374682209505172315237277433772283979289285215192uwb) + || foo (42, 43) != 85 + || bar (11450886075967129033052256159825006993789547814645317054307262295553183531582194402180689046449356587523973694466833975060817054401287265586817097051188432556072249366122506436985624261677676836219438960612585780057976181675859636764878183805546490277128899407974903051218414039906uwb, + 17319821836005877733927644950742811128616796074756636477991226488210814096671627534609545922744022960185648230703380956243036682725031141936390527207521613841001950058662947028886894999944938393683770058909115780447269611178311112868417694704349733151327800871414934360178286516220uwb) + != ((unsigned _BitInt(931)) 11450886075967129033052256159825006993789547814645317054307262295553183531582194402180689046449356587523973694466833975060817054401287265586817097051188432556072249366122506436985624261677676836219438960612585780057976181675859636764878183805546490277128899407974903051218414039906uwb + * 17319821836005877733927644950742811128616796074756636477991226488210814096671627534609545922744022960185648230703380956243036682725031141936390527207521613841001950058662947028886894999944938393683770058909115780447269611178311112868417694704349733151327800871414934360178286516220uwb) + || bar (42, 43) != (42 * 43) + || baz (1741243423058845609493717319573689670252835849747079409452709857940702982389080261485458577486556787796580475119344401810353389865747399915963686220476226766063058821552766983213692892185191052405922570241479839142610515539669844621168541758908874036250322040751021964408140728317uwb, + 278) + != ((unsigned _BitInt(931)) 1741243423058845609493717319573689670252835849747079409452709857940702982389080261485458577486556787796580475119344401810353389865747399915963686220476226766063058821552766983213692892185191052405922570241479839142610515539669844621168541758908874036250322040751021964408140728317uwb + << 278) +#if __LDBL_MAX_19_EXP__ >= 240 + || qux (1072109040180989940290225035254632830964130184664319348440549688998788uwb) + != (long double) 1072109040180989940290225035254632830964130184664319348440549688998788uwb +#endif + || false) + __builtin_abort (); +} Jakub
