Hi! Here is a new version of the core P3666R5 patch, like previously on top of https://gcc.gnu.org/pipermail/gcc-patches/2026-November/738467.html
Changes since the v2 version of the patch: 1) the module.cc ICE is resolved by not using finish_bitint there, instead building build_bitint or make_node (BITINT_TYPE) by hand 2) c_common_signed_or_unsigned_type and c_common_get_alias_set are fixed to support _BitInt(1) even for C++, previously it was just C2Y 3) tmpl<_BitInt(a > b ? 1 : 2)> is now handled correctly (> here is nested, so shouldn't be treated as template argument terminator) 4) similarly to C FE, when creating ARRAY_REFs with BITINT_TYPE index which has larger precision than sizetype, cast of the index to sizetype is added, because the middle-end is unprepared to handle ARRAY_REFs with large/huge _BitInt 5) 2 new testcases added 2026-11-13 Jakub Jelinek <[email protected]> P3666R5 gcc/c-family/ * c-lex.cc (interpret_integer): Handle 0wb as _BitInt(1) 0 for C++. * c-common.cc (c_common_reswords): Change C_ONLY to 0 for _BitInt. (c_common_signed_or_unsigned_type): Handle signed _BitInt(1) even for C++. (c_common_get_alias_set): Likewise. * c-cppbuiltin.cc (c_cpp_builtins): Predefine __BITINT_MAXWIDTH__ also for C++ when supported. For C++29 also predefine __cpp_bit_int in that case as well. gcc/cp/ * parser.cc: Implement P3666R5 - Bit-precise integers. (cp_keyword_starts_decl_specifier_p): Handle RID_BITINT. (cp_parser_simple_type_specifier): Likewise. (set_and_check_decl_spec_loc): Add "_BitInt" name. * cp-tree.h (CP_INTEGRAL_CODE_P): Define. (CP_INTEGRAL_TYPE_P): Use CP_INTEGRAL_CODE_P. (INTEGRAL_CODE_P): Likewise. (INTEGRAL_OR_ENUMERATION_TYPE_P): Use INTEGRAL_CODE_P. (BITINT_PREC): Define. (enum cp_decl_spec): Add ds_bitint. (finish_bitint): Declare. * typeck.cc (cp_common_type): Emit sorry when trying to create common type for _Complex and _BitInt. Handle the case where at least one type is bit-precise and they have the same precision. (structural_comptypes): Handle BITINT_TYPE. (cp_perform_integral_promotions): Likewise. (cp_build_array_ref): Use CP_INTEGRAL_TYPE_P macro. If idx has BITINT_TYPE wider than sizetype, cast idx to sizetype. (cp_build_binary_op): Use CP_INTEGRAL_CODE_P or INTEGRAL_CODE_P macros where possible. Handle BITINT_TYPE. (cp_build_c_cast): Handle BITINT_TYPE. (ptr_reasonably_similar): Likewise. (finish_bitint): New function. * decl.cc (reshape_init_array_1): Handle BITINT_TYPE. (grokdeclarator): Likewise. * pt.cc (find_parameter_packs_r): Likewise. (tsubst): Likewise. (uses_deducible_template_parms): Likewise. (array_deduction_r): Likewise. (unify): Likewise. (dependent_type_p_r): Likewise. * error.cc (dump_type): Likewise. (dump_type_prefix): Likewise. (dump_type_suffix): Likewise. (dump_expr): Likewise. * cxx-pretty-print.cc: Likewise. * tree.cc: Include target.h. (type_has_unique_obj_representations): Handle BITINT_TYPE. (cp_walk_subtrees): Likewise. * semantics.cc (finish_make_signed): Handle ENUMERAL_TYPE with BITINT_TYPE as underlying type. (handle_omp_for_class_iterator): Handle BITINT_TYPE. * call.cc (null_ptr_cst_p): Likewise. (build_list_conv): Likewise. (standard_conversion): Likewise. (build_conditional_expr): Likewise. (convert_like_internal): Likewise. (joust): Likewise. * constexpr.cc (cxx_eval_bit_field_ref): Likewise. (cxx_eval_outermost_constant_expr): Likewise. * cvt.cc (build_expr_type_conversion): Likewise. * init.cc (build_vec_init): Likewise. * mangle.cc (write_type): Likewise. (write_builtin_type): Likewise. * class.cc (layout_class_type): Likewise. * module.cc (trees_out::type_node, trees_in::tree_node): Likewise. gcc/testsuite/ * g++.dg/ext/bitint1.C: Remove. * g++.dg/ext/bitint2.C: Remove. * g++.dg/ext/bitint3.C: Remove. * g++.dg/ext/bitint4.C: Remove. * g++.dg/cpp29/bitint1.C: New test. * g++.dg/cpp29/bitint2.C: New test. * g++.dg/cpp29/bitint3.C: New test. * g++.dg/cpp29/bitint4.C: New test. * g++.dg/cpp29/bitint5.C: New test. * g++.dg/cpp29/bitint6.C: New test. * g++.dg/cpp29/bitint7.C: New test. * g++.dg/cpp29/bitint8.C: New test. * g++.dg/cpp29/bitint9.C: New test. * g++.dg/cpp29/bitint10.C: New test. * g++.dg/cpp29/bitint11.C: New test. * g++.dg/cpp29/bitint12.C: New test. * g++.dg/cpp29/bitint13.C: New test. * g++.dg/cpp29/bitint14.C: New test. * g++.dg/cpp29/bitint15.C: New test. * g++.dg/cpp29/bitint16.C: New test. * g++.dg/cpp29/bitint17.C: New test. * g++.dg/cpp29/bitint18.C: New test. * g++.dg/cpp29/bitint19.C: New test. * g++.dg/cpp29/bitint20.C: New test. * g++.dg/cpp29/bitint21.C: New test. * g++.dg/cpp29/bitint22.C: New test. * g++.dg/cpp29/bitint23.C: New test. * g++.dg/cpp29/bitint24.C: New test. * g++.dg/cpp29/bitint25.C: New test. * g++.dg/cpp29/bitint26.C: New test. * g++.dg/cpp29/bitint27.C: New test. * g++.dg/cpp29/bitint28.C: New test. * g++.dg/cpp29/bitint29.C: New test. * g++.dg/cpp29/bitint30.C: New test. * c-c++-common/builtin-bswapg-1.c: Use -Wno-c++29-extensions for c++26_down targets. * c-c++-common/builtin-bswapg-3.c: Likewise. * c-c++-common/builtin-bitreverseg-1.c: Likewise. * lib/target-supports.exp (check_effective_target_bitint, check_effective_target_bitint128, check_effective_target_bitint575, check_effective_target_bitint65535): For C++ use -std=c++29 rather than -std=c23. libcpp/ * expr.cc (interpret_int_suffix): Don't return 0 for wb for C++. (cpp_classify_number): Emit a pedwarn for C++ < 29 uses of wb. --- a/gcc/c-family/c-lex.cc 2026-11-06 18:32:41.031466379 +0100 +++ b/gcc/c-family/c-lex.cc 2026-11-11 13:16:41.775559360 +0100 @@ -1094,7 +1094,8 @@ interpret_integer (const cpp_token *toke } prec = wi::min_precision (wval, UNSIGNED); - if (prec == 0 && ((flags & CPP_N_UNSIGNED) != 0 || !flag_isoc2y)) + if (prec == 0 && ((flags & CPP_N_UNSIGNED) != 0 + || (!flag_isoc2y && !c_dialect_cxx ()))) prec = 1; if ((flags & CPP_N_UNSIGNED) == 0) ++prec; --- a/gcc/c-family/c-common.cc 2026-11-11 10:28:33.708007102 +0100 +++ b/gcc/c-family/c-common.cc 2026-11-13 11:30:31.606685086 +0100 @@ -400,7 +400,7 @@ const struct c_common_resword c_common_r { "_Maxof", RID_MAXOF, D_CONLY }, { "_Minof", RID_MINOF, D_CONLY }, { "_Atomic", RID_ATOMIC, D_CONLY }, - { "_BitInt", RID_BITINT, D_CONLY }, + { "_BitInt", RID_BITINT, 0 }, { "_Bool", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, @@ -2827,7 +2827,10 @@ c_common_signed_or_unsigned_type (int un if (BITINT_TYPE_P (type) /* signed _BitInt(1) is invalid before C2Y, avoid creating that. */ - && (unsignedp || flag_isoc2y || TYPE_PRECISION (type) > 1)) + && (unsignedp + || TYPE_PRECISION (type) > 1 + || flag_isoc2y + || c_dialect_cxx ())) return build_bitint_type (TYPE_PRECISION (type), unsignedp); #define TYPE_OK(node) \ @@ -3960,8 +3963,9 @@ c_common_get_alias_set (tree t) { /* There is no signed _BitInt(1) before C2Y. */ if (TREE_CODE (t) == BITINT_TYPE + && TYPE_PRECISION (t) == 1 && !flag_isoc2y - && TYPE_PRECISION (t) == 1) + && !c_dialect_cxx ()) return -1; tree t1 = c_common_signed_type (t); gcc_checking_assert (t != t1); --- a/gcc/c-family/c-cppbuiltin.cc 2026-11-11 10:28:24.302131195 +0100 +++ b/gcc/c-family/c-cppbuiltin.cc 2026-11-11 13:16:41.809558912 +0100 @@ -1261,28 +1261,28 @@ c_cpp_builtins (cpp_reader *pfile) builtin_define_type_width ("__PTRDIFF_WIDTH__", ptrdiff_type_node, NULL_TREE); builtin_define_type_width ("__SIZE_WIDTH__", size_type_node, NULL_TREE); - if (!c_dialect_cxx ()) + struct bitint_info info; + /* For now, restrict __BITINT_MAXWIDTH__ to what can be represented in + wide_int and widest_int. */ + if (targetm.c.bitint_type_info (WIDE_INT_MAX_PRECISION - 1, &info)) { - struct bitint_info info; - /* For now, restrict __BITINT_MAXWIDTH__ to what can be represented in - wide_int and widest_int. */ - if (targetm.c.bitint_type_info (WIDE_INT_MAX_PRECISION - 1, &info)) + cpp_define_formatted (pfile, "__BITINT_MAXWIDTH__=%d", + (int) WIDE_INT_MAX_PRECISION - 1); + if (c_dialect_cxx () && cxx_dialect >= cxx29) + cpp_define_warn (pfile, "__cpp_bit_int=202611L"); + if (flag_building_libgcc) { - cpp_define_formatted (pfile, "__BITINT_MAXWIDTH__=%d", - (int) WIDE_INT_MAX_PRECISION - 1); - if (flag_building_libgcc) - { - scalar_int_mode limb_mode - = as_a <scalar_int_mode> (info.limb_mode); - cpp_define_formatted (pfile, "__LIBGCC_BITINT_LIMB_WIDTH__=%d", - (int) GET_MODE_PRECISION (limb_mode)); - cpp_define_formatted (pfile, "__LIBGCC_BITINT_ORDER__=%s", - info.big_endian - ? "__ORDER_BIG_ENDIAN__" - : "__ORDER_LITTLE_ENDIAN__"); - } + scalar_int_mode limb_mode = as_a <scalar_int_mode> (info.limb_mode); + cpp_define_formatted (pfile, "__LIBGCC_BITINT_LIMB_WIDTH__=%d", + (int) GET_MODE_PRECISION (limb_mode)); + cpp_define_formatted (pfile, "__LIBGCC_BITINT_ORDER__=%s", + info.big_endian + ? "__ORDER_BIG_ENDIAN__" + : "__ORDER_LITTLE_ENDIAN__"); } } + else if (c_dialect_cxx () && cxx_dialect >= cxx29) + cpp_warn (pfile, "__cpp_bit_int"); if (c_dialect_cxx ()) for (i = 0; i < NUM_INT_N_ENTS; i ++) --- a/gcc/cp/parser.cc 2026-11-11 10:28:33.756006469 +0100 +++ b/gcc/cp/parser.cc 2026-11-12 20:11:13.165527461 +0100 @@ -1340,6 +1340,7 @@ cp_keyword_starts_decl_specifier_p (enum case RID_DOUBLE: CASE_RID_FLOATN_NX: case RID_VOID: + case RID_BITINT: /* CV qualifiers. */ case RID_CONST: case RID_VOLATILE: @@ -22704,6 +22705,14 @@ cp_parser_type_specifier (cp_parser* par nested-name-specifier(opt) template-name + C++29 extension: + + simple-type-specifier: + bit-precise-int-type-specifier + + bit-precise-int-type-specifier: + _BitInt ( constant-expression ) + computed-type-specifier: decltype-specifier pack-index-specifier @@ -22822,6 +22831,38 @@ cp_parser_simple_type_specifier (cp_pars case RID_VOID: type = void_type_node; break; + case RID_BITINT: + { + location_t loc = token->location; + if (cxx_dialect < cxx29 && pedantic) + pedwarn (loc, OPT_Wc__29_extensions, + "%<_BitInt%> only available with " + "%<-std=c++2d%> or %<-std=gnu++2d%>"); + /* Consume the `_BitInt' token. */ + cp_lexer_consume_token (parser->lexer); + matching_parens parens; + if (!parens.require_open (parser)) + return error_mark_node; + auto gr = make_temp_override (parser->greater_than_is_operator_p, + true); + tree prec + = cp_parser_constant_expression (parser, + /*allow_non_constant_p=*/false, + /*non_constant_p=*/nullptr, + /*strict_p=*/true); + if (!parens.require_close (parser)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + if (check_for_bare_parameter_packs (prec)) + prec = error_mark_node; + type = finish_bitint (loc, prec, false, tf_warning_or_error); + set_and_check_decl_spec_loc (decl_specs, ds_bitint, token); + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, token, + /*type_definition_p=*/false); + return type; + } case RID_AUTO: maybe_warn_cpp0x (CPP0X_AUTO); @@ -38031,6 +38072,7 @@ set_and_check_decl_spec_loc (cp_decl_spe "__complex", "constinit", "consteval", + "_BitInt", "this" }; gcc_rich_location richloc (location); --- a/gcc/cp/cp-tree.h 2026-11-11 12:32:33.493655185 +0100 +++ b/gcc/cp/cp-tree.h 2026-11-11 14:31:41.873252781 +0100 @@ -609,7 +609,8 @@ extern GTY(()) tree cp_global_trees[CPTI For a FUNCTION_TYPE or METHOD_TYPE, this is TYPE_RAISES_EXCEPTIONS. For a POINTER_TYPE (to a METHOD_TYPE), this is TYPE_PTRMEMFUNC_TYPE. For an ENUMERAL_TYPE, BOUND_TEMPLATE_TEMPLATE_PARM_TYPE, - RECORD_TYPE or UNION_TYPE this is TYPE_TEMPLATE_INFO, + RECORD_TYPE or UNION_TYPE this is TYPE_TEMPLATE_INFO. + For a BITINT_TYPE, this is BITINT_PREC. BINFO_VIRTUALS For a binfo, this is a TREE_LIST. There is an entry for each @@ -4911,29 +4912,29 @@ get_vec_init_expr (tree t) #define DECL_EXTERNAL_LINKAGE_P(DECL) \ (decl_linkage (DECL) == lk_external) -/* Keep these codes in ascending code order. */ - -#define INTEGRAL_CODE_P(CODE) \ - ((CODE) == ENUMERAL_TYPE \ - || (CODE) == BOOLEAN_TYPE \ - || (CODE) == INTEGER_TYPE) - /* [basic.fundamental] - Types bool, char, wchar_t, and the signed and unsigned integer types + Types bool, char, wchar_t, and the signed and unsigned integer types are collectively called integral types. Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration types as well, which is incorrect in C++. Keep these checks in ascending code order. */ +#define CP_INTEGRAL_CODE_P(CODE) \ + ((CODE) == BOOLEAN_TYPE \ + || (CODE) == INTEGER_TYPE \ + || (CODE) == BITINT_TYPE) + #define CP_INTEGRAL_TYPE_P(TYPE) \ - (TREE_CODE (TYPE) == BOOLEAN_TYPE \ - || TREE_CODE (TYPE) == INTEGER_TYPE) + CP_INTEGRAL_CODE_P (TREE_CODE (TYPE)) -/* Returns true if TYPE is an integral or enumeration name. Keep - these checks in ascending code order. */ +/* Keep these codes in ascending code order. */ +#define INTEGRAL_CODE_P(CODE) \ + ((CODE) == ENUMERAL_TYPE || CP_INTEGRAL_CODE_P (CODE)) + +/* Returns true if TYPE is an integral or enumeration name. */ #define INTEGRAL_OR_ENUMERATION_TYPE_P(TYPE) \ - (TREE_CODE (TYPE) == ENUMERAL_TYPE || CP_INTEGRAL_TYPE_P (TYPE)) + INTEGRAL_CODE_P (TREE_CODE (TYPE)) /* Returns true if TYPE is an integral or unscoped enumeration type. */ #define INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P(TYPE) \ @@ -5215,6 +5216,10 @@ get_vec_init_expr (tree t) #define INDIRECT_TYPE_P(NODE) \ (TYPE_PTR_P (NODE) || TYPE_REF_P (NODE)) +/* Precision of BITINT_TYPE when dependent. */ +#define BITINT_PREC(NODE) \ + TYPE_LANG_SLOT_1 (BITINT_TYPE_CHECK (NODE)) + /* Returns true if NODE is an object type: [basic.types] @@ -6979,6 +6984,7 @@ enum cp_decl_spec { ds_complex, ds_constinit, ds_consteval, + ds_bitint, ds_this, /* Index of last element of decl_spec_names. */ ds_thread, ds_type_spec, @@ -9116,6 +9122,8 @@ extern tree finish_binary_fold_expr extern tree treat_lvalue_as_rvalue_p (tree, bool); extern bool decl_in_std_namespace_p (tree); extern void maybe_warn_pessimizing_move (tree, tree, bool); +extern tree finish_bitint (location_t, tree, bool, + tsubst_flags_t); /* in typeck2.cc */ extern void require_complete_eh_spec_types (tree, tree); --- a/gcc/cp/typeck.cc 2026-11-11 10:28:33.761006403 +0100 +++ b/gcc/cp/typeck.cc 2026-11-12 19:17:15.180189418 +0100 @@ -473,6 +473,12 @@ cp_common_type (tree t1, tree t2) if (subtype == error_mark_node) return subtype; + if (TREE_CODE (subtype) == BITINT_TYPE) + { + sorry ("%<_Complex _BitInt(%d)%> unsupported", + TYPE_PRECISION (subtype)); + subtype = code1 == COMPLEX_TYPE ? subtype1 : subtype2; + } if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) return build_type_attribute_variant (t1, attributes); else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) @@ -584,6 +590,24 @@ cp_common_type (tree t1, tree t2) } } + if ((code1 == BITINT_TYPE || code2 == BITINT_TYPE) && code1 != code2) + { + /* Prefer any other integral types over bit-precise integer + types. */ + if (TYPE_UNSIGNED (t1) == TYPE_UNSIGNED (t2)) + return build_type_attribute_variant (code1 == BITINT_TYPE + ? t2 : t1, attributes); + /* If BITINT_TYPE is unsigned and the other type is signed + non-BITINT_TYPE with the same precision, the latter has higher + rank, so the common type is the corresponding unsigned integer + type. */ + if (TYPE_UNSIGNED (code1 == BITINT_TYPE ? t1 : t2)) + { + tree t = c_common_unsigned_type (code1 == BITINT_TYPE ? t2 : t1); + return build_type_attribute_variant (t, attributes); + } + } + /* Otherwise prefer the unsigned one. */ if (TYPE_UNSIGNED (t1)) return build_type_attribute_variant (t1, attributes); @@ -1523,6 +1547,19 @@ structural_comptypes (tree t1, tree t2, /* We don't need or want the attribute comparison. */ goto check_alias; + case BITINT_TYPE: + /* Similar to INTEGER_TYPE, just have to compare BITINT_PREC for + dependent bit-precise integers. */ + if (TYPE_CANONICAL (t1) != TYPE_CANONICAL (t2)) + return false; + if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)) + return false; + if (TYPE_PRECISION (t1) == 0 + && (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2) + || !cp_tree_equal (BITINT_PREC (t1), BITINT_PREC (t2)))) + return false; + goto check_alias; + case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: if (!comp_template_parms_position (t1, t2)) @@ -2781,6 +2818,7 @@ cp_perform_integral_promotions (tree exp tree bitfield_type = is_bitfield_expr_with_lowered_type (expr); if (bitfield_type && (TREE_CODE (bitfield_type) == ENUMERAL_TYPE + || TREE_CODE (bitfield_type) == BITINT_TYPE || TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node))) type = bitfield_type; @@ -4319,6 +4357,10 @@ cp_build_array_ref (location_t loc, tree "subscripting array declared %<register%>"); } + if (BITINT_TYPE_P (TREE_TYPE (idx)) + && TYPE_PRECISION (TREE_TYPE (idx)) > TYPE_PRECISION (sizetype)) + idx = fold_convert (sizetype, idx); + type = TREE_TYPE (TREE_TYPE (array)); rval = build4 (ARRAY_REF, type, array, idx, NULL_TREE, NULL_TREE); /* Array ref is const/volatile if the array elements are @@ -4346,7 +4388,7 @@ cp_build_array_ref (location_t loc, tree ar = first = save_expr (ar); /* Put the integer in IND to simplify error checking. */ - if (TREE_CODE (TREE_TYPE (ar)) == INTEGER_TYPE) + if (CP_INTEGRAL_TYPE_P (TREE_TYPE (ar))) std::swap (ar, ind); if (ar == error_mark_node || ind == error_mark_node) @@ -4358,7 +4400,7 @@ cp_build_array_ref (location_t loc, tree error_at (loc, "subscripted value is neither array nor pointer"); return error_mark_node; } - if (TREE_CODE (TREE_TYPE (ind)) != INTEGER_TYPE) + if (!CP_INTEGRAL_TYPE_P (TREE_TYPE (ind))) { if (complain & tf_error) error_at (loc, "array subscript is not an integer"); @@ -5764,7 +5806,7 @@ cp_build_binary_op (const op_location_t } /* In all other cases except pointer - int, the usual arithmetic rules apply. */ - else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) + else if (!(code0 == POINTER_TYPE && CP_INTEGRAL_CODE_P (code1))) { common = 1; break; @@ -5773,13 +5815,13 @@ cp_build_binary_op (const op_location_t through. */ gcc_fallthrough (); case PLUS_EXPR: - if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE) - && (code0 == INTEGER_TYPE || code1 == INTEGER_TYPE)) + if ((code0 == POINTER_TYPE && CP_INTEGRAL_CODE_P (code1)) + || (code1 == POINTER_TYPE && CP_INTEGRAL_CODE_P (code0))) { tree ptr_operand; tree int_operand; - ptr_operand = ((code0 == POINTER_TYPE) ? op0 : op1); - int_operand = ((code0 == INTEGER_TYPE) ? op0 : op1); + ptr_operand = (code0 == POINTER_TYPE) ? op0 : op1; + int_operand = (code0 == POINTER_TYPE) ? op1 : op0; if (processing_template_decl) { result_type = TREE_TYPE (ptr_operand); @@ -5842,9 +5884,9 @@ cp_build_binary_op (const op_location_t op1, non_reference (type1)); } - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + if ((CP_INTEGRAL_CODE_P (code0) || code0 == REAL_TYPE || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + && (CP_INTEGRAL_CODE_P (code1) || code1 == REAL_TYPE || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)) { enum tree_code tcode0 = code0, tcode1 = code1; @@ -5856,9 +5898,9 @@ cp_build_binary_op (const op_location_t if (tcode1 == COMPLEX_TYPE || tcode1 == VECTOR_TYPE) tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1))); - if (!((tcode0 == INTEGER_TYPE + if (!(((tcode0 == INTEGER_TYPE || tcode0 == BITINT_TYPE) || (tcode0 == ENUMERAL_TYPE && code0 == VECTOR_TYPE)) - && (tcode1 == INTEGER_TYPE + && ((tcode1 == INTEGER_TYPE || tcode1 == BITINT_TYPE) || (tcode1 == ENUMERAL_TYPE && code1 == VECTOR_TYPE)))) resultcode = RDIV_EXPR; else @@ -5879,7 +5921,7 @@ cp_build_binary_op (const op_location_t case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: - if ((code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + if ((CP_INTEGRAL_CODE_P (code0) && CP_INTEGRAL_CODE_P (code1)) || (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE && !VECTOR_FLOAT_TYPE_P (type0) && !VECTOR_FLOAT_TYPE_P (type1))) @@ -5895,7 +5937,7 @@ cp_build_binary_op (const op_location_t && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE) common = 1; - else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + else if (CP_INTEGRAL_CODE_P (code0) && CP_INTEGRAL_CODE_P (code1)) { /* Although it would be tempting to shorten always here, that loses on some targets, since the modulo instruction is undefined if the @@ -5957,8 +5999,10 @@ cp_build_binary_op (const op_location_t if (warn_constant_logical_operand && (complain & tf_warning) - && (code0 == INTEGER_TYPE || code0 == ENUMERAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == ENUMERAL_TYPE)) + && (code0 == INTEGER_TYPE || code0 == BITINT_TYPE + || code0 == ENUMERAL_TYPE) + && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE + || code1 == ENUMERAL_TYPE)) { tree cop0 = fold_for_warn (op0), cop1 = fold_for_warn (op1); const char *name @@ -6002,7 +6046,7 @@ cp_build_binary_op (const op_location_t case RSHIFT_EXPR: if (gnu_vector_type_p (type0) - && code1 == INTEGER_TYPE + && CP_INTEGRAL_CODE_P (code1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { result_type = type0; @@ -6018,7 +6062,7 @@ cp_build_binary_op (const op_location_t result_type = type0; converted = 1; } - else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + else if (CP_INTEGRAL_CODE_P (code0) && CP_INTEGRAL_CODE_P (code1)) { tree const_op1 = fold_for_warn (op1); if (TREE_CODE (const_op1) != INTEGER_CST) @@ -6053,7 +6097,7 @@ cp_build_binary_op (const op_location_t case LSHIFT_EXPR: if (gnu_vector_type_p (type0) - && code1 == INTEGER_TYPE + && CP_INTEGRAL_CODE_P (code1) && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE) { result_type = type0; @@ -6069,7 +6113,7 @@ cp_build_binary_op (const op_location_t result_type = type0; converted = 1; } - else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) + else if (CP_INTEGRAL_CODE_P (code0) && CP_INTEGRAL_CODE_P (code1)) { tree const_op0 = fold_for_warn (op0); if (TREE_CODE (const_op0) != INTEGER_CST) @@ -6146,10 +6190,10 @@ cp_build_binary_op (const op_location_t } build_type = boolean_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)) + if ((INTEGRAL_CODE_P (code0) || code0 == REAL_TYPE + || code0 == COMPLEX_TYPE) + && (INTEGRAL_CODE_P (code1) || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE)) short_compare = 1; else if (((code0 == POINTER_TYPE || TYPE_PTRDATAMEM_P (type0)) && null_ptr_cst_p (orig_op1)) @@ -6207,7 +6251,7 @@ cp_build_binary_op (const op_location_t else if (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1)) /* One of the operands must be of nullptr_t type. */ result_type = TREE_TYPE (nullptr_node); - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + else if (code0 == POINTER_TYPE && CP_INTEGRAL_CODE_P (code1)) { result_type = type0; if (complain & tf_error) @@ -6216,7 +6260,7 @@ cp_build_binary_op (const op_location_t else return error_mark_node; } - else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + else if (CP_INTEGRAL_CODE_P (code0) && code1 == POINTER_TYPE) { result_type = type1; if (complain & tf_error) @@ -6404,8 +6448,8 @@ cp_build_binary_op (const op_location_t case MAX_EXPR: case MIN_EXPR: - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((CP_INTEGRAL_CODE_P (code0) || code0 == REAL_TYPE) + && (CP_INTEGRAL_CODE_P (code1) || code1 == REAL_TYPE)) shorten = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (location, @@ -6513,10 +6557,8 @@ cp_build_binary_op (const op_location_t return build_vec_cmp (resultcode, result_type, op0, op1); } build_type = boolean_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE - || code0 == ENUMERAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == ENUMERAL_TYPE)) + if ((INTEGRAL_CODE_P (code0) || code0 == REAL_TYPE) + && (INTEGRAL_CODE_P (code1) || code1 == REAL_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (location, @@ -6532,7 +6574,7 @@ cp_build_binary_op (const op_location_t "integer zero (%qT and %qT)", type0, type1); return error_mark_node; } - else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) + else if (code0 == POINTER_TYPE && CP_INTEGRAL_CODE_P (code1)) { result_type = type0; if (complain & tf_error) @@ -6541,7 +6583,7 @@ cp_build_binary_op (const op_location_t else return error_mark_node; } - else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) + else if (CP_INTEGRAL_CODE_P (code0) && code1 == POINTER_TYPE) { result_type = type1; if (complain & tf_error) @@ -6585,10 +6627,9 @@ cp_build_binary_op (const op_location_t break; } - if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE - || code0 == ENUMERAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE - || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))) + if ((INTEGRAL_CODE_P (code0) || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) + && (INTEGRAL_CODE_P (code1) || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE)) arithmetic_types_p = 1; else { @@ -9851,7 +9892,8 @@ cp_build_c_cast (location_t loc, tree ty } if (TYPE_PTR_P (type) - && TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE + && (TREE_CODE (TREE_TYPE (value)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (value)) == BITINT_TYPE) /* Casting to an integer of smaller size is an error detected elsewhere. */ && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (value)) /* Don't warn about converting any constant. */ @@ -12167,7 +12209,8 @@ ptr_reasonably_similar (const_tree to, c && vector_types_convertible_p (to, from, false)) return true; - if (TREE_CODE (to) == INTEGER_TYPE + if ((TREE_CODE (to) == INTEGER_TYPE + || TREE_CODE (to) == BITINT_TYPE) && TYPE_PRECISION (to) == TYPE_PRECISION (from)) return true; @@ -12633,6 +12676,60 @@ check_literal_operator_args (const_tree } } +/* Finish a BITINT_TYPE with precision PREC. */ + +tree +finish_bitint (location_t loc, tree prec, bool unsignedp, + tsubst_flags_t complain) +{ + if (!type_dependent_expression_p (prec)) + prec = build_converted_constant_expr (size_type_node, prec, complain); + prec = fold_non_dependent_expr (prec, complain, true); + if (error_operand_p (prec)) + return error_mark_node; + if (TREE_CODE (prec) == INTEGER_CST) + { + if (integer_zerop (prec)) + { + if (complain & tf_error) + error_at (loc, "%<_BitInt%> argument %qE is not a positive " + "integer constant expression", prec); + return error_mark_node; + } + else if (wi::to_widest (prec) > WIDE_INT_MAX_PRECISION - 1) + { + if (complain & tf_error) + error_at (loc, "%<_BitInt%> argument %qE is larger than " + "%<BITINT_MAXWIDTH%> %qd", + prec, (int) WIDE_INT_MAX_PRECISION - 1); + return error_mark_node; + } + unsigned int p = tree_to_uhwi (prec); + struct bitint_info info; + if (!targetm.c.bitint_type_info (p, &info)) + { + if (complain & tf_error) + sorry_at (loc, "%<_BitInt(%d)%> is not supported on this " + "target", p); + return error_mark_node; + } + return build_bitint_type (p, unsignedp); + } + else if (!value_dependent_expression_p (prec)) + { + if (complain & tf_error) + error_at (loc, "%<_BitInt%> argument is not an integer " + "constant expression"); + return error_mark_node; + } + tree ret = make_node (BITINT_TYPE); + TYPE_PRECISION (ret) = 0; + TYPE_UNSIGNED (ret) = unsignedp; + BITINT_PREC (ret) = prec; + SET_TYPE_STRUCTURAL_EQUALITY (ret); + return ret; +} + /* Always returns false since unlike C90, C++ has no concept of implicit function declarations. */ --- a/gcc/cp/decl.cc 2026-11-11 10:28:33.749006561 +0100 +++ b/gcc/cp/decl.cc 2026-11-11 13:16:41.819992887 +0100 @@ -7709,6 +7709,7 @@ reshape_init_array_1 (tree elt_type, tre check_array_designated_initializer (d->cur, index); if (TREE_CODE (d->cur->value) == RAW_DATA_CST && (TREE_CODE (elt_type) == INTEGER_TYPE + || TREE_CODE (elt_type) == BITINT_TYPE || is_byte_access_type (elt_type)) && TYPE_PRECISION (elt_type) == CHAR_BIT && (!sized_array_p || index < max_index_cst) @@ -14253,6 +14254,7 @@ grokdeclarator (const cp_declarator *dec bool constexpr_p = decl_spec_seq_has_spec_p (declspecs, ds_constexpr); bool constinit_p = decl_spec_seq_has_spec_p (declspecs, ds_constinit); bool consteval_p = decl_spec_seq_has_spec_p (declspecs, ds_consteval); + bool bitint_p = decl_spec_seq_has_spec_p (declspecs, ds_bitint); bool late_return_type_p = false; bool array_parameter_p = false; tree reqs = NULL_TREE; @@ -14774,15 +14776,19 @@ grokdeclarator (const cp_declarator *dec complain_about_incompatible_declspecs ("long", declspecs->locations[ds_long], "short", declspecs->locations[ds_short]); - else if (TREE_CODE (type) != INTEGER_TYPE + else if ((TREE_CODE (type) != INTEGER_TYPE + && TREE_CODE (type) != BITINT_TYPE) || type == char8_type_node || type == char16_type_node || type == char32_type_node || ((long_p || short_p) - && (explicit_char || explicit_intN))) + && (explicit_char + || explicit_intN + || TREE_CODE (type) == BITINT_TYPE))) error_at (loc, "%qs specified with %qT", key, type); else if (!explicit_int && !defaulted_int - && !explicit_char && !explicit_intN) + && !explicit_char && !explicit_intN + && !bitint_p) { if (typedef_decl) { @@ -14845,6 +14851,16 @@ grokdeclarator (const cp_declarator *dec type = short_unsigned_type_node; else if (type == char_type_node) type = unsigned_char_type_node; + else if (TREE_CODE (type) == BITINT_TYPE) + { + if (TYPE_PRECISION (type)) + type = c_common_unsigned_type (type); + else + { + type = build_distinct_type_copy (type); + TYPE_UNSIGNED (type) = 1; + } + } else if (typedef_decl) type = c_common_unsigned_type (type); else --- a/gcc/cp/pt.cc 2026-11-11 10:28:33.758006442 +0100 +++ b/gcc/cp/pt.cc 2026-11-11 13:16:41.822558740 +0100 @@ -4248,6 +4248,15 @@ find_parameter_packs_r (tree *tp, int *w *walk_subtrees = 0; return NULL_TREE; + case BITINT_TYPE: + if (TYPE_PRECISION (t) == 0) + { + cp_walk_tree (&BITINT_PREC (t), &find_parameter_packs_r, + ppd, ppd->visited); + } + *walk_subtrees = 0; + return NULL_TREE; + case IDENTIFIER_NODE: cp_walk_tree (&TREE_TYPE (t), &find_parameter_packs_r, ppd, ppd->visited); @@ -17428,6 +17437,16 @@ tsubst (tree t, tree args, tsubst_flags_ return compute_array_index_type (NULL_TREE, max, complain); } + case BITINT_TYPE: + if (TYPE_PRECISION (t)) + return t; + else + { + tree prec = tsubst_expr (BITINT_PREC (t), args, complain, in_decl); + return finish_bitint (input_location, prec, TYPE_UNSIGNED (t), + complain); + } + case TEMPLATE_TYPE_PARM: if (TEMPLATE_TYPE_LEVEL (t) == 0) { @@ -24993,6 +25012,11 @@ uses_deducible_template_parms (tree type return (uses_deducible_template_parms (TREE_TYPE (type)) || deducible_array_bound (TYPE_DOMAIN (type))); + /* _BitInt(i) */ + if (TREE_CODE (type) == BITINT_TYPE + && TYPE_PRECISION (type) == 0) + return deducible_expression (BITINT_PREC (type)); + /* T type ::* type T::* T T::* @@ -25164,6 +25188,12 @@ array_deduction_r (tree t, void *data) UNIFY_ALLOW_NONE, /*explain*/false); } + if (TREE_CODE (t) == BITINT_TYPE + && TYPE_PRECISION (t) == 0 + && TREE_CODE (BITINT_PREC (t)) == TEMPLATE_PARM_INDEX) + unify (tparms, targs, TREE_TYPE (BITINT_PREC (t)), size_type_node, + UNIFY_ALLOW_NONE, /*explain*/false); + /* Keep walking. */ return 0; } @@ -25171,7 +25201,7 @@ array_deduction_r (tree t, void *data) /* Try to deduce any not-yet-deduced template type arguments from the type of an array bound. This is handled separately from unify because 14.8.2.5 says "The type of a type parameter is only deduced from an array bound if it is - not otherwise deduced." */ + not otherwise deduced." Also handles _BitInt width deduction. */ static void try_array_deduction (tree tparms, tree targs, tree parm) @@ -26947,6 +26977,28 @@ unify (tree tparms, tree targs, tree par will invalidate it if necessary. */ return unify_success (explain_p); + case BITINT_TYPE: + if (TREE_CODE (arg) != BITINT_TYPE + || TYPE_UNSIGNED (arg) != TYPE_UNSIGNED (parm)) + return unify_type_mismatch (explain_p, parm, arg); + if (TYPE_PRECISION (arg) == 0 || TYPE_PRECISION (parm) == 0) + { + tree arg_prec, parm_prec; + if (TYPE_PRECISION (arg) == 0) + arg_prec = BITINT_PREC (arg); + else + arg_prec = size_int (TYPE_PRECISION (arg)); + if (TYPE_PRECISION (parm) == 0) + parm_prec = BITINT_PREC (parm); + else + parm_prec = size_int (TYPE_PRECISION (parm)); + return unify (tparms, targs, parm_prec, arg_prec, + UNIFY_ALLOW_INTEGER, explain_p); + } + if (!same_type_ignoring_top_level_qualifiers_p (arg, parm)) + return unify_type_mismatch (explain_p, parm, arg); + return unify_success (explain_p); + /* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */ /* Type INTEGER_CST can come from ordinary constant template args. */ case INTEGER_CST: @@ -29909,6 +29961,12 @@ dependent_type_p_r (tree type) || TREE_CODE (type) == TRAIT_TYPE) return true; + /* Bit-precise integer types with value-dependent width are dependent. */ + if (TREE_CODE (type) == BITINT_TYPE + && TYPE_PRECISION (type) == 0 + && BITINT_PREC (type)) + return true; + /* A template argument pack is dependent if any of its packed arguments are. */ if (TREE_CODE (type) == TYPE_ARGUMENT_PACK) --- a/gcc/cp/error.cc 2026-11-11 10:28:33.749006561 +0100 +++ b/gcc/cp/error.cc 2026-11-11 13:16:41.824208069 +0100 @@ -766,6 +766,7 @@ dump_type (cxx_pretty_printer *pp, tree case COMPLEX_TYPE: case VECTOR_TYPE: case FIXED_POINT_TYPE: + case BITINT_TYPE: pp_type_specifier_seq (pp, t); break; @@ -1148,6 +1149,7 @@ dump_type_prefix (cxx_pretty_printer *pp case NULLPTR_TYPE: case PACK_INDEX_TYPE: case SPLICE_SCOPE: + case BITINT_TYPE: dump_type (pp, t, flags); pp->set_padding (pp_before); break; @@ -1282,6 +1284,7 @@ dump_type_suffix (cxx_pretty_printer *pp case NULLPTR_TYPE: case PACK_INDEX_TYPE: case SPLICE_SCOPE: + case BITINT_TYPE: break; default: @@ -3173,6 +3176,7 @@ dump_expr (cxx_pretty_printer *pp, tree case COMPLEX_TYPE: case VECTOR_TYPE: case DECLTYPE_TYPE: + case BITINT_TYPE: pp_type_specifier_seq (pp, t); break; --- a/gcc/cp/cxx-pretty-print.cc 2026-11-06 18:32:41.070465857 +0100 +++ b/gcc/cp/cxx-pretty-print.cc 2026-11-11 13:16:41.824613045 +0100 @@ -1442,6 +1442,21 @@ cxx_pretty_printer::simple_type_specifie pp_cxx_trait (this, t); break; + case BITINT_TYPE: + if (TYPE_NAME (t) == NULL_TREE + && TYPE_PRECISION (t) == 0 + && BITINT_PREC (t)) + { + if (TYPE_UNSIGNED (t)) + pp_c_ws_string (this, "unsigned"); + pp_c_ws_string (this, "_BitInt("); + expression (BITINT_PREC (t)); + pp_right_paren (this); + break; + } + c_pretty_printer::simple_type_specifier (t); + break; + case OPAQUE_TYPE: if (REFLECTION_TYPE_P (t)) { --- a/gcc/cp/tree.cc 2026-11-11 10:28:33.760006416 +0100 +++ b/gcc/cp/tree.cc 2026-11-11 13:16:41.824999313 +0100 @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. #include "attribs.h" #include "flags.h" #include "selftest.h" +#include "target.h" static tree bot_manip (tree *, int *, void *); static tree bot_replace (tree *, int *, void *); @@ -5126,6 +5127,39 @@ type_has_unique_obj_representations (con inform (loc, "%qT is a fixed-point type", t); return false; + case BITINT_TYPE: + { + struct bitint_info info; + bool ok = targetm.c.bitint_type_info (TYPE_PRECISION (t), &info); + gcc_assert (ok); + if (info.extended == bitint_ext_full) + return true; + scalar_int_mode abi_limb_mode + = as_a <scalar_int_mode> (info.abi_limb_mode); + if (TYPE_PRECISION (t) < GET_MODE_PRECISION (abi_limb_mode)) + { + if (info.extended == bitint_ext_partial) + return true; + } + else if (TYPE_PRECISION (t) == GET_MODE_PRECISION (abi_limb_mode)) + return true; + else if ((((unsigned) TYPE_PRECISION (t)) + % GET_MODE_PRECISION (abi_limb_mode)) == 0) + return true; + else if (info.extended == bitint_ext_partial) + { + scalar_int_mode limb_mode + = as_a <scalar_int_mode> (info.limb_mode); + if ((ROUND_UP ((unsigned) TYPE_PRECISION (t), + (unsigned) GET_MODE_PRECISION (limb_mode)) + % GET_MODE_PRECISION (abi_limb_mode)) == 0) + return true; + } + if (explain) + inform (loc, "%qT has padding bits", t); + return false; + } + case OFFSET_TYPE: return true; @@ -6618,6 +6652,11 @@ cp_walk_subtrees (tree *tp, int *walk_su WALK_SUBTREE (TYPE_MAX_VALUE (t)); break; + case BITINT_TYPE: + if (TYPE_PRECISION (t) == 0) + WALK_SUBTREE (BITINT_PREC (t)); + break; + case SPLICE_SCOPE: WALK_SUBTREE (SPLICE_SCOPE_EXPR (t)); *walk_subtrees_p = 0; --- a/gcc/cp/semantics.cc 2026-11-11 12:33:59.592518785 +0100 +++ b/gcc/cp/semantics.cc 2026-11-11 13:23:44.205992637 +0100 @@ -5358,11 +5358,14 @@ finish_make_signed (tree type, bool unsi return error_mark_node; } tree ret = type; - if (TREE_CODE (type) == ENUMERAL_TYPE - || TYPE_MAIN_VARIANT (type) == wchar_type_node - || TYPE_MAIN_VARIANT (type) == char8_type_node - || TYPE_MAIN_VARIANT (type) == char16_type_node - || TYPE_MAIN_VARIANT (type) == char32_type_node) + if (TREE_CODE (type) == ENUMERAL_TYPE && BITINT_TYPE_P (type)) + ret = c_common_signed_or_unsigned_type (unsignedp, + ENUM_UNDERLYING_TYPE (type)); + else if (TREE_CODE (type) == ENUMERAL_TYPE + || TYPE_MAIN_VARIANT (type) == wchar_type_node + || TYPE_MAIN_VARIANT (type) == char8_type_node + || TYPE_MAIN_VARIANT (type) == char16_type_node + || TYPE_MAIN_VARIANT (type) == char32_type_node) { tree unit = TYPE_SIZE_UNIT (type); tree types[] = { @@ -11919,7 +11922,8 @@ handle_omp_for_class_iterator (int i, lo diff = cp_fully_fold (diff); if (error_operand_p (diff)) return true; - if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE) + if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE + && TREE_CODE (TREE_TYPE (diff)) != BITINT_TYPE) { error_at (elocus, "difference between %qE and %qD does not have integer type", TREE_OPERAND (cond, 1), iter); @@ -11962,7 +11966,9 @@ handle_omp_for_class_iterator (int i, lo if (TREE_OPERAND (rhs, 0) == iter) { if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 1))) - != INTEGER_TYPE) + != INTEGER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 1))) + != BITINT_TYPE)) incr = error_mark_node; else { @@ -11990,7 +11996,10 @@ handle_omp_for_class_iterator (int i, lo } else if (TREE_OPERAND (rhs, 1) == iter) { - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) != INTEGER_TYPE + if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) + != INTEGER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) + != BITINT_TYPE)) || TREE_CODE (rhs) != PLUS_EXPR) incr = error_mark_node; else --- a/gcc/cp/call.cc 2026-11-11 10:28:33.744006627 +0100 +++ b/gcc/cp/call.cc 2026-11-11 13:16:41.826982338 +0100 @@ -564,7 +564,8 @@ null_ptr_cst_p (tree t) /* Core issue 903 says only literal 0 is a null pointer constant. */ if (TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t) - && TREE_CODE (type) == INTEGER_TYPE + && (TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == BITINT_TYPE) && integer_zerop (t) && !char_type_p (type)) return true; @@ -888,6 +889,7 @@ build_list_conv (tree type, tree ctor, i if (sub->kind == ck_std && sub->type && (TREE_CODE (sub->type) == INTEGER_TYPE + || TREE_CODE (sub->type) == BITINT_TYPE || is_byte_access_type (sub->type)) && TYPE_PRECISION (sub->type) == CHAR_BIT && (next = next_conversion (sub)) @@ -1400,15 +1402,18 @@ standard_conversion (tree to, tree from, && ((expr && null_ptr_cst_p (expr)) || NULLPTR_TYPE_P (from))) conv = build_conv (ck_std, to, conv); - else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE) - || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE)) + else if (((tcode == INTEGER_TYPE || tcode == BITINT_TYPE) + && fcode == POINTER_TYPE) + || (tcode == POINTER_TYPE + && (fcode == INTEGER_TYPE || fcode == BITINT_TYPE))) { /* For backwards brain damage compatibility, allow interconversion of pointers and integers with a pedwarn. */ conv = build_conv (ck_std, to, conv); conv->bad_p = true; } - else if (UNSCOPED_ENUM_P (to) && fcode == INTEGER_TYPE) + else if (UNSCOPED_ENUM_P (to) + && (fcode == INTEGER_TYPE || fcode == BITINT_TYPE)) { /* For backwards brain damage compatibility, allow interconversion of enums and integers with a pedwarn. */ @@ -6073,9 +6078,11 @@ build_conditional_expr (const op_locatio if ((TREE_CODE (arg2) == EXCESS_PRECISION_EXPR || TREE_CODE (arg3) == EXCESS_PRECISION_EXPR) && (TREE_CODE (arg2_type) == INTEGER_TYPE + || TREE_CODE (arg2_type) == BITINT_TYPE || SCALAR_FLOAT_TYPE_P (arg2_type) || TREE_CODE (arg2_type) == COMPLEX_TYPE) && (TREE_CODE (arg3_type) == INTEGER_TYPE + || TREE_CODE (arg3_type) == BITINT_TYPE || SCALAR_FLOAT_TYPE_P (arg3_type) || TREE_CODE (arg3_type) == COMPLEX_TYPE)) { @@ -9085,6 +9092,7 @@ convert_like_internal (conversion *convs conversion *next = next_conversion (convs->u.list[ix]); gcc_assert (et && (TREE_CODE (et) == INTEGER_TYPE + || TREE_CODE (et) == BITINT_TYPE || is_byte_access_type (et)) && TYPE_PRECISION (et) == CHAR_BIT && next @@ -13483,8 +13491,10 @@ joust (struct z_candidate *cand1, struct == cr_std + cr_promotion) && t1->kind == ck_std && t2->kind == ck_std - && TREE_CODE (t1->type) == INTEGER_TYPE - && TREE_CODE (t2->type) == INTEGER_TYPE + && (TREE_CODE (t1->type) == INTEGER_TYPE + || TREE_CODE (t1->type) == BITINT_TYPE) + && (TREE_CODE (t2->type) == INTEGER_TYPE + || TREE_CODE (t2->type) == BITINT_TYPE) && (TYPE_PRECISION (t1->type) == TYPE_PRECISION (t2->type)) && (TYPE_UNSIGNED (next_conversion (t1)->type) --- a/gcc/cp/constexpr.cc 2026-11-11 10:28:33.746006601 +0100 +++ b/gcc/cp/constexpr.cc 2026-11-11 13:16:41.828172106 +0100 @@ -6882,7 +6882,8 @@ cxx_eval_bit_field_ref (const constexpr_ STRIP_ANY_LOCATION_WRAPPER (value); if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1)) return value; - if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE + if ((TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (field)) == BITINT_TYPE) && TREE_CODE (value) == INTEGER_CST && tree_fits_shwi_p (bitpos) && tree_fits_shwi_p (DECL_SIZE (field))) @@ -11642,7 +11643,9 @@ cxx_eval_outermost_constant_expr (tree t we don't shortcut all vector constructors. */ if (fndecl && DECL_CONSTRUCTOR_P (fndecl) && allow_non_constant && is_std_class (type, "vector") && call_expr_nargs (x) > 1 - && TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) == INTEGER_TYPE) + && (TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) == INTEGER_TYPE + || (TREE_CODE (TREE_TYPE (get_nth_callarg (x, 1))) + == BITINT_TYPE))) return t; } if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)) --- a/gcc/cp/cvt.cc 2026-11-06 18:32:41.070465857 +0100 +++ b/gcc/cp/cvt.cc 2026-11-11 13:16:41.828958331 +0100 @@ -1868,6 +1868,7 @@ build_expr_type_conversion (int desires, switch (TREE_CODE (basetype)) { case INTEGER_TYPE: + case BITINT_TYPE: if ((desires & WANT_NULL) && null_ptr_cst_p (expr)) return expr; /* fall through. */ @@ -1897,6 +1898,7 @@ build_expr_type_conversion (int desires, switch (TREE_CODE (TREE_TYPE (basetype))) { case INTEGER_TYPE: + case BITINT_TYPE: case BOOLEAN_TYPE: return (desires & WANT_INT) ? expr : NULL_TREE; case ENUMERAL_TYPE: @@ -1937,6 +1939,7 @@ build_expr_type_conversion (int desires, { case BOOLEAN_TYPE: case INTEGER_TYPE: + case BITINT_TYPE: win = (desires & WANT_INT); break; case ENUMERAL_TYPE: win = (desires & WANT_ENUM); break; --- a/gcc/cp/init.cc 2026-11-06 18:32:41.072465831 +0100 +++ b/gcc/cp/init.cc 2026-11-11 13:16:41.829680586 +0100 @@ -4930,6 +4930,7 @@ build_vec_init (tree base, tree maxindex { if (digested && (TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == BITINT_TYPE || is_byte_access_type (type)) && TYPE_PRECISION (type) == CHAR_BIT) { --- a/gcc/cp/mangle.cc 2026-11-11 10:28:33.749006561 +0100 +++ b/gcc/cp/mangle.cc 2026-11-11 13:16:41.830167880 +0100 @@ -2554,7 +2554,8 @@ write_type (tree type) if (!VOID_TYPE_P (type) && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE - && TREE_CODE (type) != BOOLEAN_TYPE) + && TREE_CODE (type) != BOOLEAN_TYPE + && TREE_CODE (type) != BITINT_TYPE) add_substitution (type); return; } @@ -2566,6 +2567,7 @@ write_type (tree type) case INTEGER_TYPE: /* Includes wchar_t. */ case REAL_TYPE: case FIXED_POINT_TYPE: + case BITINT_TYPE: { /* If this is a typedef, TYPE may not be one of the standard builtin type nodes, but an alias of one. Use @@ -2940,7 +2942,16 @@ write_CV_qualifiers_for_type (const tree ::= f # float ::= d # double ::= e # long double, __float80 - ::= g # __float128 [not supported] + ::= g # __float128 + ::= Di # char32_t + ::= Ds # char16_t + ::= Du # char8_t + ::= DB <number> _ # C++29 signed _BitInt(N) + ::= DB <instantiation-dependent expression> _ + # C++29 signed _BitInt(N) + ::= DU <number> _ # C++29 unsigned _BitInt(N) + ::= DU <instantiation-dependent expression> _ + # C++29 unsigned _BitInt(N) ::= u <source-name> # vendor extended type */ static void @@ -3056,6 +3067,18 @@ write_builtin_type (tree type) gcc_unreachable (); break; + case BITINT_TYPE: + if (TYPE_UNSIGNED (type)) + write_string ("DU"); + else + write_string ("DB"); + if (TYPE_PRECISION (type) != 0) + write_number (TYPE_PRECISION (type), /*unsigned_p=*/1, 10); + else + write_expression (BITINT_PREC (type)); + write_char ('_'); + break; + default: gcc_unreachable (); } --- a/gcc/cp/class.cc 2026-11-11 10:28:33.745006614 +0100 +++ b/gcc/cp/class.cc 2026-11-11 13:16:41.830820812 +0100 @@ -7316,9 +7316,13 @@ layout_class_type (tree t, tree *virtual width = tree_to_uhwi (DECL_SIZE (field)); if (width != TYPE_PRECISION (ftype)) { - TREE_TYPE (field) - = c_build_bitfield_integer_type (width, - TYPE_UNSIGNED (ftype)); + if (BITINT_TYPE_P (ftype) && width >= 1) + TREE_TYPE (field) + = build_bitint_type (width, TYPE_UNSIGNED (ftype)); + else + TREE_TYPE (field) + = c_build_bitfield_integer_type (width, + TYPE_UNSIGNED (ftype)); TREE_TYPE (field) = cp_build_qualified_type (TREE_TYPE (field), cp_type_quals (ftype)); @@ -7374,7 +7378,8 @@ layout_class_type (tree t, tree *virtual to that width. */ && (DECL_SIZE (field) == NULL_TREE || integer_zerop (DECL_SIZE (field))) - && TREE_TYPE (field) != error_mark_node) + && TREE_TYPE (field) != error_mark_node + && DECL_BIT_FIELD (field)) SET_DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field, 1); check_non_pod_aggregate (field); } --- a/gcc/cp/module.cc 2026-11-11 10:28:33.751006535 +0100 +++ b/gcc/cp/module.cc 2026-11-12 10:31:26.357957754 +0100 @@ -9801,6 +9801,17 @@ trees_out::type_node (tree type) } break; + case BITINT_TYPE: + tree_node (BITINT_PREC (type)); + if (streaming_p ()) + { + unsigned prec = TYPE_PRECISION (type); + bool unsigned_p = TYPE_UNSIGNED (type); + + u ((prec << 1) | unsigned_p); + } + break; + case METHOD_TYPE: case FUNCTION_TYPE: { @@ -10611,6 +10622,26 @@ trees_in::tree_node (bool is_use) } break; + case BITINT_TYPE: + { + tree prec = tree_node (); + unsigned enc = u (); + if (!get_overrun ()) + { + if ((enc & ~1) != 0) + res = build_bitint_type (enc >> 1, enc & 1); + else + { + res = make_node (BITINT_TYPE); + TYPE_PRECISION (res) = 0; + TYPE_UNSIGNED (res) = enc & 1; + BITINT_PREC (res) = prec; + SET_TYPE_STRUCTURAL_EQUALITY (res); + } + } + } + break; + case FUNCTION_TYPE: case METHOD_TYPE: { --- a/gcc/testsuite/c-c++-common/builtin-bswapg-1.c 2026-11-06 18:32:41.086465643 +0100 +++ b/gcc/testsuite/c-c++-common/builtin-bswapg-1.c 2026-11-11 13:16:41.834809766 +0100 @@ -1,6 +1,7 @@ /* Test __builtin_bswapg. */ /* { dg-do run { target { c || c++11 } } } */ /* { dg-options "-O2" } */ +/* { dg-additional-options "-Wno-c++29-extensions" { target c++26_down } } */ #if !__has_builtin(__builtin_bswapg) #error __builtin_bswapg unsupported --- a/gcc/testsuite/c-c++-common/builtin-bswapg-3.c 2026-11-06 18:32:41.086465643 +0100 +++ b/gcc/testsuite/c-c++-common/builtin-bswapg-3.c 2026-11-11 13:16:41.834960406 +0100 @@ -1,6 +1,7 @@ /* Test __builtin_bswapg. */ /* { dg-do compile } */ /* { dg-options "" } */ +/* { dg-additional-options "-Wno-c++29-extensions" { target c++26_down } } */ int main () --- a/gcc/testsuite/c-c++-common/builtin-bitreverseg-1.c 2026-11-06 18:32:41.086465643 +0100 +++ b/gcc/testsuite/c-c++-common/builtin-bitreverseg-1.c 2026-11-11 13:16:41.835152040 +0100 @@ -1,6 +1,7 @@ /* Test __builtin_bitreverseg. */ /* { dg-do run { target { c || c++11 } } } */ /* { dg-options "-O2" } */ +/* { dg-additional-options "-Wno-c++29-extensions" { target c++26_down } } */ #if !__has_builtin(__builtin_bitreverseg) #error __builtin_bitreverseg unsupported --- a/gcc/testsuite/g++.dg/ext/bitint1.C 2026-11-06 18:32:41.087465629 +0100 +++ b/gcc/testsuite/g++.dg/ext/bitint1.C 2026-11-11 13:16:41.831287099 +0100 @@ -1,9 +0,0 @@ -// PR c/102989 -// { dg-do compile } - -_BitInt(63) a; // { dg-error "expected" } -unsigned _BitInt(31) b; // { dg-error "expected" } -int c = 21wb; // { dg-error "invalid suffix 'wb' on integer constant" "" { target c++98_only } } - // { dg-error "unable to find numeric literal operator 'operator\"\"wb'" "" { target c++11 } .-1 } -long long d = 60594869054uwb; // { dg-error "invalid suffix 'uwb' on integer constant" "" { target c++98_only } } - // { dg-error "unable to find numeric literal operator 'operator\"\"uwb'" "" { target c++11 } .-1 } --- a/gcc/testsuite/g++.dg/ext/bitint2.C 2026-11-06 18:32:41.087465629 +0100 +++ b/gcc/testsuite/g++.dg/ext/bitint2.C 2026-11-11 13:16:41.831476601 +0100 @@ -1,10 +0,0 @@ -// PR c/102989 -// { dg-do compile } -// { dg-options "" } - -_BitInt(63) a; // { dg-error "expected" } -unsigned _BitInt(31) b; // { dg-error "expected" } -int c = 21wb; // { dg-error "invalid suffix 'wb' on integer constant" "" { target c++98_only } } - // { dg-error "unable to find numeric literal operator 'operator\"\"wb'" "" { target c++11 } .-1 } -long long d = 60594869054uwb; // { dg-error "invalid suffix 'uwb' on integer constant" "" { target c++98_only } } - // { dg-error "unable to find numeric literal operator 'operator\"\"uwb'" "" { target c++11 } .-1 } --- a/gcc/testsuite/g++.dg/ext/bitint3.C 2026-11-06 18:32:41.087465629 +0100 +++ b/gcc/testsuite/g++.dg/ext/bitint3.C 2026-11-11 13:16:41.831612286 +0100 @@ -1,8 +0,0 @@ -// PR c/102989 -// { dg-do compile { target c++11 } } - -constexpr int operator""wb (unsigned long long) { return 0; } // { dg-warning "reserved for future standardization" } -constexpr int operator""uwb (unsigned long long) { return 1; } // { dg-warning "reserved for future standardization" } - -static_assert (-42wb == 0, ""); -static_assert (81uwb == 1, ""); --- a/gcc/testsuite/g++.dg/ext/bitint4.C 2026-11-06 18:32:41.087465629 +0100 +++ b/gcc/testsuite/g++.dg/ext/bitint4.C 2026-11-11 13:16:41.831718996 +0100 @@ -1,9 +0,0 @@ -// PR c/102989 -// { dg-do compile { target c++11 } } -// { dg-options "" } - -constexpr int operator""wb (unsigned long long) { return 0; } // { dg-warning "reserved for future standardization" } -constexpr int operator""uwb (unsigned long long) { return 1; } // { dg-warning "reserved for future standardization" } - -static_assert (-42wb == 0, ""); -static_assert (81uwb == 1, ""); --- a/gcc/testsuite/g++.dg/cpp29/bitint1.C 2026-11-11 13:16:41.831941083 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint1.C 2026-11-11 13:16:41.831941083 +0100 @@ -0,0 +1,27 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +void +foo (int x) +{ + _BitInt (1) a; + signed _BitInt (1) b; + _BitInt (0) c; // { dg-error "'_BitInt' argument '0' is not a positive integer constant expression" } + unsigned _BitInt (0) d; // { dg-error "'_BitInt' argument '0' is not a positive integer constant expression" } + _BitInt (-42) e; // { dg-error "narrowing conversion of '-42' from 'int' to '\[^'\n\r]*'" } + _BitInt (-5) unsigned f; // { dg-error "narrowing conversion of '-5' from 'int' to '\[^'\n\r]*'" } + _BitInt (4294967295ULL) g; // { dg-error "'_BitInt' argument '4294967295' is larger than 'BITINT_MAXWIDTH' '\[0-9]+'" } + long _BitInt (42) h; // { dg-error "'long' specified with '_BitInt\\\(42\\\)'" } + long long _BitInt (42) i; // { dg-error "'long long' specified with '_BitInt\\\(42\\\)'" } + _BitInt (42) long j; // { dg-error "'long' specified with '_BitInt\\\(42\\\)'" } + _BitInt (42) long long k; // { dg-error "'long long' specified with '_BitInt\\\(42\\\)'" } + short _BitInt (42) l; // { dg-error "'short' specified with '_BitInt\\\(42\\\)'" } + _BitInt (42) short m; // { dg-error "'short' specified with '_BitInt\\\(42\\\)'" } + _Complex _BitInt (42) n; // { dg-error "complex invalid for 'n'" } + _BitInt (42) _Complex o; // { dg-error "complex invalid for 'o'" } + int _BitInt (42) p; // { dg-error "two or more data types in declaration of 'p'" } + _BitInt (42) int q; // { dg-error "two or more data types in declaration of 'q'" } + _BitInt (x) r; // { dg-error "'x' is not a constant expression" } +} // { dg-error "'_BitInt' argument is not an integer constant expression" "" { target *-*-* } .-1 } --- a/gcc/testsuite/g++.dg/cpp29/bitint2.C 2026-11-11 13:16:41.832037162 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint2.C 2026-11-11 13:16:41.832037162 +0100 @@ -0,0 +1,9 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-require-effective-target bitint } + +auto a = 123wb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +auto b = 234uwb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +_BitInt(1) c; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } +unsigned _BitInt(1) d; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } +_BitInt(1) signed e; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } --- a/gcc/testsuite/g++.dg/cpp29/bitint3.C 2026-11-11 13:16:41.832122509 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint3.C 2026-11-11 14:38:50.982574598 +0100 @@ -0,0 +1,10 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile } +// { dg-options "" } +// { dg-require-effective-target bitint } + +int a = 123wb; +unsigned b = 234uwb; +_BitInt(1) c; +unsigned _BitInt(1) d; +_BitInt(1) signed e; --- a/gcc/testsuite/g++.dg/cpp29/bitint4.C 2026-11-11 13:16:41.832201891 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint4.C 2026-11-11 13:16:41.832201891 +0100 @@ -0,0 +1,10 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-pedantic" } +// { dg-require-effective-target bitint } + +auto a = 123wb; // { dg-warning "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +auto b = 234uwb; // { dg-warning "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +_BitInt(1) c; // { dg-warning "'_BitInt' only available with" "" { target c++26_down } } +unsigned _BitInt(1) d; // { dg-warning "'_BitInt' only available with" "" { target c++26_down } } +_BitInt(1) signed e; // { dg-warning "'_BitInt' only available with" "" { target c++26_down } } --- a/gcc/testsuite/g++.dg/cpp29/bitint5.C 2026-11-11 13:16:41.832290516 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint5.C 2026-11-11 13:16:41.832290516 +0100 @@ -0,0 +1,128 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; + +#define expr_has_type(e, t) same_type <decltype (e), t>::value + +#ifdef __BITINT_MAXWIDTH__ +void +foo (void) +{ + _BitInt(42) a = (_BitInt(42)) 1; + _BitInt(42) unsigned b = (unsigned _BitInt(42)) 2; + _BitInt(5) c = (_BitInt(5)) 3; + _BitInt(5) unsigned d = (unsigned _BitInt(5)) 4; + _BitInt(32) e = (_BitInt(32)) 5; + _BitInt(32) unsigned f = (unsigned _BitInt(32)) 6; + constexpr int g = 43; + enum E { F = 44 }; + _BitInt(g) h; + unsigned _BitInt(F) i; + static_assert (expr_has_type (a, signed _BitInt(42)), ""); + static_assert (expr_has_type (a, _BitInt(42)), ""); + static_assert (!expr_has_type (a, unsigned _BitInt(42)), ""); + static_assert (!expr_has_type (b, signed _BitInt(42)), ""); + static_assert (!expr_has_type (b, _BitInt(42)), ""); + static_assert (expr_has_type (b, unsigned _BitInt(42)), ""); + static_assert (expr_has_type (a + b, unsigned _BitInt(42)), ""); + static_assert (expr_has_type (a * b, unsigned _BitInt(42)), ""); + static_assert (expr_has_type (a - b, unsigned _BitInt(42)), ""); + static_assert (expr_has_type (a * a, _BitInt(42)), ""); + static_assert (expr_has_type (a / b, unsigned _BitInt(42)), ""); + static_assert (expr_has_type (c, signed _BitInt(5)), ""); + static_assert (expr_has_type (c, _BitInt(5)), ""); + static_assert (!expr_has_type (c, unsigned _BitInt(5)), ""); + static_assert (!expr_has_type (d, signed _BitInt(5)), ""); + static_assert (!expr_has_type (d, _BitInt(5)), ""); + static_assert (expr_has_type (d, unsigned _BitInt(5)), ""); + static_assert (expr_has_type (c + d, unsigned _BitInt(5)), ""); + static_assert (expr_has_type (c * d, unsigned _BitInt(5)), ""); + static_assert (expr_has_type (c - d, unsigned _BitInt(5)), ""); + static_assert (expr_has_type (c * c, _BitInt(5)), ""); + static_assert (expr_has_type (c / d, unsigned _BitInt(5)), ""); + static_assert (expr_has_type (e, signed _BitInt(32)), ""); + static_assert (expr_has_type (e, _BitInt(32)), ""); + static_assert (!expr_has_type (e, unsigned _BitInt(32)), ""); + static_assert (!expr_has_type (f, signed _BitInt(32)), ""); + static_assert (!expr_has_type (f, _BitInt(32)), ""); + static_assert (expr_has_type (f, unsigned _BitInt(32)), ""); + static_assert (expr_has_type (e + f, unsigned _BitInt(32)), ""); + static_assert (expr_has_type (e * f, unsigned _BitInt(32)), ""); + static_assert (expr_has_type (e - f, unsigned _BitInt(32)), ""); + static_assert (expr_has_type (e * e, _BitInt(32)), ""); + static_assert (expr_has_type (e / f, unsigned _BitInt(32)), ""); +#if __CHAR_BIT__ * __SIZEOF_INT__ == 32 + static_assert (expr_has_type (e + 1, int), ""); + static_assert (expr_has_type (f + 1, unsigned int), ""); + static_assert (expr_has_type (e + 1U, unsigned int), ""); + static_assert (expr_has_type (f + 1U, unsigned int), ""); + static_assert (expr_has_type (1 - e, int), ""); + static_assert (expr_has_type (1 - f, unsigned int), ""); + static_assert (expr_has_type (1U * e, unsigned int), ""); + static_assert (expr_has_type (1U / f, unsigned int), ""); +#endif + static_assert (expr_has_type (0wb, _BitInt(1)), ""); + static_assert (expr_has_type (-1WB, _BitInt(2)), ""); + static_assert (expr_has_type (-1wb - 1wb, _BitInt(2)), ""); + static_assert (expr_has_type (1wb, _BitInt(2)), ""); + static_assert (expr_has_type (2wb, _BitInt(3)), ""); + static_assert (expr_has_type (0wbu, unsigned _BitInt(1)), ""); + static_assert (expr_has_type (-1UWB, unsigned _BitInt(1)), ""); + static_assert (expr_has_type (1uWB, unsigned _BitInt(1)), ""); + static_assert (expr_has_type (2Uwb, unsigned _BitInt(2)), ""); + static_assert (expr_has_type (h, signed _BitInt(43)), ""); + static_assert (expr_has_type (i, unsigned _BitInt(44)), ""); + static_assert (0wb == 0, ""); + static_assert (-1wb == -1, ""); + static_assert (0xffffffffwb == 4294967295wb, ""); + static_assert (0xffffffffwb == 000000000000000000000000000037777777777wb, ""); + static_assert (0x0000000000000000000000000ffffffffwb == 0b00011111111111111111111111111111111wb, ""); +#if __BITINT_MAXWIDTH__ >= 128 + static_assert (expr_has_type (0xffffffffffffffffffffffffffffffffuwb, unsigned _BitInt(128)), ""); + static_assert (0xffffffffffffffffffffffffffffffffuwb == 340282366920938463463374607431768211455uwb, ""); + static_assert (200000000000000000000000000000000000000wb == 0x96769950b50d88f41314448000000000WB, ""); + static_assert (02263551452055206610750114242110000000000000wb == 200000000000000000000000000000000000000wb, ""); +#endif +#if __BITINT_MAXWIDTH__ >= 575 + static_assert (expr_has_type (123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567UWB, unsigned _BitInt(575)), ""); + static_assert (expr_has_type (0x00000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwbu, unsigned _BitInt(575)), ""); + static_assert (expr_has_type (0377777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777uwb, unsigned _BitInt(575)), ""); + static_assert (123665200736552267030251260509823595017565674550605919957031528046448612553265933585158200530621522494798835713008069669675682517153375604983773077550946583958303386074349567uwb == 0x00000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwbu, ""); + static_assert (0377777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777WBU == 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffuWB, ""); + static_assert (100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000uwb == 0X678159610903F7974A7CB3F22F01FA5D9A2CD6039DE4A7A60F713676CE7D7113FF1A499D9BFD0FDCD2999652EB4C7F398DE2A0000000000000000000000000000000000000000000UWB, ""); + static_assert (expr_has_type (-61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb, _BitInt(575)), ""); + static_assert (expr_has_type (0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwb, signed _BitInt(575)), ""); + static_assert (expr_has_type (0177777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777wb, _BitInt(575)), ""); + static_assert (-61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783WB == -0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwb, ""); + static_assert (0177777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777wb / 2wb * 2wb + 1wb == 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffwb, ""); +#endif +#if (0wb != 0) || (0wbU != 0U) || (1wb != 1) || (1uWB != 1u) \ + || (-1wb >= 0) || (-1UWB < 0) || (4294967295uwb != 4294967295U) \ + || 18446744073709551615wbu != 18446744073709551615ULL +#error "" +#endif +} + +void +bar (void) +{ + _BitInt(2) a = (_BitInt(2)) 1; + unsigned _BitInt(1) b = 1uwb; + _BitInt(4) c; + c = 7; + _BitInt(2) d = 1; + _BitInt(5) e = 2wb; + unsigned _BitInt(6) f = 3uwb; +} +#endif + +int +main () +{ +} --- a/gcc/testsuite/g++.dg/cpp29/bitint6.C 2026-11-11 13:16:41.832438752 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint6.C 2026-11-11 13:16:41.832438752 +0100 @@ -0,0 +1,110 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +using size_t = decltype (sizeof 0); +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; +template <class> +struct is_bitint { static constexpr bool value = false; }; +template <size_t N> +struct is_bitint <_BitInt (N)> { static constexpr bool value = true; }; +template <size_t N> +struct is_bitint <unsigned _BitInt (N)> { static constexpr bool value = true; }; + +template <int N> +constexpr int foo (_BitInt (N)) { return N; } +template <size_t N> +constexpr int bar (unsigned _BitInt (N)) { return N; } +template <size_t N> +constexpr int baz (_BitInt (N)) { return -int (N); } +template <size_t N> +constexpr int baz (unsigned _BitInt (N)) { return N; } +#if __cplusplus >= 201703L +template <typename T, T N> +constexpr T qux (_BitInt (N)) { return N; } +#endif +#if __cpp_concepts >= 202002L +template <typename T> +static constexpr bool is_bitintc_v = requires { baz (T ()); }; +#endif + +static_assert (foo (0wb) == 1, ""); +static_assert (foo (1wb) == 2, ""); +static_assert (foo (78262296091114787wb) == 58, ""); +static_assert (bar (0uwb) == 1, ""); +static_assert (bar (1uwb) == 1, ""); +static_assert (bar (2uwb) == 2, ""); +static_assert (bar (78262296091114787uwb) == 57, ""); +static_assert (baz (0wb) == -1, ""); +static_assert (baz (1wb) == -2, ""); +static_assert (baz (78262296091114787wb) == -58, ""); +static_assert (baz (0uwb) == 1, ""); +static_assert (baz (1uwb) == 1, ""); +static_assert (baz (2uwb) == 2, ""); +static_assert (baz (78262296091114787uwb) == 57, ""); +#if __cplusplus >= 201703L +static_assert (same_type <decltype (qux (0wb)), size_t>::value, ""); +static_assert (qux (68796wb) == 18, ""); +#endif +static_assert (foo <42> (0) == 42, ""); +static_assert (bar <42> (0) == 42, ""); +template <size_t N> +struct S { using T = unsigned _BitInt(N); }; +static_assert (same_type <S <42>::T, unsigned _BitInt (42)>::value, ""); +char *p; +static_assert (is_bitint <decltype (0wb)>::value, ""); +static_assert (is_bitint <decltype (0uwb)>::value, ""); +static_assert (is_bitint <decltype (78262296091114787wb)>::value, ""); +static_assert (is_bitint <decltype (78262296091114787uwb)>::value, ""); +static_assert (!is_bitint <decltype (0)>::value, ""); +static_assert (is_bitint <_BitInt (5)>::value, ""); +static_assert (is_bitint <_BitInt (5) unsigned>::value, ""); +static_assert (is_bitint <_BitInt (__BITINT_MAXWIDTH__) signed>::value, ""); +static_assert (is_bitint <unsigned _BitInt (__BITINT_MAXWIDTH__)>::value, ""); +static_assert (!is_bitint <size_t>::value, ""); +static_assert (!is_bitint <decltype (p - p)>::value, ""); +static_assert (!is_bitint <char>::value, ""); +static_assert (!is_bitint <signed char>::value, ""); +static_assert (!is_bitint <unsigned char>::value, ""); +static_assert (!is_bitint <short>::value, ""); +static_assert (!is_bitint <unsigned short>::value, ""); +static_assert (!is_bitint <int>::value, ""); +static_assert (!is_bitint <unsigned int>::value, ""); +static_assert (!is_bitint <long>::value, ""); +static_assert (!is_bitint <unsigned long>::value, ""); +static_assert (!is_bitint <long long>::value, ""); +static_assert (!is_bitint <unsigned long long>::value, ""); +static_assert (!is_bitint <float>::value, ""); +static_assert (!is_bitint <double>::value, ""); +static_assert (!is_bitint <long double>::value, ""); +#if __cpp_concepts >= 202002L +static_assert (is_bitintc_v <decltype (0wb)>); +static_assert (is_bitintc_v <decltype (0uwb)>); +static_assert (is_bitintc_v <decltype (78262296091114787wb)>); +static_assert (is_bitintc_v <decltype (78262296091114787uwb)>); +static_assert (!is_bitintc_v <decltype (0)>); +static_assert (is_bitintc_v <_BitInt (5)>); +static_assert (is_bitintc_v <_BitInt (5) unsigned>); +static_assert (is_bitintc_v <_BitInt (__BITINT_MAXWIDTH__) signed>); +static_assert (is_bitintc_v <unsigned _BitInt (__BITINT_MAXWIDTH__)>); +static_assert (!is_bitintc_v <size_t>); +static_assert (!is_bitintc_v <decltype (p - p)>); +static_assert (!is_bitintc_v <char>); +static_assert (!is_bitintc_v <signed char>); +static_assert (!is_bitintc_v <unsigned char>); +static_assert (!is_bitintc_v <short>); +static_assert (!is_bitintc_v <unsigned short>); +static_assert (!is_bitintc_v <int>); +static_assert (!is_bitintc_v <unsigned int>); +static_assert (!is_bitintc_v <long>); +static_assert (!is_bitintc_v <unsigned long>); +static_assert (!is_bitintc_v <long long>); +static_assert (!is_bitintc_v <unsigned long long>); +static_assert (!is_bitintc_v <float>); +static_assert (!is_bitintc_v <double>); +static_assert (!is_bitintc_v <long double>); +#endif --- a/gcc/testsuite/g++.dg/cpp29/bitint7.C 2026-11-11 13:16:41.832549371 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint7.C 2026-11-11 13:16:41.832549371 +0100 @@ -0,0 +1,24 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +using size_t = decltype (sizeof 0); + +template <int N> +void foo (_BitInt (N)); // { dg-error "'_BitInt' argument '0' is not a positive integer constant expression" } + // { dg-error "'_BitInt' argument '\[0-9]*' is larger than 'BITINT_MAXWIDTH' '\[0-9]*'" "" { target *-*-* } .-1 } +template <size_t N> +void bar (_BitInt (N + 1)); + +void +baz () +{ + foo <0> (0); // { dg-error "no matching function for call to 'foo<0>\\\(int\\\)'" } + foo <1> (0); + foo <__BITINT_MAXWIDTH__> (0); + foo <__BITINT_MAXWIDTH__ + 1> (0); // { dg-error "no matching function for call to 'foo<\\\(\[0-9]* \\\+ 1\\\)>\\\(int\\\)'" } + bar <26> (0); + bar (123456789wb); // { dg-error "no matching function for call to 'bar\\\(_BitInt\\\(28\\\)\\\)'" } + bar <27> (123456789wb); +} --- a/gcc/testsuite/g++.dg/cpp29/bitint8.C 2026-11-11 13:16:41.832638393 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint8.C 2026-11-11 13:16:41.832638393 +0100 @@ -0,0 +1,54 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +using size_t = decltype (sizeof 0); +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; +template <class> +struct is_bitint { static constexpr bool value = false; }; +template <size_t N> +struct is_bitint <_BitInt (N)> { static constexpr bool value = true; }; +template <size_t N> +struct is_bitint <unsigned _BitInt (N)> { static constexpr bool value = true; }; + +enum A { A0 = 0wb, A1 = 1wb, A2 = same_type <decltype (A1), _BitInt(2)>::value + 2wb - 1wb, + A3 = 3wb, A4, A5 = (5wb + same_type <decltype (A4), _BitInt(3)>::value + + same_type <decltype (A4), _BitInt(4)>::value + + is_bitint <decltype (A4)>::value + + same_type <decltype (A4), unsigned _BitInt(3)>::value), + A6 = 6wb, A7, A8 = 8wb - 1 + same_type <decltype (A7), _BitInt(4)>::value } a; +constexpr int intprec = __SIZEOF_INT__ * __CHAR_BIT__; +constexpr int longprec = __SIZEOF_LONG__ * __CHAR_BIT__; +enum B { B0 = 0, B1 = _BitInt (intprec + 1) (1) << (intprec - 1) } b; +enum C { C0 = -1wb, C1 = _BitInt (intprec + 1) (1) << (intprec - 1) } c; +enum D { D0 = 0, D1 = _BitInt (longprec + 1) (1) << (longprec - 1) } d; +enum E : _BitInt(5) { E0 = 0wb, E1 = 15wb, E2 = _BitInt (46) (2), + E3 = same_type <decltype (E2), _BitInt(5)>::value, + E4 = -15wb - 1 } e; +enum F { F0 = E0, F1 = same_type <decltype (F0), _BitInt(5)>::value }; +static_assert (same_type <decltype (+a), int>::value, ""); +static_assert (same_type <decltype (a), A>::value, ""); +static_assert (!same_type <decltype (A0), _BitInt (1)>::value, ""); +static_assert (!same_type <decltype (A0), _BitInt (2)>::value, ""); +static_assert (!is_bitint <decltype (A0)>::value, ""); +static_assert (!is_bitint <decltype (+A0)>::value, ""); +static_assert (A2 == 2, ""); +static_assert (A5 == 5, ""); +static_assert (A8 == 8, ""); +static_assert (same_type <decltype (+b), unsigned>::value, ""); +#if __SIZEOF_INT__ == __SIZEOF_LONG__ +static_assert (same_type <decltype (+c), long long>::value, ""); +static_assert (same_type <decltype (+d), unsigned>::value, ""); +#else +static_assert (same_type <decltype (+c), long>::value, ""); +static_assert (same_type <decltype (+d), unsigned long>::value, ""); +#endif +static_assert (same_type <decltype (+e), _BitInt(5)>::value, ""); +static_assert (E3 == 1, ""); +#if 0 // FIXME - CWG1765 unimplemented +static_assert (F1 == 1, ""); +#endif --- a/gcc/testsuite/g++.dg/cpp29/bitint9.C 2026-11-11 13:16:41.832734044 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint9.C 2026-11-11 13:16:41.832734044 +0100 @@ -0,0 +1,6 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-3.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint10.C 2026-11-11 13:16:41.832830291 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint10.C 2026-11-11 13:16:41.832830291 +0100 @@ -0,0 +1,5 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++29 } } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-4.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint11.C 2026-11-11 13:16:41.832915200 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint11.C 2026-11-11 13:16:41.832915200 +0100 @@ -0,0 +1,6 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-5.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint12.C 2026-11-11 13:16:41.833002195 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint12.C 2026-11-11 13:16:41.833002195 +0100 @@ -0,0 +1,5 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++29 } } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-6.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint13.C 2026-11-11 13:16:41.833083750 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint13.C 2026-11-11 13:16:41.833083750 +0100 @@ -0,0 +1,6 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions -w" } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-12.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint14.C 2026-11-11 13:16:41.833162460 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint14.C 2026-11-11 13:16:41.833162460 +0100 @@ -0,0 +1,11 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target { c++29 && bitint575 } } } +// { dg-options "-pedantic-errors" } + +enum A : _BitInt(15) { A0 = 0, A1 = 1 }; +enum B : unsigned _BitInt(575) { B0 = 0, B1 = 1 }; +enum C { C0 = 459875743wb, C1 = 3298437354uwb }; +enum D { D0 = 61832600368276133515125630254911797508782837275302959978515764023224306276632966792579100265310761247399417856504034834837841258576687802491886538775473291979151693037174783wb, D1 }; +// { dg-error "no integral type can represent all of the enumerator values for 'D'" "" { target *-*-* } .-1 } */ +// { dg-error "overflow in enumeration values" "" { target *-*-* } .-2 } */ +// { dg-warning "unsigned conversion from '_BitInt\\\(575\\\)' to '\[^'\n\r]*' changes value from" "" { target *-*-* } .-3 } */ --- a/gcc/testsuite/g++.dg/cpp29/bitint15.C 2026-11-11 13:16:41.833250685 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint15.C 2026-11-11 13:16:41.833250685 +0100 @@ -0,0 +1,53 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; + +#define expr_has_type(e, t) same_type <decltype (e), t>::value + +struct S1 { char x; char : 0; char y; }; +struct S2 { char x; int : 0; char y; }; +#if __BITINT_MAXWIDTH__ >= 575 +struct S3 { char x; _BitInt(575) : 0; char y; }; +#endif +#if __BITINT_MAXWIDTH__ >= 389 +struct S4 { char x; _BitInt(195) a : 63; _BitInt(282) b : 280; _BitInt(389) c : 23; _BitInt(2) d : 1; char y; }; +#endif +#if __BITINT_MAXWIDTH__ >= 192 +struct S5 { char x; _BitInt(192) a : 191; unsigned _BitInt(192) b : 190; _BitInt(192) c : 189; char y; }; +#endif +struct S6 { _BitInt(2) a : 1; }; +#if __BITINT_MAXWIDTH__ >= 389 +struct S4 s4; +static_assert (expr_has_type (s4.a + 1uwb, _BitInt(195))); +static_assert (expr_has_type (s4.b + 1uwb, _BitInt(282))); +static_assert (expr_has_type (s4.c + 1uwb, _BitInt(389))); +static_assert (expr_has_type (s4.d * 0wb, _BitInt(2))); +#endif +#if __BITINT_MAXWIDTH__ >= 192 +struct S5 s5; +static_assert (expr_has_type (s5.a + 1uwb, _BitInt(192))); +static_assert (expr_has_type (s5.b + 1wb, unsigned _BitInt(192))); +static_assert (expr_has_type (s5.c + 1uwb, _BitInt(192))); +#endif +struct S6 s6; +static_assert (expr_has_type (s6.a + 0wb, _BitInt(2))); +#if defined(__x86_64__) && __LP64__ && __BITINT_MAXWIDTH__ >= 575 +static_assert (sizeof (struct S1) == 2); +static_assert (sizeof (struct S2) == 5); +static_assert (sizeof (struct S3) == 9); +static_assert (sizeof (struct S4) == 48); +static_assert (sizeof (struct S5) == 88); +static_assert (sizeof (struct S6) == 1); +static_assert (alignof (struct S1) == 1); +static_assert (alignof (struct S2) == 1); +static_assert (alignof (struct S3) == 1); +static_assert (alignof (struct S4) == 8); +static_assert (alignof (struct S5) == 8); +static_assert (alignof (struct S6) == 1); +#endif --- a/gcc/testsuite/g++.dg/cpp29/bitint16.C 2026-11-11 13:16:41.833354998 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint16.C 2026-11-11 13:16:41.833354998 +0100 @@ -0,0 +1,22 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; + +#define expr_has_type(e, t) same_type <decltype (e), t>::value + +void +foo (_Complex int ci, _Complex long long cl) +{ + _BitInt(__SIZEOF_INT__ * __CHAR_BIT__ - 1) bi = 0wb; + _BitInt(__SIZEOF_LONG_LONG__ * __CHAR_BIT__ - 1) bl = 0wb; + static_assert (expr_has_type (ci + bi, _Complex int), ""); + static_assert (expr_has_type (cl + bl, _Complex long long), ""); + static_assert (expr_has_type (bi + ci, _Complex int), ""); + static_assert (expr_has_type (bl + cl, _Complex long long), ""); +} --- a/gcc/testsuite/g++.dg/cpp29/bitint17.C 2026-11-11 13:16:41.833442105 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint17.C 2026-11-11 13:16:41.833442105 +0100 @@ -0,0 +1,17 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +void +foo (_Complex int ci, _Complex long long cl) +{ + _BitInt(__SIZEOF_INT__ * __CHAR_BIT__ + 1) bi = 0wb; + ci + bi; /* { dg-message "unsupported" } */ + bi + ci; /* { dg-message "unsupported" } */ +#if __BITINT_MAXWIDTH__ >= 575 + _BitInt(575) bw = 0wb; + cl + bw; /* { dg-message "unsupported" "" { target bitint575 } } */ + bw + cl; /* { dg-message "unsupported" "" { target bitint575 } } */ +#endif +} --- a/gcc/testsuite/g++.dg/cpp29/bitint18.C 2026-11-11 13:16:41.833526023 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint18.C 2026-11-11 13:16:41.833526023 +0100 @@ -0,0 +1,12 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +#define IB __SIZEOF_INT__ * __CHAR_BIT__ +typedef _BitInt(IB) V1 __attribute__((vector_size (sizeof (_BitInt(IB))))); /* { dg-error "invalid vector type for attribute 'vector_size'" } */ +typedef _BitInt(IB) V2 __attribute__((vector_size (8 * sizeof (_BitInt(IB))))); /* { dg-error "invalid vector type for attribute 'vector_size'" } */ +#if __BITINT_MAXWIDTH__ >= 575 +typedef _BitInt(575) V3 __attribute__((vector_size (sizeof (_BitInt(575))))); /* { dg-error "invalid vector type for attribute 'vector_size'" "" { target bitint575 } } */ +typedef _BitInt(575) V3 __attribute__((vector_size (16 * sizeof (_BitInt(575))))); /* { dg-error "invalid vector type for attribute 'vector_size'" "" { target bitint575 } } */ +#endif --- a/gcc/testsuite/g++.dg/cpp29/bitint19.C 2026-11-11 13:16:41.833624475 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint19.C 2026-11-11 13:16:41.833624475 +0100 @@ -0,0 +1,18 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-require-effective-target bitint } + +_BitInt(63) a; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } +signed _BitInt(15) b; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } +unsigned _BitInt(31) c; // { dg-error "'_BitInt' only available with" "" { target c++26_down } } +int d = 21wb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +long long e = 60594869054uwb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +__extension__ _BitInt(63) f; +__extension__ _BitInt(15) g; +__extension__ unsigned _BitInt(31) h; +int i = __extension__ 21wb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +long long j = __extension__ 60594869054uwb; // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +#if 0wb == 0 // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +#endif +#if 0uwb == 0 // { dg-error "'wb' literal suffixes before C\\\+\\\+29 are a GCC extension" "" { target c++26_down } } +#endif --- a/gcc/testsuite/g++.dg/cpp29/bitint20.C 2026-11-11 13:16:41.833711112 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint20.C 2026-11-11 13:16:41.833711112 +0100 @@ -0,0 +1,8 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-add-options ieee } */ + +#include "../../gcc.dg/bitint-28.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint21.C 2026-11-11 13:16:41.833791476 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint21.C 2026-11-11 13:16:41.833791476 +0100 @@ -0,0 +1,8 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-add-options ieee } */ + +#include "../../gcc.dg/bitint-29.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint22.C 2026-11-11 13:16:41.833870879 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint22.C 2026-11-11 13:16:41.833870879 +0100 @@ -0,0 +1,8 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-add-options ieee } */ + +#include "../../gcc.dg/bitint-30.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint23.C 2026-11-11 13:16:41.833960275 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint23.C 2026-11-11 13:16:41.833960275 +0100 @@ -0,0 +1,8 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } +/* { dg-require-effective-target fenv_exceptions } */ +/* { dg-add-options ieee } */ + +#include "../../gcc.dg/bitint-31.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint24.C 2026-11-11 13:16:41.834043270 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint24.C 2026-11-11 13:16:41.834043270 +0100 @@ -0,0 +1,6 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions -funsigned-bitfields -Wno-overflow" } +// { dg-require-effective-target bitint } + +#include "../../gcc.dg/bitint-34.c" --- a/gcc/testsuite/g++.dg/cpp29/bitint25.C 2026-11-11 13:16:41.834125892 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint25.C 2026-11-11 13:16:41.834125892 +0100 @@ -0,0 +1,102 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +#if __BITINT_MAXWIDTH__ >= 156 +struct S156 { unsigned _BitInt(156) a : 135; _BitInt(156) b : 2; }; +struct S156 s1 = { 18071796389618321960417503813958783219759uwb, 0 }; +struct S156 s2 = { 18071796389618321960417503813958783219759uwb, -1 }; +struct T156 { _BitInt(156) a : 2; unsigned _BitInt(156) b : 135; _BitInt(156) c : 2; }; +struct T156 s3 = { -1, 10623570996611319062233232245276988766900uwb, -1 }; +struct T156 s4 = { 0, 10623570996611319062233232245276988766900uwb, 0 }; +#endif +#if __BITINT_MAXWIDTH__ >= 230 +struct U230 { _BitInt(230) a : 140, b : 140, c : 168; unsigned _BitInt(230) d : 135; _BitInt(230) e : 2; }; +struct U230 s5 = { -1, -1, -167793869854583920719725244652254633450201662238868wb, (unsigned _BitInt(135)) -1, -1 }; +struct U230 s6 = { 0, 0, -167793869854583920719725244652254633450201662238868wb, 0, 0 }; +#endif +#if __BITINT_MAXWIDTH__ >= 412 +struct S412 { unsigned _BitInt(412) a : 391; _BitInt(412) b : 2; }; +struct S412 s7 = { 3345867579074605921998363891622879168820794533140203757607077179689806177940265164723139484043689737118576518770430659uwb, 0 }; +struct S412 s8 = { 3345867579074605921998363891622879168820794533140203757607077179689806177940265164723139484043689737118576518770430659uwb, -1 }; +struct T412 { _BitInt(412) a : 2; unsigned _BitInt(412) b : 391; _BitInt(412) c : 2; }; +struct T412 s9 = { -1, 4349534826165161048611343533362431993802129027379695873644854753645283352804798649538744513979417539155427766538864041uwb, -1 }; +struct T412 s10 = { 0, 4349534826165161048611343533362431993802129027379695873644854753645283352804798649538744513979417539155427766538864041uwb, 0 }; +#endif +#if __BITINT_MAXWIDTH__ >= 486 +struct U486 { _BitInt(486) a : 396, b : 396, c : 424; unsigned _BitInt(486) d : 391; _BitInt(486) e : 2; }; +struct U486 s11 = { -1, -1, -13261086392773587186244717277670203234755842300010780483040284280064790949739084884446379147987979627678541509279207301027482398wb, (unsigned _BitInt(391)) -1, -1 }; +struct U486 s12 = { 0, 0, 13261086392773587186244717277670203234755842300010780483040284280064790949739084884446379147987979627678541509279207301027482398wb, 0, 0 }; +#endif + +#if __BITINT_MAXWIDTH__ >= 156 +__attribute__((noipa)) _BitInt(156) +f1 (struct S156 *p) +{ + return p->a; +} + +__attribute__((noipa)) _BitInt(156) +f2 (struct T156 *q) +{ + return q->b; +} +#endif + +#if __BITINT_MAXWIDTH__ >= 230 +__attribute__((noipa)) _BitInt(230) +f3 (struct U230 *q) +{ + return q->c; +} +#endif + +#if __BITINT_MAXWIDTH__ >= 412 +__attribute__((noipa)) _BitInt(412) +f4 (struct S412 *p) +{ + return p->a; +} +#endif + +#if __BITINT_MAXWIDTH__ >= 486 +__attribute__((noipa)) _BitInt(412) +f5 (struct T412 *q) +{ + return q->b; +} + +__attribute__((noipa)) _BitInt(486) +f6 (struct U486 *q) +{ + return q->c; +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 156 + if (f1 (&s1) != 18071796389618321960417503813958783219759wb + || f1 (&s2) != 18071796389618321960417503813958783219759wb + || f2 (&s3) != 10623570996611319062233232245276988766900wb + || f2 (&s4) != 10623570996611319062233232245276988766900wb +#if __BITINT_MAXWIDTH__ >= 230 + || f3 (&s5) != -167793869854583920719725244652254633450201662238868wb + || f3 (&s6) != -167793869854583920719725244652254633450201662238868wb +#if __BITINT_MAXWIDTH__ >= 412 + || f4 (&s7) != 3345867579074605921998363891622879168820794533140203757607077179689806177940265164723139484043689737118576518770430659uwb + || f4 (&s8) != 3345867579074605921998363891622879168820794533140203757607077179689806177940265164723139484043689737118576518770430659uwb + || f5 (&s9) != 4349534826165161048611343533362431993802129027379695873644854753645283352804798649538744513979417539155427766538864041uwb + || f5 (&s10) != 4349534826165161048611343533362431993802129027379695873644854753645283352804798649538744513979417539155427766538864041uwb +#if __BITINT_MAXWIDTH__ >= 486 + || f6 (&s11) != -13261086392773587186244717277670203234755842300010780483040284280064790949739084884446379147987979627678541509279207301027482398wb + || f6 (&s12) != 13261086392773587186244717277670203234755842300010780483040284280064790949739084884446379147987979627678541509279207301027482398wb +#endif +#endif +#endif + || 0) + __builtin_abort (); +#endif +} --- a/gcc/testsuite/g++.dg/cpp29/bitint26.C 2026-11-11 13:16:41.834233294 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint26.C 2026-11-11 13:16:41.834233294 +0100 @@ -0,0 +1,174 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +#if __BITINT_MAXWIDTH__ >= 2048 +struct S { unsigned _BitInt(2048) a : 2048, b : 2048, c : 17, d : 1984, e : 47; }; + +__attribute__((noipa)) void +foo (struct S *p, unsigned _BitInt(1024) x, unsigned _BitInt(1024) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +bar (struct S *p, _BitInt(1024) x, _BitInt(1024) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +baz (struct S *p, unsigned _BitInt(1920) x, unsigned _BitInt(1920) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +qux (struct S *p, _BitInt(1920) x, _BitInt(1920) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +corge (struct S *p, unsigned _BitInt(1900) x, unsigned _BitInt(1900) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +garply (struct S *p, _BitInt(1900) x, _BitInt(1900) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +freddy (struct S *p, unsigned _BitInt(1856) x, unsigned _BitInt(1856) y) +{ + p->d = x + y; +} + +__attribute__((noipa)) void +waldo (struct S *p, _BitInt(1856) x, _BitInt(1856) y) +{ + p->d = x + y; +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 2048 + static struct S a = { + (unsigned _BitInt(2048)) -1, (unsigned _BitInt(2048)) -1, 0, + 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb, + 0 }; + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + foo (&a, 104931473307998568376284944455816272419276290777426540227909077072607565781305910683656824567560123753706639375583615231475830225655977968417978331508801616912246729932071770026909197561252489929164753507156163716727743848177523298403504040861948797263925263359073704810875557925737265337616304489108966376158uwb, + 59920243355458337710161417863366293718453205838526168844643867766614610356796955200643446741760592218738700475637131838188996966576023003439875232851999584726009865342375796439481941924864368246882381830388251975603959739534065212652254710711469239923127731536814696621712112440700123429434845131596418309393uwb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1024)) (104931473307998568376284944455816272419276290777426540227909077072607565781305910683656824567560123753706639375583615231475830225655977968417978331508801616912246729932071770026909197561252489929164753507156163716727743848177523298403504040861948797263925263359073704810875557925737265337616304489108966376158uwb + + 59920243355458337710161417863366293718453205838526168844643867766614610356796955200643446741760592218738700475637131838188996966576023003439875232851999584726009865342375796439481941924864368246882381830388251975603959739534065212652254710711469239923127731536814696621712112440700123429434845131596418309393uwb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = 0; a.e = 0; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + bar (&a, 57696900052508731507403549405758598034300143658103207319023779669222605350088754701899236130746881446668609696540074847952256437939432895408791375123523927312623997545422223335393957708478037810305856074599089747771505132758755976367296302409566647338223622914274236998855494169815473992397952258483243021302wb, + -72842517138334828284807942772540307802590837121353434029836391595120471219334627505967145432766876195584374614127318095866715782180696170716375533225237916165551049842450106822314457638403968810895466326295894575989547864175819099455892706907142084137837126096115084189997686278911334555694779991889737914097wb); + if (a.c != 0 + || a.d != (unsigned _BitInt(1984)) (57696900052508731507403549405758598034300143658103207319023779669222605350088754701899236130746881446668609696540074847952256437939432895408791375123523927312623997545422223335393957708478037810305856074599089747771505132758755976367296302409566647338223622914274236998855494169815473992397952258483243021302wb + - 72842517138334828284807942772540307802590837121353434029836391595120471219334627505967145432766876195584374614127318095866715782180696170716375533225237916165551049842450106822314457638403968810895466326295894575989547864175819099455892706907142084137837126096115084189997686278911334555694779991889737914097wb) + || a.e != 0) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + bar (&a, -57696900052508731507403549405758598034300143658103207319023779669222605350088754701899236130746881446668609696540074847952256437939432895408791375123523927312623997545422223335393957708478037810305856074599089747771505132758755976367296302409566647338223622914274236998855494169815473992397952258483243021302wb, + 72842517138334828284807942772540307802590837121353434029836391595120471219334627505967145432766876195584374614127318095866715782180696170716375533225237916165551049842450106822314457638403968810895466326295894575989547864175819099455892706907142084137837126096115084189997686278911334555694779991889737914097wb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1984)) (-57696900052508731507403549405758598034300143658103207319023779669222605350088754701899236130746881446668609696540074847952256437939432895408791375123523927312623997545422223335393957708478037810305856074599089747771505132758755976367296302409566647338223622914274236998855494169815473992397952258483243021302wb + + 72842517138334828284807942772540307802590837121353434029836391595120471219334627505967145432766876195584374614127318095866715782180696170716375533225237916165551049842450106822314457638403968810895466326295894575989547864175819099455892706907142084137837126096115084189997686278911334555694779991889737914097wb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + baz (&a, 10046674427769604624104256297198144686571499244626667928387309298929376098027029576279399593953275611749179759608292175423884771453122373428446900092238297028886595955833507301142748242755116804512085361142982476735378897659094772516348752033708523603210976749488948779512595019051543682808058468854071972247830133684340816736701518783450117953852153823310129790997309466493287853621568286299778852505115809372004493209067461371542082762075506285274124778581566591915544298148128752861519967454244034597718098760883258950102015993032472578845214796865351706334956028690073732824uwb, + 30612973315144170166058778463435127763223804285434461900113576569307167284342964585999954156672087142162949891238018140546663093988389394093653346239026903138243323723125156926788354976614671206441524235029939884520999076249737807760807371468017378301855151655697275608111727393644387426955142126548487675753916845926686394733479586127697929204917657250622879488360082650822591661695896650131839942739510727482535722456341390110272939230980001298487239399637003898555616301235680415285050104075063794523896618439667653475267312346144285918918555551560640876816454019806981149346uwb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1920)) (10046674427769604624104256297198144686571499244626667928387309298929376098027029576279399593953275611749179759608292175423884771453122373428446900092238297028886595955833507301142748242755116804512085361142982476735378897659094772516348752033708523603210976749488948779512595019051543682808058468854071972247830133684340816736701518783450117953852153823310129790997309466493287853621568286299778852505115809372004493209067461371542082762075506285274124778581566591915544298148128752861519967454244034597718098760883258950102015993032472578845214796865351706334956028690073732824uwb + + 30612973315144170166058778463435127763223804285434461900113576569307167284342964585999954156672087142162949891238018140546663093988389394093653346239026903138243323723125156926788354976614671206441524235029939884520999076249737807760807371468017378301855151655697275608111727393644387426955142126548487675753916845926686394733479586127697929204917657250622879488360082650822591661695896650131839942739510727482535722456341390110272939230980001298487239399637003898555616301235680415285050104075063794523896618439667653475267312346144285918918555551560640876816454019806981149346uwb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = 0; a.e = 0; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + qux (&a, 13016013079173103291099614189980806323842381205278317530930273134000041840366629398775140035115843810473709567772778302693082141789947769432915075175055773162235275161483274294215337459035077170772792870300959580270341613989326562524225424508425190735941052267862958598262374659588227320019762607908610630268016655402141784434304726674259917365365145444188910006023308330624708207712990521956652004155313903306577312390098183139445953080974727140041686581923442658014291404592915933601121276930660194063673671653456001711834226809501680465040298012239797363611423758621282776913wb, + -28446813692377976500941113458061042520266991028095510595278491516213231833343127954947958697833886839482306777092401391414122947073667300047514166155274861575977000665767593771951017640475352507402509527609607984675986413277164234921816991523476344394719439798762757430434241059844235758595109405173122010749636425151730743690113153472777458440898097338588818905573968955113497483813484624809156428527476374283821364764837699711517717561791530220504756111060769224676146577608338385717008304034083639716040512354106392262091939683382939797913585450175899702396573011461697333034wb); + if (a.c != 0 + || a.d != (unsigned _BitInt(1984)) (13016013079173103291099614189980806323842381205278317530930273134000041840366629398775140035115843810473709567772778302693082141789947769432915075175055773162235275161483274294215337459035077170772792870300959580270341613989326562524225424508425190735941052267862958598262374659588227320019762607908610630268016655402141784434304726674259917365365145444188910006023308330624708207712990521956652004155313903306577312390098183139445953080974727140041686581923442658014291404592915933601121276930660194063673671653456001711834226809501680465040298012239797363611423758621282776913wb + - 28446813692377976500941113458061042520266991028095510595278491516213231833343127954947958697833886839482306777092401391414122947073667300047514166155274861575977000665767593771951017640475352507402509527609607984675986413277164234921816991523476344394719439798762757430434241059844235758595109405173122010749636425151730743690113153472777458440898097338588818905573968955113497483813484624809156428527476374283821364764837699711517717561791530220504756111060769224676146577608338385717008304034083639716040512354106392262091939683382939797913585450175899702396573011461697333034wb) + || a.e != 0) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + qux (&a, -13016013079173103291099614189980806323842381205278317530930273134000041840366629398775140035115843810473709567772778302693082141789947769432915075175055773162235275161483274294215337459035077170772792870300959580270341613989326562524225424508425190735941052267862958598262374659588227320019762607908610630268016655402141784434304726674259917365365145444188910006023308330624708207712990521956652004155313903306577312390098183139445953080974727140041686581923442658014291404592915933601121276930660194063673671653456001711834226809501680465040298012239797363611423758621282776913wb, + 28446813692377976500941113458061042520266991028095510595278491516213231833343127954947958697833886839482306777092401391414122947073667300047514166155274861575977000665767593771951017640475352507402509527609607984675986413277164234921816991523476344394719439798762757430434241059844235758595109405173122010749636425151730743690113153472777458440898097338588818905573968955113497483813484624809156428527476374283821364764837699711517717561791530220504756111060769224676146577608338385717008304034083639716040512354106392262091939683382939797913585450175899702396573011461697333034wb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1984)) (-13016013079173103291099614189980806323842381205278317530930273134000041840366629398775140035115843810473709567772778302693082141789947769432915075175055773162235275161483274294215337459035077170772792870300959580270341613989326562524225424508425190735941052267862958598262374659588227320019762607908610630268016655402141784434304726674259917365365145444188910006023308330624708207712990521956652004155313903306577312390098183139445953080974727140041686581923442658014291404592915933601121276930660194063673671653456001711834226809501680465040298012239797363611423758621282776913wb + + 28446813692377976500941113458061042520266991028095510595278491516213231833343127954947958697833886839482306777092401391414122947073667300047514166155274861575977000665767593771951017640475352507402509527609607984675986413277164234921816991523476344394719439798762757430434241059844235758595109405173122010749636425151730743690113153472777458440898097338588818905573968955113497483813484624809156428527476374283821364764837699711517717561791530220504756111060769224676146577608338385717008304034083639716040512354106392262091939683382939797913585450175899702396573011461697333034wb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + corge (&a, 64171754625068989919140837000994640111727112880534508544592426680368730902810558177004927067680584241787685314155807083650755609249723856651964519183899537071234738837290542998681042547778311707239561819724556440611184192044964070498288365795284868545819938858772217225078359446215623326392822749370924397592547178151227397770818626413099911326742674650698762654686406157275035696691347162817031065585247142657560604671730554635740625725423122837711895800895711658181231623745755808749163225238686251279789200140461667130974133295022126714627199940806900473151584805415195uwb, + 10507418314822331271773044775475398971761862686484059883353388622395900044257992245406697831431608445492518374055670273513238951235394317339987011165612885709605626614512380143227176716397144020233730021138060515517588833982427087228530305874044854732163307726421040484981309646463788817170356084893284995027973314236302612849097075836350102359164874937708745757469764621885202447442513857862352391464614086255770773793956362777147243363233935961477956934790795000772957425970578395645388729306937175617548119494347932433902865451670299375626936811709188316328877711066266uwb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1900)) (64171754625068989919140837000994640111727112880534508544592426680368730902810558177004927067680584241787685314155807083650755609249723856651964519183899537071234738837290542998681042547778311707239561819724556440611184192044964070498288365795284868545819938858772217225078359446215623326392822749370924397592547178151227397770818626413099911326742674650698762654686406157275035696691347162817031065585247142657560604671730554635740625725423122837711895800895711658181231623745755808749163225238686251279789200140461667130974133295022126714627199940806900473151584805415195uwb + + 10507418314822331271773044775475398971761862686484059883353388622395900044257992245406697831431608445492518374055670273513238951235394317339987011165612885709605626614512380143227176716397144020233730021138060515517588833982427087228530305874044854732163307726421040484981309646463788817170356084893284995027973314236302612849097075836350102359164874937708745757469764621885202447442513857862352391464614086255770773793956362777147243363233935961477956934790795000772957425970578395645388729306937175617548119494347932433902865451670299375626936811709188316328877711066266uwb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = 0; a.e = 0; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + garply (&a, 5868498364266506524577605439874476245426686973426700959109780040518579902459120222835694740563157202759355683256866704897404738166990697509006899291520655587106188792963812978958796524525114633868734394698171505881029257971723149816101834255875674028498733002531852425394712442344661593840806267795078353686464213122490607069539130187483435521707186417019607510065332996787510980236995794693748424754247983911372699143281367405983607540070016093272958998509389591623580441329207441967951990849359776649279644251163115935521494220792988120247084691082546041345346792010242wb, + -11347197387388289958753680375659873990863802565165926783885510745013060725984194141674849668356803935504502347397858539486502925095461636911844100666788607295568532884580882894109301976999229938210427880195738078809053637249087573583682429867587279531387832617988923148433372488547498087660777174110005800619288934623468273334771375199931835359341800380427942391213375221877238129575165007900737487381149085076124736500637930425093008055570334609463897282935446073021835731133748226290709813024590427968994174853094349555317945926316079817123209552512780636562105208387802wb); + if (a.c != 0 + || a.d != (unsigned _BitInt(1984)) (5868498364266506524577605439874476245426686973426700959109780040518579902459120222835694740563157202759355683256866704897404738166990697509006899291520655587106188792963812978958796524525114633868734394698171505881029257971723149816101834255875674028498733002531852425394712442344661593840806267795078353686464213122490607069539130187483435521707186417019607510065332996787510980236995794693748424754247983911372699143281367405983607540070016093272958998509389591623580441329207441967951990849359776649279644251163115935521494220792988120247084691082546041345346792010242wb + - 11347197387388289958753680375659873990863802565165926783885510745013060725984194141674849668356803935504502347397858539486502925095461636911844100666788607295568532884580882894109301976999229938210427880195738078809053637249087573583682429867587279531387832617988923148433372488547498087660777174110005800619288934623468273334771375199931835359341800380427942391213375221877238129575165007900737487381149085076124736500637930425093008055570334609463897282935446073021835731133748226290709813024590427968994174853094349555317945926316079817123209552512780636562105208387802wb) + || a.e != 0) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + garply (&a, -5868498364266506524577605439874476245426686973426700959109780040518579902459120222835694740563157202759355683256866704897404738166990697509006899291520655587106188792963812978958796524525114633868734394698171505881029257971723149816101834255875674028498733002531852425394712442344661593840806267795078353686464213122490607069539130187483435521707186417019607510065332996787510980236995794693748424754247983911372699143281367405983607540070016093272958998509389591623580441329207441967951990849359776649279644251163115935521494220792988120247084691082546041345346792010242wb, + 11347197387388289958753680375659873990863802565165926783885510745013060725984194141674849668356803935504502347397858539486502925095461636911844100666788607295568532884580882894109301976999229938210427880195738078809053637249087573583682429867587279531387832617988923148433372488547498087660777174110005800619288934623468273334771375199931835359341800380427942391213375221877238129575165007900737487381149085076124736500637930425093008055570334609463897282935446073021835731133748226290709813024590427968994174853094349555317945926316079817123209552512780636562105208387802wb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1984)) (-5868498364266506524577605439874476245426686973426700959109780040518579902459120222835694740563157202759355683256866704897404738166990697509006899291520655587106188792963812978958796524525114633868734394698171505881029257971723149816101834255875674028498733002531852425394712442344661593840806267795078353686464213122490607069539130187483435521707186417019607510065332996787510980236995794693748424754247983911372699143281367405983607540070016093272958998509389591623580441329207441967951990849359776649279644251163115935521494220792988120247084691082546041345346792010242wb + + 11347197387388289958753680375659873990863802565165926783885510745013060725984194141674849668356803935504502347397858539486502925095461636911844100666788607295568532884580882894109301976999229938210427880195738078809053637249087573583682429867587279531387832617988923148433372488547498087660777174110005800619288934623468273334771375199931835359341800380427942391213375221877238129575165007900737487381149085076124736500637930425093008055570334609463897282935446073021835731133748226290709813024590427968994174853094349555317945926316079817123209552512780636562105208387802wb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + freddy (&a, 469252210556625900395321429768118373804271568886989705934619437372829749132450328525095591418777876663202724364753274041797120201435942727547992144282707964490547818365755687730365454828375134854279482853064804665151021915981446605629215712706942096964289300397645214217794960755102650152979365923262599694610536124094997394321315947501858977257060703103733108840085012396782596975471783978125423726167181925777731261440167038194119207611413091278559852866397229440000783332669637577092646062124696818736270717467013532501981408774198349957822434112647379005uwb, + 94070362846521859801705045906377514499678063439381376804210675777018147620560698746550277910632595473262065531986582027530889487288929548537551849350646108895807918918852446632833846575499156686904909401606895792588697611268444788607535104014712049735819470354574164068246431532229132503353457795214808974265484177085433521985873683760061889599206572475727862420333264989214721uwb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1856)) (469252210556625900395321429768118373804271568886989705934619437372829749132450328525095591418777876663202724364753274041797120201435942727547992144282707964490547818365755687730365454828375134854279482853064804665151021915981446605629215712706942096964289300397645214217794960755102650152979365923262599694610536124094997394321315947501858977257060703103733108840085012396782596975471783978125423726167181925777731261440167038194119207611413091278559852866397229440000783332669637577092646062124696818736270717467013532501981408774198349957822434112647379005uwb + + 94070362846521859801705045906377514499678063439381376804210675777018147620560698746550277910632595473262065531986582027530889487288929548537551849350646108895807918918852446632833846575499156686904909401606895792588697611268444788607535104014712049735819470354574164068246431532229132503353457795214808974265484177085433521985873683760061889599206572475727862420333264989214721uwb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); + a.c = 0; a.e = 0; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + waldo (&a, 1077348803036394846628052386931031477092268876025321812336873307109206087913752615224874421161444982772998789879219858386748806555972198085260006113906211122468615028890545260489793232067037450746579377138953792376873515309768581358563731155642172915978701005830989320122620476563103717896150506580888344726125553209010077521592754225575655834325745455132336873236702283266289571810538207635029653566169955010183651423213982024692540900019767542204779117227674016120820660909981982885062591878726323250427606511922288639386683242905759109753373254316490315520wb, + -1985135610193680083664291948423326826338570203155603158942205167041487273165308445801199835862136626921357451386015509681859914819637185970790210070511326605854081763286684508027882510126294034064385106397322907046379158342618996640895074355907730050734884021065120984859890403437402777612953035357875244537844302334232817294878831239344832373356172440988052876809100011735694217824097948414358681171509506376373643145643902181072431032225879081947415698025494088413669737484685311564937312541325716542256136502054579138572508697290597615704140203423671499131wb); + if (a.c != 0 + || a.d != (unsigned _BitInt(1984)) (1077348803036394846628052386931031477092268876025321812336873307109206087913752615224874421161444982772998789879219858386748806555972198085260006113906211122468615028890545260489793232067037450746579377138953792376873515309768581358563731155642172915978701005830989320122620476563103717896150506580888344726125553209010077521592754225575655834325745455132336873236702283266289571810538207635029653566169955010183651423213982024692540900019767542204779117227674016120820660909981982885062591878726323250427606511922288639386683242905759109753373254316490315520wb + - 1985135610193680083664291948423326826338570203155603158942205167041487273165308445801199835862136626921357451386015509681859914819637185970790210070511326605854081763286684508027882510126294034064385106397322907046379158342618996640895074355907730050734884021065120984859890403437402777612953035357875244537844302334232817294878831239344832373356172440988052876809100011735694217824097948414358681171509506376373643145643902181072431032225879081947415698025494088413669737484685311564937312541325716542256136502054579138572508697290597615704140203423671499131wb) + || a.e != 0) + __builtin_abort (); + a.c = (unsigned _BitInt(17)) -1; a.e = (unsigned _BitInt(47)) -1; + a.d = 463917970028583783130221282302564969130016367896792751313667391101541961539304534496983866855440713410002431069759936351630526612549721249569957606098639059197777177066032356317311377246348044640151413769734055367388430457406812743413172658955449268511488689032363320539418931719008983635641503449973939023326362877468919468283037515857633928783609142892025498615118950347461620276675520332352617645525539262850089419854851129987768363578088495582892780293031963532530279743528517338149433293940566560543044220727331056862486476880117725416278405160480429664896200335164399009026428547582688918275uwb; + waldo (&a, -1077348803036394846628052386931031477092268876025321812336873307109206087913752615224874421161444982772998789879219858386748806555972198085260006113906211122468615028890545260489793232067037450746579377138953792376873515309768581358563731155642172915978701005830989320122620476563103717896150506580888344726125553209010077521592754225575655834325745455132336873236702283266289571810538207635029653566169955010183651423213982024692540900019767542204779117227674016120820660909981982885062591878726323250427606511922288639386683242905759109753373254316490315520wb, + 1985135610193680083664291948423326826338570203155603158942205167041487273165308445801199835862136626921357451386015509681859914819637185970790210070511326605854081763286684508027882510126294034064385106397322907046379158342618996640895074355907730050734884021065120984859890403437402777612953035357875244537844302334232817294878831239344832373356172440988052876809100011735694217824097948414358681171509506376373643145643902181072431032225879081947415698025494088413669737484685311564937312541325716542256136502054579138572508697290597615704140203423671499131wb); + if (a.c != (unsigned _BitInt(17)) -1 + || a.d != (unsigned _BitInt(1984)) (-1077348803036394846628052386931031477092268876025321812336873307109206087913752615224874421161444982772998789879219858386748806555972198085260006113906211122468615028890545260489793232067037450746579377138953792376873515309768581358563731155642172915978701005830989320122620476563103717896150506580888344726125553209010077521592754225575655834325745455132336873236702283266289571810538207635029653566169955010183651423213982024692540900019767542204779117227674016120820660909981982885062591878726323250427606511922288639386683242905759109753373254316490315520wb + + 1985135610193680083664291948423326826338570203155603158942205167041487273165308445801199835862136626921357451386015509681859914819637185970790210070511326605854081763286684508027882510126294034064385106397322907046379158342618996640895074355907730050734884021065120984859890403437402777612953035357875244537844302334232817294878831239344832373356172440988052876809100011735694217824097948414358681171509506376373643145643902181072431032225879081947415698025494088413669737484685311564937312541325716542256136502054579138572508697290597615704140203423671499131wb) + || a.e != (unsigned _BitInt(47)) -1) + __builtin_abort (); +#endif +} --- a/gcc/testsuite/g++.dg/cpp29/bitint27.C 2026-11-11 13:16:41.834502872 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint27.C 2026-11-11 13:16:41.834502872 +0100 @@ -0,0 +1,179 @@ +// P3666R5 - Bit-precise integers +// { dg-do run { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <class, class> +struct same_type { static constexpr bool value = false; }; +template <class T> +struct same_type <T, T> { static constexpr bool value = true; }; + +#define expr_has_type(e, t) same_type <decltype (e), t>::value + +void +foo () +{ + _BitInt(1) a = (_BitInt(1)) -1; + static_assert (expr_has_type (a, signed _BitInt(1)), ""); + static_assert (expr_has_type (0wb, _BitInt(1)), ""); + static_assert (expr_has_type (~0wb, _BitInt(1)), ""); + static_assert (expr_has_type (1wb, _BitInt(2)), ""); + static_assert (expr_has_type (-1wb, _BitInt(2)), ""); + static_assert (expr_has_type (2wb, _BitInt(3)), ""); + static_assert (expr_has_type (0wb + 0wb, signed _BitInt(1)), ""); + static_assert (expr_has_type (0wb + 0uwb, unsigned _BitInt(1)), ""); + static_assert (expr_has_type (0wb + 1wb, _BitInt(2)), ""); + static_assert (expr_has_type (0uwb + 0wb, unsigned _BitInt(1)), ""); + static_assert (expr_has_type (1wb + 0wb, _BitInt(2)), ""); + static_assert (0wb == 0, ""); + static_assert (~0wb == -1, ""); + static_assert (~~0wb == 0, ""); + static_assert (-1wb == -1, ""); +} + +_BitInt(1) b = 0wb; +_BitInt(1) c = ~0wb; +_BitInt(1) d = 0wb; + +[[gnu::noipa]] void +bar (_BitInt(1) a[21], signed _BitInt(1) b[21], const _BitInt(1) c[21]) +{ + a[0] = b[0] + c[0]; + a[1] = b[1] + c[1]; + a[2] = b[2] + c[2]; + a[3] = b[3] - c[3]; + a[4] = b[4] - c[4]; + a[5] = b[5] - c[5]; + a[6] = b[6] * c[6]; + a[7] = b[7] * c[7]; + a[8] = b[8] * c[8]; + a[9] = b[9] / c[9]; + a[10] = b[10] % c[10]; + a[11] = b[10] % c[11]; + a[12] = b[12] & c[12]; + a[13] = b[13] & c[13]; + a[14] = b[14] & c[14]; + a[15] = b[15] | c[15]; + a[16] = b[16] | c[16]; + a[17] = b[17] | c[17]; + a[18] = b[18] ^ c[18]; + a[19] = b[19] ^ c[19]; + a[20] = b[20] ^ c[20]; +} + +#if __BITINT_MAXWIDTH__ >= 256 +[[gnu::noipa]] _BitInt(256) +baz (_BitInt(256) x, _BitInt(1) y) +{ + return x * y; +} +#endif + +[[gnu::noipa]] void +qux (_BitInt(1) p[3], float q, double r, long double s) +{ + p[0] = q; + p[1] = r; + p[2] = s; +} + +[[gnu::noipa]] void +corge (_BitInt(1) p[2], float q[2], double r[2], long double s[2]) +{ + q[0] = p[0]; + q[1] = p[1]; + r[0] = p[0]; + r[1] = p[1]; + s[0] = p[0]; + s[1] = p[1]; +} + +int +main () +{ + if (b != 0 || c != -1) + __builtin_abort (); + if (0) + { + --b; + ++c; + } + else + { + b += _BitInt(1)(-1wb); + c -= _BitInt(1)(-1wb); + } + if (b != -1 || c != 0) + __builtin_abort (); + b = ~b; + c = ~c; + if (b != 0 || c != -1) + __builtin_abort (); + c *= d; + if (d != 0) + __builtin_abort (); + _BitInt(1) e[21]; + _BitInt(1) f[21] = { + 0, -1, 0, + 0, -1, -1, + 0, -1, 0, + 0, + 0, -1, + 0, -1, -1, + 0, 0, -1, + 0, -1, -1 + }; + signed _BitInt(1) g[21] = { + 0, 0, -1, + 0, 0, -1, + 0, 0, -1, + -1, + -1, -1, + 0, 0, -1, + 0, -1, -1, + 0, 0, -1 + }; + bar (e, f, g); + _BitInt(1) h[21] = { + 0, -1, -1, + 0, -1, 0, + 0, 0, 0, + 0, + 0, 0, + 0, 0, -1, + 0, -1, -1, + 0, -1, 0 + }; + for (int i = 0; i < 21; ++i) + if (e[i] != h[i]) + __builtin_abort (); +#if __BITINT_MAXWIDTH__ >= 256 + if (baz (24807048826655379640613156875228202584070386120119745959437529938064756141700wb, ~0wb) + != -24807048826655379640613156875228202584070386120119745959437529938064756141700wb) + __builtin_abort (); + if (baz (24807048826655379640613156875228202584070386120119745959437529938064756141700wb, 0wb) != 0wb) + __builtin_abort (); + if (baz (-24807048826655379640613156875228202584070386120119745959437529938064756141700wb, 0wb) != 0wb) + __builtin_abort (); + if (baz (0wb, ~0wb) != 0wb) + __builtin_abort (); +#endif + qux (e, 0.5f, 0.25, 0.75L); + qux (e + 3, -0.5f, -0.25, -0.75L); + qux (e + 6, 0.f, 0., 0.L); + qux (e + 9, -1.f, -1., -1.L); + qux (e + 12, -1.5f, -1.25, -1.75L); + for (int i = 0; i < 15; ++i) + if (e[i] != (i < 9 ? 0 : -1)) + __builtin_abort (); + e[0] = 0wb; + e[1] = ~0wb; + float j[2]; + double k[2]; + long double l[2]; + corge (e, j, k, l); + if (j[0] != 0.0f || j[1] != -1.0f + || k[0] != 0.0 || k[1] != -1.0 + || l[0] != 0.0L || l[1] != -1.0L) + __builtin_abort (); +} --- a/gcc/testsuite/g++.dg/cpp29/bitint28.C 2026-11-11 14:04:05.637614277 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint28.C 2026-11-11 14:04:05.637614277 +0100 @@ -0,0 +1,19 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <int N> struct A { void foo (_BitInt(N)); }; +template <int N> void A <N>::foo (_BitInt(N)) {} // { dg-bogus "no declaration matches" } + +template <int N> struct B { static _BitInt(N) m; }; +template <int N> _BitInt(N) B <N>::m; // { dg-bogus "conflicting declaration" } + +template <int N> void bar (_BitInt(N)); +template <int N> void bar (_BitInt(N)); + +int +main () +{ + bar <5> (0wb); // { dg-bogus "call of overloaded 'bar<5>\\\(_BitInt\\\(1\\\)\\\)' is ambiguous" } +} --- a/gcc/testsuite/g++.dg/cpp29/bitint29.C 2026-11-12 19:11:57.151159474 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint29.C 2026-11-12 19:12:23.695810400 +0100 @@ -0,0 +1,24 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint575 } + +unsigned a[42]; + +unsigned +foo (unsigned _BitInt (532) x) +{ + return a[x]; +} + +unsigned +bar (unsigned *p, unsigned _BitInt (532) x) +{ + return p[x]; +} + +unsigned long long +baz (unsigned long long x, _BitInt (575) y) +{ + return x << y; +} --- a/gcc/testsuite/g++.dg/cpp29/bitint30.C 2026-11-12 20:12:38.301411444 +0100 +++ b/gcc/testsuite/g++.dg/cpp29/bitint30.C 2026-11-12 20:16:42.865179722 +0100 @@ -0,0 +1,20 @@ +// P3666R5 - Bit-precise integers +// { dg-do compile { target c++11 } } +// { dg-options "-Wno-c++29-extensions" } +// { dg-require-effective-target bitint } + +template <typename T> +struct S { static constexpr bool v = false; }; + +template <int N> +struct S <unsigned _BitInt(N)> { static constexpr bool v = true; }; + +template <int N> +constexpr bool +foo () +{ + return S <unsigned _BitInt(42 > N ? 42 : N)>::v; // { dg-bogus "template argument 1 is invalid" } +} + +static_assert (foo <0> (), ""); +static_assert (foo <64> (), ""); --- a/gcc/testsuite/lib/target-supports.exp 2026-11-11 10:28:33.815005690 +0100 +++ b/gcc/testsuite/lib/target-supports.exp 2026-11-11 13:16:41.836191933 +0100 @@ -4721,37 +4721,57 @@ proc check_effective_target_fixed_point # Return 1 if the target supports _BitInt(N), 0 otherwise. proc check_effective_target_bitint { } { + if [check_effective_target_c++] { + set opts "-std=c++29" + } else { + set opts "-std=c23" + } return [check_no_compiler_messages bitint object { _BitInt (2) a = 1wb; unsigned _BitInt (__BITINT_MAXWIDTH__) b = 0uwb; - } "-std=c23"] + } $opts] } # Return 1 if the target supports _BitInt(128), 0 otherwise. proc check_effective_target_bitint128 { } { + if [check_effective_target_c++] { + set opts "-std=c++29" + } else { + set opts "-std=c23" + } return [check_no_compiler_messages bitint128 object { _BitInt (2) a = 1wb; unsigned _BitInt (128) b = 0uwb; - } "-std=c23"] + } $opts] } # Return 1 if the target supports _BitInt(575), 0 otherwise. proc check_effective_target_bitint575 { } { + if [check_effective_target_c++] { + set opts "-std=c++29" + } else { + set opts "-std=c23" + } return [check_no_compiler_messages bitint575 object { _BitInt (2) a = 1wb; unsigned _BitInt (575) b = 0uwb; - } "-std=c23"] + } $opts] } # Return 1 if the target supports _BitInt(65535), 0 otherwise. proc check_effective_target_bitint65535 { } { + if [check_effective_target_c++] { + set opts "-std=c++29" + } else { + set opts "-std=c23" + } return [check_no_compiler_messages bitint65535 object { _BitInt (2) a = 1wb; unsigned _BitInt (65535) b = 0uwb; - } "-std=c23"] + } $opts] } # Return 1 if the target supports compiling decimal floating point, --- a/libcpp/expr.cc 2026-11-06 18:32:41.088465616 +0100 +++ b/libcpp/expr.cc 2026-11-11 14:04:50.046500932 +0100 @@ -386,8 +386,6 @@ interpret_int_suffix (cpp_reader *pfile, if (wb) { - if (CPP_OPTION (pfile, cplusplus)) - return 0; if (l > 0 || i > 0 || z > 0) return 0; } @@ -897,26 +895,37 @@ cpp_classify_number (cpp_reader *pfile, virtual_location, 0, message); } - if ((result & CPP_N_BITINT) != 0 - && CPP_OPTION (pfile, cpp_warn_c11_c23_compat) != 0) + if ((result & CPP_N_BITINT) != 0) { - if (CPP_OPTION (pfile, cpp_warn_c11_c23_compat) > 0) - { - const char *message = N_("ISO C does not support literal " - "%<wb%> suffixes before C23"); - if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, true_false)) - cpp_pedwarning_with_line (pfile, CPP_W_C11_C23_COMPAT, - virtual_location, 0, message); - else - cpp_warning_with_line (pfile, CPP_W_C11_C23_COMPAT, - virtual_location, 0, message); - } - else if (!CPP_OPTION (pfile, true_false)) + if (CPP_OPTION (pfile, cplusplus)) { - const char *message = N_("ISO C does not support literal " - "%<wb%> suffixes before C23"); - cpp_pedwarning_with_line (pfile, CPP_W_PEDANTIC, - virtual_location, 0, message); + if (CPP_OPTION (pfile, lang) < CLK_GNUCXX29 + && CPP_PEDANTIC (pfile)) + cpp_pedwarning_with_line (pfile, CPP_W_CXX29_EXTENSIONS, + virtual_location, 0, + "%<wb%> literal suffixes before " + "C++29 are a GCC extension"); + } + else if (CPP_OPTION (pfile, cpp_warn_c11_c23_compat) != 0) + { + if (CPP_OPTION (pfile, cpp_warn_c11_c23_compat) > 0) + { + const char *message = N_("ISO C does not support literal " + "%<wb%> suffixes before C23"); + if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, true_false)) + cpp_pedwarning_with_line (pfile, CPP_W_C11_C23_COMPAT, + virtual_location, 0, message); + else + cpp_warning_with_line (pfile, CPP_W_C11_C23_COMPAT, + virtual_location, 0, message); + } + else if (!CPP_OPTION (pfile, true_false)) + { + const char *message = N_("ISO C does not support literal " + "%<wb%> suffixes before C23"); + cpp_pedwarning_with_line (pfile, CPP_W_PEDANTIC, + virtual_location, 0, message); + } } } Jakub
