@@ -157,6 +157,11 @@ see the files COPYING3 and COPYING.RUNTI
# undef BOOL_WIDTH
# define BOOL_WIDTH 1
+# ifdef __BITINT_MAXWIDTH__
+# undef BITINT_MAXWIDTH
+# define BITINT_MAXWIDTH __BITINT_MAXWIDTH__
+# endif
+
# define __STDC_VERSION_LIMITS_H__ 202311L
#endif
@@ -349,6 +349,7 @@ const struct c_common_resword c_common_r
{ "_Alignas", RID_ALIGNAS, D_CONLY },
{ "_Alignof", RID_ALIGNOF, D_CONLY },
{ "_Atomic", RID_ATOMIC, D_CONLY },
+ { "_BitInt", RID_BITINT, D_CONLY },
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
@@ -2728,6 +2729,9 @@ c_common_signed_or_unsigned_type (int un
|| TYPE_UNSIGNED (type) == unsignedp)
return type;
+ if (TREE_CODE (type) == BITINT_TYPE)
+ return build_bitint_type (TYPE_PRECISION (type), unsignedp);
+
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
&& TYPE_PRECISION (type) == TYPE_PRECISION (node))
@@ -6341,8 +6345,10 @@ check_builtin_function_arguments (locati
code0 = TREE_CODE (TREE_TYPE (args[0]));
code1 = TREE_CODE (TREE_TYPE (args[1]));
if (!((code0 == REAL_TYPE && code1 == REAL_TYPE)
- || (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
- || (code0 == INTEGER_TYPE && code1 == REAL_TYPE)))
+ || (code0 == REAL_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
+ || ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
+ && code1 == REAL_TYPE)))
{
error_at (loc, "non-floating-point arguments in call to "
"function %qE", fndecl);
@@ -7185,12 +7191,16 @@ speculation_safe_value_resolve_return (t
/* A helper function for resolve_overloaded_builtin in resolving the
overloaded __sync_ builtins. Returns a positive power of 2 if the
first operand of PARAMS is a pointer to a supported data type.
- Returns 0 if an error is encountered.
+ Returns 0 if an error is encountered. Return -1 for _BitInt
+ __atomic*fetch* with unsupported type which should be handled by
+ a cas loop.
FETCH is true when FUNCTION is one of the _FETCH_OP_ or _OP_FETCH_
+ built-ins. ORIG_FORMAT is for __sync_* rather than __atomic_*
built-ins. */
static int
-sync_resolve_size (tree function, vec<tree, va_gc> *params, bool fetch)
+sync_resolve_size (tree function, vec<tree, va_gc> *params, bool fetch,
+ bool orig_format)
{
/* Type of the argument. */
tree argtype;
@@ -7225,9 +7235,19 @@ sync_resolve_size (tree function, vec<tr
goto incompatible;
size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ if (size == 16
+ && fetch
+ && !orig_format
+ && TREE_CODE (type) == BITINT_TYPE
+ && !targetm.scalar_mode_supported_p (TImode))
+ return -1;
+
if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
return size;
+ if (fetch && !orig_format && TREE_CODE (type) == BITINT_TYPE)
+ return -1;
+
incompatible:
/* Issue the diagnostic only if the argument is valid, otherwise
it would be redundant at best and could be misleading. */
@@ -7844,6 +7864,223 @@ resolve_overloaded_atomic_store (locatio
}
+/* Emit __atomic*fetch* on _BitInt which doesn't have a size of
+ 1, 2, 4, 8 or 16 bytes using __atomic_compare_exchange loop.
+ ORIG_CODE is the DECL_FUNCTION_CODE of ORIG_FUNCTION and
+ ORIG_PARAMS arguments of the call. */
+
+static tree
+atomic_bitint_fetch_using_cas_loop (location_t loc,
+ enum built_in_function orig_code,
+ tree orig_function,
+ vec<tree, va_gc> *orig_params)
+{
+ enum tree_code code = ERROR_MARK;
+ bool return_old_p = false;
+ switch (orig_code)
+ {
+ case BUILT_IN_ATOMIC_ADD_FETCH_N:
+ code = PLUS_EXPR;
+ break;
+ case BUILT_IN_ATOMIC_SUB_FETCH_N:
+ code = MINUS_EXPR;
+ break;
+ case BUILT_IN_ATOMIC_AND_FETCH_N:
+ code = BIT_AND_EXPR;
+ break;
+ case BUILT_IN_ATOMIC_NAND_FETCH_N:
+ break;
+ case BUILT_IN_ATOMIC_XOR_FETCH_N:
+ code = BIT_XOR_EXPR;
+ break;
+ case BUILT_IN_ATOMIC_OR_FETCH_N:
+ code = BIT_IOR_EXPR;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_ADD_N:
+ code = PLUS_EXPR;
+ return_old_p = true;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_SUB_N:
+ code = MINUS_EXPR;
+ return_old_p = true;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_AND_N:
+ code = BIT_AND_EXPR;
+ return_old_p = true;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_NAND_N:
+ return_old_p = true;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_XOR_N:
+ code = BIT_XOR_EXPR;
+ return_old_p = true;
+ break;
+ case BUILT_IN_ATOMIC_FETCH_OR_N:
+ code = BIT_IOR_EXPR;
+ return_old_p = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (orig_params->length () != 3)
+ {
+ if (orig_params->length () < 3)
+ error_at (loc, "too few arguments to function %qE", orig_function);
+ else
+ error_at (loc, "too many arguments to function %qE", orig_function);
+ return error_mark_node;
+ }
+
+ tree stmts = push_stmt_list ();
+
+ tree nonatomic_lhs_type = TREE_TYPE (TREE_TYPE ((*orig_params)[0]));
+ nonatomic_lhs_type = TYPE_MAIN_VARIANT (nonatomic_lhs_type);
+ gcc_assert (TREE_CODE (nonatomic_lhs_type) == BITINT_TYPE);
+
+ tree lhs_addr = (*orig_params)[0];
+ tree val = convert (nonatomic_lhs_type, (*orig_params)[1]);
+ tree model = convert (integer_type_node, (*orig_params)[2]);
+ if (TREE_SIDE_EFFECTS (lhs_addr))
+ {
+ tree var = create_tmp_var_raw (TREE_TYPE (lhs_addr));
+ lhs_addr = build4 (TARGET_EXPR, TREE_TYPE (lhs_addr), var, lhs_addr,
+ NULL_TREE, NULL_TREE);
+ add_stmt (lhs_addr);
+ }
+ if (TREE_SIDE_EFFECTS (val))
+ {
+ tree var = create_tmp_var_raw (nonatomic_lhs_type);
+ val = build4 (TARGET_EXPR, nonatomic_lhs_type, var, val, NULL_TREE,
+ NULL_TREE);
+ add_stmt (val);
+ }
+ if (TREE_SIDE_EFFECTS (model))
+ {
+ tree var = create_tmp_var_raw (integer_type_node);
+ model = build4 (TARGET_EXPR, integer_type_node, var, model, NULL_TREE,
+ NULL_TREE);
+ add_stmt (model);
+ }
+
+ tree old = create_tmp_var_raw (nonatomic_lhs_type);
+ tree old_addr = build_unary_op (loc, ADDR_EXPR, old, false);
+ TREE_ADDRESSABLE (old) = 1;
+ suppress_warning (old);
+
+ tree newval = create_tmp_var_raw (nonatomic_lhs_type);
+ tree newval_addr = build_unary_op (loc, ADDR_EXPR, newval, false);
+ TREE_ADDRESSABLE (newval) = 1;
+ suppress_warning (newval);
+
+ tree loop_decl = create_artificial_label (loc);
+ tree loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
+
+ tree done_decl = create_artificial_label (loc);
+ tree done_label = build1 (LABEL_EXPR, void_type_node, done_decl);
+
+ vec<tree, va_gc> *params;
+ vec_alloc (params, 6);
+
+ /* __atomic_load (addr, &old, SEQ_CST). */
+ tree fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
+ params->quick_push (lhs_addr);
+ params->quick_push (old_addr);
+ params->quick_push (build_int_cst (integer_type_node, MEMMODEL_RELAXED));
+ tree func_call = resolve_overloaded_builtin (loc, fndecl, params);
+ if (func_call == NULL_TREE)
+ func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+ old = build4 (TARGET_EXPR, nonatomic_lhs_type, old, func_call, NULL_TREE,
+ NULL_TREE);
+ add_stmt (old);
+ params->truncate (0);
+
+ /* loop: */
+ add_stmt (loop_label);
+
+ /* newval = old + val; */
+ tree rhs;
+ switch (code)
+ {
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ if (!TYPE_OVERFLOW_WRAPS (nonatomic_lhs_type))
+ {
+ tree utype
+ = build_bitint_type (TYPE_PRECISION (nonatomic_lhs_type), 1);
+ rhs = convert (nonatomic_lhs_type,
+ build2_loc (loc, code, utype,
+ convert (utype, old),
+ convert (utype, val)));
+ }
+ else
+ rhs = build2_loc (loc, code, nonatomic_lhs_type, old, val);
+ break;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ rhs = build2_loc (loc, code, nonatomic_lhs_type, old, val);
+ break;
+ case ERROR_MARK:
+ rhs = build2_loc (loc, BIT_AND_EXPR, nonatomic_lhs_type,
+ build1_loc (loc, BIT_NOT_EXPR,
+ nonatomic_lhs_type, old), val);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, rhs, NULL_TREE,
+ NULL_TREE);
+ SET_EXPR_LOCATION (rhs, loc);
+ add_stmt (rhs);
+
+ /* if (__atomic_compare_exchange (addr, &old, &new, false, model, model))
+ goto done; */
+ fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_COMPARE_EXCHANGE);
+ params->quick_push (lhs_addr);
+ params->quick_push (old_addr);
+ params->quick_push (newval_addr);
+ params->quick_push (integer_zero_node);
+ params->quick_push (model);
+ if (tree_fits_uhwi_p (model)
+ && (tree_to_uhwi (model) == MEMMODEL_RELEASE
+ || tree_to_uhwi (model) == MEMMODEL_ACQ_REL))
+ params->quick_push (build_int_cst (integer_type_node, MEMMODEL_RELAXED));
+ else
+ params->quick_push (model);
+ func_call = resolve_overloaded_builtin (loc, fndecl, params);
+ if (func_call == NULL_TREE)
+ func_call = build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+
+ tree goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
+ SET_EXPR_LOCATION (goto_stmt, loc);
+
+ tree stmt
+ = build3 (COND_EXPR, void_type_node, func_call, goto_stmt, NULL_TREE);
+ SET_EXPR_LOCATION (stmt, loc);
+ add_stmt (stmt);
+
+ /* goto loop; */
+ goto_stmt = build1 (GOTO_EXPR, void_type_node, loop_decl);
+ SET_EXPR_LOCATION (goto_stmt, loc);
+ add_stmt (goto_stmt);
+
+ /* done: */
+ add_stmt (done_label);
+
+ tree ret = create_tmp_var_raw (nonatomic_lhs_type);
+ stmt = build2_loc (loc, MODIFY_EXPR, void_type_node, ret,
+ return_old_p ? old : newval);
+ add_stmt (stmt);
+
+ /* Finish the compound statement. */
+ stmts = pop_stmt_list (stmts);
+
+ return build4 (TARGET_EXPR, nonatomic_lhs_type, ret, stmts, NULL_TREE,
+ NULL_TREE);
+}
+
+
/* Some builtin functions are placeholders for other expressions. This
function should be called immediately after parsing the call expression
before surrounding code has committed to the type of the expression.
@@ -8025,19 +8262,22 @@ resolve_overloaded_builtin (location_t l
/* The following are not _FETCH_OPs and must be accepted with
pointers to _Bool (or C++ bool). */
if (fetch_op)
- fetch_op =
- (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
- && orig_code != BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
- && orig_code != BUILT_IN_SYNC_LOCK_TEST_AND_SET_N
- && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N);
+ fetch_op = (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
+ && orig_code != BUILT_IN_SYNC_LOCK_TEST_AND_SET_N
+ && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N);
- int n = sync_resolve_size (function, params, fetch_op);
+ int n = sync_resolve_size (function, params, fetch_op, orig_format);
tree new_function, first_param, result;
enum built_in_function fncode;
if (n == 0)
return error_mark_node;
+ if (n == -1)
+ return atomic_bitint_fetch_using_cas_loop (loc, orig_code,
+ function, params);
+
fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
new_function = builtin_decl_explicit (fncode);
if (!sync_resolve_params (loc, function, new_function, params,
@@ -8402,6 +8642,7 @@ keyword_begins_type_specifier (enum rid
case RID_FRACT:
case RID_ACCUM:
case RID_BOOL:
+ case RID_BITINT:
case RID_WCHAR:
case RID_CHAR8:
case RID_CHAR16:
@@ -101,7 +101,7 @@ enum rid
RID_ENUM, RID_STRUCT, RID_UNION, RID_IF, RID_ELSE,
RID_WHILE, RID_DO, RID_FOR, RID_SWITCH, RID_CASE,
RID_DEFAULT, RID_BREAK, RID_CONTINUE, RID_RETURN, RID_GOTO,
- RID_SIZEOF,
+ RID_SIZEOF, RID_BITINT,
/* C extensions */
RID_ASM, RID_TYPEOF, RID_TYPEOF_UNQUAL, RID_ALIGNOF, RID_ATTRIBUTE,
@@ -1190,6 +1190,29 @@ 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))
+ {
+ 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__");
+ }
+ }
+ }
+
if (c_dialect_cxx ())
for (i = 0; i < NUM_INT_N_ENTS; i ++)
if (int_n_enabled_p[i])
@@ -837,6 +837,170 @@ interpret_integer (const cpp_token *toke
*overflow = OT_NONE;
+ if (UNLIKELY (flags & CPP_N_BITINT))
+ {
+ unsigned int suffix_len = 2 + ((flags & CPP_N_UNSIGNED) ? 1 : 0);
+ int max_bits_per_digit = 4; // ceil (log2 (10))
+ unsigned int prefix_len = 0;
+ bool hex = false;
+ const int bitint_maxwidth = WIDE_INT_MAX_PRECISION - 1;
+ if ((flags & CPP_N_RADIX) == CPP_N_OCTAL)
+ {
+ max_bits_per_digit = 3;
+ prefix_len = 1;
+ }
+ else if ((flags & CPP_N_RADIX) == CPP_N_HEX)
+ {
+ max_bits_per_digit = 4;
+ prefix_len = 2;
+ hex = true;
+ }
+ else if ((flags & CPP_N_RADIX) == CPP_N_BINARY)
+ {
+ max_bits_per_digit = 1;
+ prefix_len = 2;
+ }
+ int max_digits
+ = TYPE_PRECISION (intmax_type_node) >> max_bits_per_digit;
+ const int max_buf = 128;
+ if (max_digits > max_buf)
+ max_digits = max_buf;
+
+ widest_int wval;
+ unsigned int prec;
+ gcc_checking_assert (token->val.str.len > prefix_len + suffix_len
+ || token->val.str.len == 1 + suffix_len);
+ if (token->val.str.len - (prefix_len + suffix_len)
+ <= (unsigned) max_digits)
+ {
+ integer = cpp_interpret_integer (parse_in, token,
+ (flags & CPP_N_RADIX)
+ | CPP_N_UNSIGNED);
+ ival[0] = integer.low;
+ ival[1] = integer.high;
+ ival[2] = 0;
+ wval = widest_int::from_array (ival, 3);
+ }
+ else
+ {
+ unsigned char buf[3 + max_buf];
+ memcpy (buf, token->val.str.text, prefix_len);
+ wval = 0U;
+ const unsigned char *p = token->val.str.text + prefix_len;
+ cpp_token tok = *token;
+ tok.val.str.text = buf;
+ if (!prefix_len)
+ max_digits = 19;
+ do
+ {
+ unsigned char *q = buf + prefix_len;
+ do
+ {
+ unsigned char c = *p++;
+ if (ISDIGIT (c) || (hex && ISXDIGIT (c)))
+ {
+ *q++ = c;
+ if (q == buf + prefix_len + max_digits)
+ break;
+ }
+ else if (c != '\'')
+ {
+ --p;
+ break;
+ }
+ }
+ while (1);
+ if (q == buf + prefix_len)
+ break;
+ else
+ {
+ wi::overflow_type wioverflow;
+ *q = '\0';
+ tok.val.str.len = q - buf;
+ if (wval == 0)
+ ;
+ else if (prefix_len)
+ {
+ prec = wi::min_precision (wval, UNSIGNED);
+ unsigned HOST_WIDE_INT shift
+ = (tok.val.str.len - prefix_len) * max_bits_per_digit;
+ if (prec + shift > bitint_maxwidth)
+ goto bitint_overflow;
+ wval = wi::lshift (wval, shift);
+ }
+ else
+ {
+ static unsigned HOST_WIDE_INT tens[]
+ = { 1U, 10U, 100U, 1000U,
+ HOST_WIDE_INT_UC (10000),
+ HOST_WIDE_INT_UC (100000),
+ HOST_WIDE_INT_UC (1000000),
+ HOST_WIDE_INT_UC (10000000),
+ HOST_WIDE_INT_UC (100000000),
+ HOST_WIDE_INT_UC (1000000000),
+ HOST_WIDE_INT_UC (10000000000),
+ HOST_WIDE_INT_UC (100000000000),
+ HOST_WIDE_INT_UC (1000000000000),
+ HOST_WIDE_INT_UC (10000000000000),
+ HOST_WIDE_INT_UC (100000000000000),
+ HOST_WIDE_INT_UC (1000000000000000),
+ HOST_WIDE_INT_UC (10000000000000000),
+ HOST_WIDE_INT_UC (100000000000000000),
+ HOST_WIDE_INT_UC (1000000000000000000),
+ HOST_WIDE_INT_UC (10000000000000000000) };
+ widest_int ten = tens[q - buf];
+ wval = wi::umul (wval, ten, &wioverflow);
+ if (wioverflow)
+ goto bitint_overflow;
+ }
+ integer = cpp_interpret_integer (parse_in, &tok,
+ (flags & CPP_N_RADIX)
+ | CPP_N_UNSIGNED);
+ ival[0] = integer.low;
+ ival[1] = integer.high;
+ ival[2] = 0;
+ if (prefix_len)
+ wval = wval + widest_int::from_array (ival, 3);
+ else
+ {
+ widest_int addend = widest_int::from_array (ival, 3);
+ wval = wi::add (wval, addend, UNSIGNED, &wioverflow);
+ if (wioverflow)
+ goto bitint_overflow;
+ }
+ }
+ }
+ while (1);
+ }
+
+ prec = wi::min_precision (wval, UNSIGNED);
+ if (prec == 0)
+ prec = 1;
+ if ((flags & CPP_N_UNSIGNED) == 0)
+ ++prec;
+ if (prec > bitint_maxwidth)
+ {
+ bitint_overflow:
+ if ((flags & CPP_N_UNSIGNED) != 0)
+ error ("integer constant is too large for "
+ "%<unsigned _BitInt(%d)%> type", bitint_maxwidth);
+ else
+ error ("integer constant is too large for "
+ "%<_BitInt(%d)%> type", bitint_maxwidth);
+ return integer_zero_node;
+ }
+
+ struct bitint_info info;
+ if (!targetm.c.bitint_type_info (prec, &info))
+ {
+ sorry ("%<_BitInt(%d)%> is not supported on this target", prec);
+ return integer_zero_node;
+ }
+
+ type = build_bitint_type (prec, (flags & CPP_N_UNSIGNED) != 0);
+ return wide_int_to_tree (type, wval);
+ }
+
integer = cpp_interpret_integer (parse_in, token, flags);
if (integer.overflow)
*overflow = OT_OVERFLOW;
@@ -399,6 +399,23 @@ c_pretty_printer::simple_type_specifier
}
break;
+ case BITINT_TYPE:
+ if (TYPE_NAME (t))
+ {
+ t = TYPE_NAME (t);
+ simple_type_specifier (t);
+ }
+ else
+ {
+ int prec = TYPE_PRECISION (t);
+ if (TYPE_UNSIGNED (t))
+ pp_c_ws_string (this, "unsigned");
+ pp_c_ws_string (this, "_BitInt(");;
+ pp_decimal_int (this, prec);
+ pp_right_paren (this);
+ }
+ break;
+
case TYPE_DECL:
if (DECL_NAME (t))
id_expression (t);
@@ -688,6 +705,7 @@ c_pretty_printer::direct_abstract_declar
case REAL_TYPE:
case FIXED_POINT_TYPE:
case ENUMERAL_TYPE:
+ case BITINT_TYPE:
case RECORD_TYPE:
case UNION_TYPE:
case VECTOR_TYPE:
@@ -1019,8 +1037,18 @@ pp_c_integer_constant (c_pretty_printer
pp_minus (pp);
wi = -wi;
}
- print_hex (wi, pp_buffer (pp)->digit_buffer);
- pp_string (pp, pp_buffer (pp)->digit_buffer);
+ unsigned int prec = wi.get_precision ();
+ if ((prec + 3) / 4 > sizeof (pp_buffer (pp)->digit_buffer) - 3)
+ {
+ char *buf = XALLOCAVEC (char, (prec + 3) / 4 + 3);
+ print_hex (wi, buf);
+ pp_string (pp, buf);
+ }
+ else
+ {
+ print_hex (wi, pp_buffer (pp)->digit_buffer);
+ pp_string (pp, pp_buffer (pp)->digit_buffer);
+ }
}
}
@@ -117,6 +117,7 @@ c_convert (tree type, tree expr, bool in
gcc_fallthrough ();
case INTEGER_TYPE:
+ case BITINT_TYPE:
if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
&& current_function_decl != NULL_TREE
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (expr))
@@ -6390,7 +6390,8 @@ check_bitfield_type_and_width (location_
/* Detect invalid bit-field type. */
if (TREE_CODE (*type) != INTEGER_TYPE
&& TREE_CODE (*type) != BOOLEAN_TYPE
- && TREE_CODE (*type) != ENUMERAL_TYPE)
+ && TREE_CODE (*type) != ENUMERAL_TYPE
+ && TREE_CODE (*type) != BITINT_TYPE)
{
error_at (loc, "bit-field %qs has invalid type", name);
*type = unsigned_type_node;
@@ -9330,8 +9331,14 @@ finish_struct (location_t loc, tree t, t
tree type = TREE_TYPE (field);
if (width != TYPE_PRECISION (type))
{
- TREE_TYPE (field)
- = c_build_bitfield_integer_type (width, TYPE_UNSIGNED (type));
+ if (TREE_CODE (type) == BITINT_TYPE
+ && (width > 1 || TYPE_UNSIGNED (type)))
+ TREE_TYPE (field)
+ = build_bitint_type (width, TYPE_UNSIGNED (type));
+ else
+ TREE_TYPE (field)
+ = c_build_bitfield_integer_type (width,
+ TYPE_UNSIGNED (type));
SET_DECL_MODE (field, TYPE_MODE (TREE_TYPE (field)));
}
DECL_INITIAL (field) = NULL_TREE;
@@ -11546,14 +11553,18 @@ declspecs_add_type (location_t loc, stru
("both %<long%> and %<void%> in "
"declaration specifiers"));
else if (specs->typespec_word == cts_int_n)
- error_at (loc,
- ("both %<long%> and %<__int%d%> in "
- "declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
+ error_at (loc,
+ ("both %<long%> and %<__int%d%> in "
+ "declaration specifiers"),
+ int_n_data[specs->u.int_n_idx].bitsize);
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<long%> and %<_Bool%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_bitint)
+ error_at (loc,
+ ("both %<long%> and %<_BitInt%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
error_at (loc,
("both %<long%> and %<char%> in "
@@ -11566,8 +11577,8 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<long%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->typespec_word == cts_dfloat32)
@@ -11606,11 +11617,15 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<short%> and %<__int%d%> in "
"declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
else if (specs->typespec_word == cts_bool)
error_at (loc,
("both %<short%> and %<_Bool%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_bitint)
+ error_at (loc,
+ ("both %<short%> and %<_BitInt%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
error_at (loc,
("both %<short%> and %<char%> in "
@@ -11627,8 +11642,8 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<short%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->typespec_word == cts_dfloat32)
@@ -11679,8 +11694,8 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<signed%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->typespec_word == cts_dfloat32)
@@ -11731,8 +11746,8 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<unsigned%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->typespec_word == cts_dfloat32)
@@ -11770,6 +11785,10 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<complex%> and %<_Bool%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_bitint)
+ error_at (loc,
+ ("both %<complex%> and %<_BitInt%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<complex%> and %<_Decimal32%> in "
@@ -11809,7 +11828,7 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<_Sat%> and %<__int%d%> in "
"declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
}
else if (specs->typespec_word == cts_auto_type)
error_at (loc,
@@ -11823,6 +11842,10 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<_Sat%> and %<_Bool%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_bitint)
+ error_at (loc,
+ ("both %<_Sat%> and %<_BitInt%> in "
+ "declaration specifiers"));
else if (specs->typespec_word == cts_char)
error_at (loc,
("both %<_Sat%> and %<char%> in "
@@ -11843,8 +11866,8 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<_Sat%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->typespec_word == cts_dfloat32)
@@ -11882,7 +11905,7 @@ declspecs_add_type (location_t loc, stru
{
/* "void", "_Bool", "char", "int", "float", "double",
"_FloatN", "_FloatNx", "_Decimal32", "__intN",
- "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ "_Decimal64", "_Decimal128", "_Fract", "_Accum", "_BitInt(N)" or
"__auto_type". */
if (specs->typespec_word != cts_none)
{
@@ -11927,7 +11950,7 @@ declspecs_add_type (location_t loc, stru
case RID_INT_N_1:
case RID_INT_N_2:
case RID_INT_N_3:
- specs->int_n_idx = i - RID_INT_N_0;
+ specs->u.int_n_idx = i - RID_INT_N_0;
if (!in_system_header_at (input_location)
/* If the INT_N type ends in "__", and so is of the format
"__intN__", don't pedwarn. */
@@ -11935,29 +11958,29 @@ declspecs_add_type (location_t loc, stru
+ (IDENTIFIER_LENGTH (type) - 2), "__", 2) != 0))
pedwarn (loc, OPT_Wpedantic,
"ISO C does not support %<__int%d%> types",
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
if (specs->long_p)
error_at (loc,
("both %<__int%d%> and %<long%> in "
"declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
else if (specs->saturating_p)
error_at (loc,
("both %<_Sat%> and %<__int%d%> in "
"declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
else if (specs->short_p)
error_at (loc,
("both %<__int%d%> and %<short%> in "
"declaration specifiers"),
- int_n_data[specs->int_n_idx].bitsize);
- else if (! int_n_enabled_p[specs->int_n_idx])
+ int_n_data[specs->u.int_n_idx].bitsize);
+ else if (! int_n_enabled_p[specs->u.int_n_idx])
{
specs->typespec_word = cts_int_n;
error_at (loc,
"%<__int%d%> is not supported on this target",
- int_n_data[specs->int_n_idx].bitsize);
+ int_n_data[specs->u.int_n_idx].bitsize);
}
else
{
@@ -12115,12 +12138,12 @@ declspecs_add_type (location_t loc, stru
}
return specs;
CASE_RID_FLOATN_NX:
- specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
+ specs->u.floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
if (!in_system_header_at (input_location))
pedwarn (loc, OPT_Wpedantic,
"ISO C does not support the %<_Float%d%s%> type",
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
@@ -12128,49 +12151,49 @@ declspecs_add_type (location_t loc, stru
error_at (loc,
("both %<long%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->short_p)
error_at (loc,
("both %<short%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->signed_p)
error_at (loc,
("both %<signed%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->unsigned_p)
error_at (loc,
("both %<unsigned%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
else if (specs->saturating_p)
error_at (loc,
("both %<_Sat%> and %<_Float%d%s%> in "
"declaration specifiers"),
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
- else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ else if (FLOATN_NX_TYPE_NODE (specs->u.floatn_nx_idx) == NULL_TREE)
{
specs->typespec_word = cts_floatn_nx;
error_at (loc,
"%<_Float%d%s%> is not supported on this target",
- floatn_nx_types[specs->floatn_nx_idx].n,
- (floatn_nx_types[specs->floatn_nx_idx].extended
+ floatn_nx_types[specs->u.floatn_nx_idx].n,
+ (floatn_nx_types[specs->u.floatn_nx_idx].extended
? "x"
: ""));
}
@@ -12267,6 +12290,63 @@ declspecs_add_type (location_t loc, stru
pedwarn (loc, OPT_Wpedantic,
"ISO C does not support fixed-point types");
return specs;
+ case RID_BITINT:
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<_BitInt%> in "
+ "declaration specifiers"));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<_BitInt%> in "
+ "declaration specifiers"));
+ else if (specs->complex_p)
+ error_at (loc,
+ ("both %<complex%> and %<_BitInt%> in "
+ "declaration specifiers"));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<_BitInt%> in "
+ "declaration specifiers"));
+ else
+ {
+ specs->typespec_word = cts_bitint;
+ specs->locations[cdw_typespec] = loc;
+ specs->u.bitint_prec = -1;
+ if (error_operand_p (spec.expr))
+ return specs;
+ if (TREE_CODE (spec.expr) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (spec.expr)))
+ {
+ error_at (loc, "%<_BitInt%> argument is not an integer "
+ "constant expression");
+ return specs;
+ }
+ if (tree_int_cst_sgn (spec.expr) <= 0)
+ {
+ error_at (loc, "%<_BitInt%> argument %qE is not "
+ "positive integer constant expression",
+ spec.expr);
+ return specs;
+ }
+ if (wi::to_widest (spec.expr) > WIDE_INT_MAX_PRECISION - 1)
+ {
+ error_at (loc, "%<_BitInt%> argument %qE is larger than "
+ "%<BITINT_MAXWIDTH%> %qd",
+ spec.expr, (int) WIDE_INT_MAX_PRECISION - 1);
+ return specs;
+ }
+ specs->u.bitint_prec = tree_to_uhwi (spec.expr);
+ struct bitint_info info;
+ if (!targetm.c.bitint_type_info (specs->u.bitint_prec,
+ &info))
+ {
+ sorry_at (loc, "%<_BitInt(%d)%> is not supported on "
+ "this target", specs->u.bitint_prec);
+ specs->u.bitint_prec = -1;
+ return specs;
+ }
+ }
+ return specs;
default:
/* ObjC reserved word "id", handled below. */
break;
@@ -12668,12 +12748,12 @@ finish_declspecs (struct c_declspecs *sp
case cts_int_n:
gcc_assert (!specs->long_p && !specs->short_p && !specs->long_long_p);
gcc_assert (!(specs->signed_p && specs->unsigned_p));
- if (! int_n_enabled_p[specs->int_n_idx])
+ if (! int_n_enabled_p[specs->u.int_n_idx])
specs->type = integer_type_node;
else
specs->type = (specs->unsigned_p
- ? int_n_trees[specs->int_n_idx].unsigned_type
- : int_n_trees[specs->int_n_idx].signed_type);
+ ? int_n_trees[specs->u.int_n_idx].unsigned_type
+ : int_n_trees[specs->u.int_n_idx].signed_type);
if (specs->complex_p)
{
pedwarn (specs->locations[cdw_complex], OPT_Wpedantic,
@@ -12733,12 +12813,12 @@ finish_declspecs (struct c_declspecs *sp
case cts_floatn_nx:
gcc_assert (!specs->long_p && !specs->short_p
&& !specs->signed_p && !specs->unsigned_p);
- if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ if (FLOATN_NX_TYPE_NODE (specs->u.floatn_nx_idx) == NULL_TREE)
specs->type = integer_type_node;
else if (specs->complex_p)
- specs->type = COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ specs->type = COMPLEX_FLOATN_NX_TYPE_NODE (specs->u.floatn_nx_idx);
else
- specs->type = FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx);
+ specs->type = FLOATN_NX_TYPE_NODE (specs->u.floatn_nx_idx);
break;
case cts_dfloat32:
case cts_dfloat64:
@@ -12840,6 +12920,22 @@ finish_declspecs (struct c_declspecs *sp
: accum_type_node;
}
break;
+ case cts_bitint:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->complex_p);
+ if (!specs->unsigned_p && specs->u.bitint_prec == 1)
+ {
+ error_at (specs->locations[cdw_typespec],
+ "%<signed _BitInt%> argument must be at least 2");
+ specs->type = integer_type_node;
+ break;
+ }
+ if (specs->u.bitint_prec == -1)
+ specs->type = integer_type_node;
+ else
+ specs->type = build_bitint_type (specs->u.bitint_prec,
+ specs->unsigned_p);
+ break;
default:
gcc_unreachable ();
}
@@ -580,6 +580,7 @@ c_keyword_starts_typename (enum rid keyw
case RID_DFLOAT128:
CASE_RID_FLOATN_NX:
case RID_BOOL:
+ case RID_BITINT:
case RID_ENUM:
case RID_STRUCT:
case RID_UNION:
@@ -783,6 +784,7 @@ c_token_starts_declspecs (c_token *token
case RID_DFLOAT128:
CASE_RID_FLOATN_NX:
case RID_BOOL:
+ case RID_BITINT:
case RID_ENUM:
case RID_STRUCT:
case RID_UNION:
@@ -3358,6 +3360,30 @@ c_parser_declspecs (c_parser *parser, st
t = c_parser_typeof_specifier (parser);
declspecs_add_type (loc, specs, t);
break;
+ case RID_BITINT:
+ if (!typespec_ok)
+ goto out;
+ else
+ {
+ attrs_ok = true;
+ seen_type = true;
+ t.kind = ctsk_resword;
+ t.spec = c_parser_peek_token (parser)->value;
+ t.expr = error_mark_node;
+ t.expr_const_operands = true;
+ t.has_enum_type_specifier = false;
+ c_parser_consume_token (parser);
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ t.expr = convert_lvalue_to_rvalue (loc, expr, true,
+ true).value;
+ parens.skip_until_found_close (parser);
+ }
+ declspecs_add_type (loc, specs, t);
+ }
+ break;
case RID_ATOMIC:
/* C parser handling of Objective-C constructs needs
checking for correct lvalue-to-rvalue conversions, and
@@ -5005,6 +5031,7 @@ c_parser_gnu_attribute_any_word (c_parse
case RID_DFLOAT128:
CASE_RID_FLOATN_NX:
case RID_BOOL:
+ case RID_BITINT:
case RID_FRACT:
case RID_ACCUM:
case RID_SAT:
@@ -270,7 +270,7 @@ enum c_storage_class {
/* A type specifier keyword "void", "_Bool", "char", "int", "float",
"double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum",
- or none of these. */
+ "_BitInt", or none of these. */
enum c_typespec_keyword {
cts_none,
cts_void,
@@ -286,6 +286,7 @@ enum c_typespec_keyword {
cts_floatn_nx,
cts_fract,
cts_accum,
+ cts_bitint,
cts_auto_type
};
@@ -366,11 +367,16 @@ struct c_declspecs {
specifier, in bytes, or -1 if no such specifiers with nonzero
alignment. */
int align_log;
- /* For the __intN declspec, this stores the index into the int_n_* arrays. */
- int int_n_idx;
- /* For the _FloatN and _FloatNx declspec, this stores the index into
- the floatn_nx_types array. */
- int floatn_nx_idx;
+ union {
+ /* For the __intN declspec, this stores the index into the int_n_*
+ arrays. */
+ int int_n_idx;
+ /* For the _FloatN and _FloatNx declspec, this stores the index into
+ the floatn_nx_types array. */
+ int floatn_nx_idx;
+ /* For _BitInt(N) this stores the N. */
+ int bitint_prec;
+ } u;
/* The storage class specifier, or csc_none if none. */
enum c_storage_class storage_class;
/* Any type specifier keyword used such as "int", not reflecting
@@ -413,10 +413,14 @@ composite_type (tree t1, tree t2)
the composite type. */
if (code1 == ENUMERAL_TYPE
- && (code2 == INTEGER_TYPE || code2 == BOOLEAN_TYPE))
+ && (code2 == INTEGER_TYPE
+ || code2 == BOOLEAN_TYPE
+ || code2 == BITINT_TYPE))
return t1;
if (code2 == ENUMERAL_TYPE
- && (code1 == INTEGER_TYPE || code1 == BOOLEAN_TYPE))
+ && (code1 == INTEGER_TYPE
+ || code1 == BOOLEAN_TYPE
+ || code1 == BITINT_TYPE))
return t2;
gcc_assert (code1 == code2);
@@ -764,10 +768,10 @@ c_common_type (tree t1, tree t2)
gcc_assert (code1 == VECTOR_TYPE || code1 == COMPLEX_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == REAL_TYPE
- || code1 == INTEGER_TYPE);
+ || code1 == INTEGER_TYPE || code1 == BITINT_TYPE);
gcc_assert (code2 == VECTOR_TYPE || code2 == COMPLEX_TYPE
|| code2 == FIXED_POINT_TYPE || code2 == REAL_TYPE
- || code2 == INTEGER_TYPE);
+ || code2 == INTEGER_TYPE || code2 == BITINT_TYPE);
/* When one operand is a decimal float type, the other operand cannot be
a generic float type or a complex type. We also disallow vector types
@@ -1004,6 +1008,20 @@ c_common_type (tree t1, tree t2)
if (mv1 == FLOATNX_TYPE_NODE (i) || mv2 == FLOATNX_TYPE_NODE (i))
return FLOATNX_TYPE_NODE (i);
+ 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 code1 == BITINT_TYPE ? t2 : t1;
+ /* If BITINT_TYPE is unsigned and the other type is signed
+ non-BITINT_TYPE with the same precision, the latter has higher rank.
+ In that case:
+ Otherwise, both operands are converted to the unsigned integer type
+ corresponding to the type of the operand with signed integer type. */
+ if (TYPE_UNSIGNED (code1 == BITINT_TYPE ? t1 : t2))
+ return c_common_unsigned_type (code1 == BITINT_TYPE ? t2 : t1);
+ }
+
/* Otherwise prefer the unsigned one. */
if (TYPE_UNSIGNED (t1))
@@ -1177,6 +1195,7 @@ comptypes_internal (const_tree type1, co
case INTEGER_TYPE:
case FIXED_POINT_TYPE:
case REAL_TYPE:
+ case BITINT_TYPE:
/* With these nodes, we can't determine type equivalence by
looking at what is stored in the nodes themselves, because
two nodes might have different TYPE_MAIN_VARIANTs but still
@@ -2260,12 +2279,17 @@ perform_integral_promotions (tree exp)
/* ??? This should no longer be needed now bit-fields have their
proper types. */
if (TREE_CODE (exp) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1))
+ && DECL_C_BIT_FIELD (TREE_OPERAND (exp, 1)))
+ {
+ if (TREE_CODE (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1)))
+ == BITINT_TYPE)
+ return convert (DECL_BIT_FIELD_TYPE (TREE_OPERAND (exp, 1)), exp);
/* If it's thinner than an int, promote it like a
c_promoting_integer_type_p, otherwise leave it alone. */
- && compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
- TYPE_PRECISION (integer_type_node)) < 0)
- return convert (integer_type_node, exp);
+ if (compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)),
+ TYPE_PRECISION (integer_type_node)) < 0)
+ return convert (integer_type_node, exp);
+ }
if (c_promoting_integer_type_p (type))
{
@@ -2790,7 +2814,8 @@ build_array_ref (location_t loc, tree ar
if (index == error_mark_node)
return error_mark_node;
- gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE);
+ gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (index)) == BITINT_TYPE);
bool was_vector = VECTOR_TYPE_P (TREE_TYPE (array));
bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, index);
@@ -4558,6 +4583,7 @@ build_unary_op (location_t location, enu
associativity, but won't generate any code. */
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
+ || typecode == BITINT_TYPE
|| gnu_vector_type_p (TREE_TYPE (arg))))
{
error_at (location, "wrong type argument to unary plus");
@@ -4571,6 +4597,7 @@ build_unary_op (location_t location, enu
case NEGATE_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
+ || typecode == BITINT_TYPE
|| gnu_vector_type_p (TREE_TYPE (arg))))
{
error_at (location, "wrong type argument to unary minus");
@@ -4583,6 +4610,7 @@ build_unary_op (location_t location, enu
case BIT_NOT_EXPR:
/* ~ works on integer types and non float vectors. */
if (typecode == INTEGER_TYPE
+ || typecode == BITINT_TYPE
|| (gnu_vector_type_p (TREE_TYPE (arg))
&& !VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg))))
{
@@ -4657,7 +4685,8 @@ build_unary_op (location_t location, enu
case TRUTH_NOT_EXPR:
if (typecode != INTEGER_TYPE && typecode != FIXED_POINT_TYPE
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
- && typecode != COMPLEX_TYPE && typecode != NULLPTR_TYPE)
+ && typecode != COMPLEX_TYPE && typecode != NULLPTR_TYPE
+ && typecode != BITINT_TYPE)
{
error_at (location,
"wrong type argument to unary exclamation mark");
@@ -4769,7 +4798,7 @@ build_unary_op (location_t location, enu
if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE
- && typecode != COMPLEX_TYPE
+ && typecode != COMPLEX_TYPE && typecode != BITINT_TYPE
&& !gnu_vector_type_p (TREE_TYPE (arg)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
@@ -5394,9 +5423,9 @@ build_conditional_expr (location_t colon
result_type = TYPE_MAIN_VARIANT (type1);
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE)
+ || code1 == COMPLEX_TYPE || code1 == BITINT_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE
- || code2 == COMPLEX_TYPE))
+ || code2 == COMPLEX_TYPE || code2 == BITINT_TYPE))
{
/* In C11, a conditional expression between a floating-point
type and an integer type should convert the integer type to
@@ -5583,7 +5612,8 @@ build_conditional_expr (location_t colon
(build_qualified_type (void_type_node, qual));
}
}
- else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
+ else if (code1 == POINTER_TYPE
+ && (code2 == INTEGER_TYPE || code2 == BITINT_TYPE))
{
if (!null_pointer_constant_p (orig_op2))
pedwarn (colon_loc, 0,
@@ -5594,7 +5624,8 @@ build_conditional_expr (location_t colon
}
result_type = type1;
}
- else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
+ else if (code2 == POINTER_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
if (!null_pointer_constant_p (orig_op1))
pedwarn (colon_loc, 0,
@@ -7131,11 +7162,11 @@ convert_for_assignment (location_t locat
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| codel == FIXED_POINT_TYPE
|| codel == ENUMERAL_TYPE || codel == COMPLEX_TYPE
- || codel == BOOLEAN_TYPE)
+ || codel == BOOLEAN_TYPE || codel == BITINT_TYPE)
&& (coder == INTEGER_TYPE || coder == REAL_TYPE
|| coder == FIXED_POINT_TYPE
|| coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE
- || coder == BOOLEAN_TYPE))
+ || coder == BOOLEAN_TYPE || coder == BITINT_TYPE))
{
if (warnopt && errtype == ic_argpass)
maybe_warn_builtin_no_proto_arg (expr_loc, fundecl, parmnum, type,
@@ -8562,7 +8593,8 @@ digest_init (location_t init_loc, tree t
if (code == INTEGER_TYPE || code == REAL_TYPE || code == FIXED_POINT_TYPE
|| code == POINTER_TYPE || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
- || code == COMPLEX_TYPE || code == VECTOR_TYPE || code == NULLPTR_TYPE)
+ || code == COMPLEX_TYPE || code == VECTOR_TYPE || code == NULLPTR_TYPE
+ || code == BITINT_TYPE)
{
tree unconverted_init = inside_init;
if (TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE
@@ -12357,12 +12389,14 @@ build_binary_op (location_t location, en
{
case PLUS_EXPR:
/* Handle the pointer + int case. */
- if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+ if (code0 == POINTER_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
ret = pointer_int_sum (location, PLUS_EXPR, op0, op1);
goto return_build_binary_op;
}
- else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
+ else if (code1 == POINTER_TYPE
+ && (code0 == INTEGER_TYPE || code0 == BITINT_TYPE))
{
ret = pointer_int_sum (location, PLUS_EXPR, op1, op0);
goto return_build_binary_op;
@@ -12381,7 +12415,8 @@ build_binary_op (location_t location, en
goto return_build_binary_op;
}
/* Handle pointer minus int. Just like pointer plus int. */
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+ else if (code0 == POINTER_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
ret = pointer_int_sum (location, MINUS_EXPR, op0, op1);
goto return_build_binary_op;
@@ -12403,11 +12438,11 @@ build_binary_op (location_t location, en
warn_for_div_by_zero (location, op1);
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == FIXED_POINT_TYPE
+ || code0 == FIXED_POINT_TYPE || code0 == BITINT_TYPE
|| code0 == COMPLEX_TYPE
|| gnu_vector_type_p (type0))
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == FIXED_POINT_TYPE
+ || code1 == FIXED_POINT_TYPE || code1 == BITINT_TYPE
|| code1 == COMPLEX_TYPE
|| gnu_vector_type_p (type1)))
{
@@ -12418,8 +12453,9 @@ build_binary_op (location_t location, en
if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
tcode1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
- if (!((tcode0 == INTEGER_TYPE && tcode1 == INTEGER_TYPE)
- || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
+ if (!(((tcode0 == INTEGER_TYPE || tcode0 == BITINT_TYPE)
+ && (tcode1 == INTEGER_TYPE || tcode1 == BITINT_TYPE))
+ || (tcode0 == FIXED_POINT_TYPE && tcode1 == FIXED_POINT_TYPE)))
resultcode = RDIV_EXPR;
else
/* Although it would be tempting to shorten always here, that
@@ -12435,7 +12471,8 @@ build_binary_op (location_t location, en
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+ if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
shorten = -1;
/* Allow vector types which are not floating point types. */
else if (gnu_vector_type_p (type0)
@@ -12455,7 +12492,8 @@ build_binary_op (location_t location, en
&& 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 ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
/* Although it would be tempting to shorten always here, that loses
on some targets, since the modulo instruction is undefined if the
@@ -12473,10 +12511,12 @@ build_binary_op (location_t location, en
case TRUTH_XOR_EXPR:
if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE
|| code0 == REAL_TYPE || code0 == COMPLEX_TYPE
- || code0 == FIXED_POINT_TYPE || code0 == NULLPTR_TYPE)
+ || code0 == FIXED_POINT_TYPE || code0 == NULLPTR_TYPE
+ || code0 == BITINT_TYPE)
&& (code1 == INTEGER_TYPE || code1 == POINTER_TYPE
|| code1 == REAL_TYPE || code1 == COMPLEX_TYPE
- || code1 == FIXED_POINT_TYPE || code1 == NULLPTR_TYPE))
+ || code1 == FIXED_POINT_TYPE || code1 == NULLPTR_TYPE
+ || code1 == BITINT_TYPE))
{
/* Result of these operations is always an int,
but that does not mean the operands should be
@@ -12539,9 +12579,10 @@ build_binary_op (location_t location, en
converted = 1;
}
else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+ || code0 == BITINT_TYPE
|| (gnu_vector_type_p (type0)
&& TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE))
- && code1 == INTEGER_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
doing_shift = true;
if (TREE_CODE (op1) == INTEGER_CST)
@@ -12599,9 +12640,10 @@ build_binary_op (location_t location, en
converted = 1;
}
else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE
+ || code0 == BITINT_TYPE
|| (gnu_vector_type_p (type0)
&& TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE))
- && code1 == INTEGER_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
doing_shift = true;
if (TREE_CODE (op0) == INTEGER_CST
@@ -12715,9 +12757,10 @@ build_binary_op (location_t location, en
/* Result of comparison is always int,
but don't convert the args to int! */
build_type = integer_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == BITINT_TYPE
|| code0 == FIXED_POINT_TYPE || code0 == COMPLEX_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == BITINT_TYPE
|| code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE
@@ -12778,12 +12821,14 @@ build_binary_op (location_t location, en
(build_qualified_type (void_type_node, qual));
}
}
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+ else if (code0 == POINTER_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
result_type = type0;
pedwarn (location, 0, "comparison between pointer and integer");
}
- else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
+ else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
+ && code1 == POINTER_TYPE)
{
result_type = type1;
pedwarn (location, 0, "comparison between pointer and integer");
@@ -12871,9 +12916,9 @@ build_binary_op (location_t location, en
}
build_type = integer_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == FIXED_POINT_TYPE)
+ || code0 == BITINT_TYPE || code0 == FIXED_POINT_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == FIXED_POINT_TYPE))
+ || code1 == BITINT_TYPE || code1 == FIXED_POINT_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
@@ -12932,12 +12977,14 @@ build_binary_op (location_t location, en
warning_at (location, OPT_Wextra,
"ordered comparison of pointer with integer zero");
}
- else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
+ else if (code0 == POINTER_TYPE
+ && (code1 == INTEGER_TYPE || code1 == BITINT_TYPE))
{
result_type = type0;
pedwarn (location, 0, "comparison between pointer and integer");
}
- else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
+ else if ((code0 == INTEGER_TYPE || code0 == BITINT_TYPE)
+ && code1 == POINTER_TYPE)
{
result_type = type1;
pedwarn (location, 0, "comparison between pointer and integer");
@@ -12991,12 +13038,11 @@ build_binary_op (location_t location, en
}
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
- || code0 == FIXED_POINT_TYPE
+ || code0 == FIXED_POINT_TYPE || code0 == BITINT_TYPE
|| gnu_vector_type_p (type0))
- &&
- (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
- || code1 == FIXED_POINT_TYPE
- || gnu_vector_type_p (type1)))
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE
+ || code1 == FIXED_POINT_TYPE || code1 == BITINT_TYPE
+ || gnu_vector_type_p (type1)))
{
bool first_complex = (code0 == COMPLEX_TYPE);
bool second_complex = (code1 == COMPLEX_TYPE);
@@ -327,9 +327,9 @@ static unsigned int
interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
size_t orig_len = len;
- size_t u, l, i, z;
+ size_t u, l, i, z, wb;
- u = l = i = z = 0;
+ u = l = i = z = wb = 0;
while (len--)
switch (s[len])
@@ -343,11 +343,23 @@ interpret_int_suffix (cpp_reader *pfile,
if (l == 2 && s[len] != s[len + 1])
return 0;
break;
+ case 'b':
+ if (len == 0 || s[len - 1] != 'w')
+ return 0;
+ wb++;
+ len--;
+ break;
+ case 'B':
+ if (len == 0 || s[len - 1] != 'W')
+ return 0;
+ wb++;
+ len--;
+ break;
default:
return 0;
}
- if (l > 2 || u > 1 || i > 1 || z > 1)
+ if (l > 2 || u > 1 || i > 1 || z > 1 || wb > 1)
return 0;
if (z)
@@ -358,6 +370,14 @@ interpret_int_suffix (cpp_reader *pfile,
return 0;
}
+ if (wb)
+ {
+ if (CPP_OPTION (pfile, cplusplus))
+ return 0;
+ if (l > 0 || i > 0 || z > 0)
+ return 0;
+ }
+
if (i)
{
if (!CPP_OPTION (pfile, ext_numeric_literals))
@@ -376,7 +396,8 @@ interpret_int_suffix (cpp_reader *pfile,
| (u ? CPP_N_UNSIGNED : 0)
| ((l == 0) ? CPP_N_SMALL
: (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE)
- | (z ? CPP_N_SIZE_T : 0));
+ | (z ? CPP_N_SIZE_T : 0)
+ | (wb ? CPP_N_BITINT : 0));
}
/* Return the classification flags for an int suffix. */
@@ -1284,6 +1284,7 @@ struct cpp_num
#define CPP_N_SIZE_T 0x2000000 /* C++23 size_t literal. */
#define CPP_N_BFLOAT16 0x4000000 /* std::bfloat16_t type. */
+#define CPP_N_BITINT 0x8000000 /* C2X _BitInt literal. */
#define CPP_N_WIDTH_FLOATN_NX 0xF0000000 /* _FloatN / _FloatNx value
of N, divided by 16. */