re PR c/2511 (-pedantic not warning about bitfield overflow)

2004-07-08  Joseph S. Myers  <jsm@polyomino.org.uk>
            Neil Booth  <neil@daikokuya.co.uk>

	PR c/2511
	PR c/3325
	* c-decl.c (finish_struct): Ensure bit-fields are given the
	correct type.
	* c-common.c (c_common_signed_or_unsigned_type): For C, require
	the precision to match as well as the mode.
	* expr.c (reduce_to_bit_field_precision): New function.
	(expand_expr_real_1): Reduce expressions of bit-field type to
	proper precision.
	* langhooks.h (reduce_bit_field_operations): New hook.
	* langhooks-def.h (LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS):
	Define.
	* c-lang.c, objc/objc-lang.c
	(LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS): Define.
	* objc/objc-act.c (check_ivars): Convert types to bit-field types
	before checking.
	* tree.c (build_nonstandard_integer_type): New function.
	* tree.h (build_nonstandard_integer_type): New prototype.
	* tree-ssa.c (tree_ssa_useless_type_conversion_1): Don't treat
	conversions between integer and boolean types as useless.

testsuite:
	* gcc.c-torture/execute/bitfld-1.x: Remove.
	* gcc.c-torture/execute/bitfld-3.c: New test.
	* gcc.dg/bitfld-2.c: Remove XFAILs.

Co-Authored-By: Neil Booth <neil@daikokuya.co.uk>

From-SVN: r84279
This commit is contained in:
Joseph Myers 2004-07-08 09:45:05 +01:00 committed by Joseph Myers
parent 942e59391c
commit bc15d0efe4
16 changed files with 250 additions and 51 deletions

View File

@ -1,3 +1,27 @@
2004-07-08 Joseph S. Myers <jsm@polyomino.org.uk>
Neil Booth <neil@daikokuya.co.uk>
PR c/2511
PR c/3325
* c-decl.c (finish_struct): Ensure bit-fields are given the
correct type.
* c-common.c (c_common_signed_or_unsigned_type): For C, require
the precision to match as well as the mode.
* expr.c (reduce_to_bit_field_precision): New function.
(expand_expr_real_1): Reduce expressions of bit-field type to
proper precision.
* langhooks.h (reduce_bit_field_operations): New hook.
* langhooks-def.h (LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS):
Define.
* c-lang.c, objc/objc-lang.c
(LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS): Define.
* objc/objc-act.c (check_ivars): Convert types to bit-field types
before checking.
* tree.c (build_nonstandard_integer_type): New function.
* tree.h (build_nonstandard_integer_type): New prototype.
* tree-ssa.c (tree_ssa_useless_type_conversion_1): Don't treat
conversions between integer and boolean types as useless.
2004-07-08 Paolo Bonzini <bonzini@gnu.org>
* c-common.c (c_common_nodes_and_builtins): Do not

View File

@ -1636,40 +1636,51 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
|| TYPE_UNSIGNED (type) == unsignedp)
return type;
/* Must check the mode of the types, not the precision. Enumeral types
in C++ have precision set to match their range, but may use a wider
mode to match an ABI. If we change modes, we may wind up with bad
conversions. */
/* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
the precision; they have precision set to match their range, but
may use a wider mode to match an ABI. If we change modes, we may
wind up with bad conversions. For INTEGER_TYPEs in C, must check
the precision as well, so as to yield correct results for
bit-field types. C++ does not have these separate bit-field
types, and producing a signed or unsigned variant of an
ENUMERAL_TYPE may cause other problems as well. */
if (TYPE_MODE (type) == TYPE_MODE (signed_char_type_node))
#define TYPE_OK(node) \
(TYPE_MODE (type) == TYPE_MODE (node) \
&& (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
if (TYPE_OK (signed_char_type_node))
return unsignedp ? unsigned_char_type_node : signed_char_type_node;
if (TYPE_MODE (type) == TYPE_MODE (integer_type_node))
if (TYPE_OK (integer_type_node))
return unsignedp ? unsigned_type_node : integer_type_node;
if (TYPE_MODE (type) == TYPE_MODE (short_integer_type_node))
if (TYPE_OK (short_integer_type_node))
return unsignedp ? short_unsigned_type_node : short_integer_type_node;
if (TYPE_MODE (type) == TYPE_MODE (long_integer_type_node))
if (TYPE_OK (long_integer_type_node))
return unsignedp ? long_unsigned_type_node : long_integer_type_node;
if (TYPE_MODE (type) == TYPE_MODE (long_long_integer_type_node))
if (TYPE_OK (long_long_integer_type_node))
return (unsignedp ? long_long_unsigned_type_node
: long_long_integer_type_node);
if (TYPE_MODE (type) == TYPE_MODE (widest_integer_literal_type_node))
if (TYPE_OK (widest_integer_literal_type_node))
return (unsignedp ? widest_unsigned_literal_type_node
: widest_integer_literal_type_node);
#if HOST_BITS_PER_WIDE_INT >= 64
if (TYPE_MODE (type) == TYPE_MODE (intTI_type_node))
if (TYPE_OK (intTI_type_node))
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
#endif
if (TYPE_MODE (type) == TYPE_MODE (intDI_type_node))
if (TYPE_OK (intDI_type_node))
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
if (TYPE_MODE (type) == TYPE_MODE (intSI_type_node))
if (TYPE_OK (intSI_type_node))
return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
if (TYPE_MODE (type) == TYPE_MODE (intHI_type_node))
if (TYPE_OK (intHI_type_node))
return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
if (TYPE_MODE (type) == TYPE_MODE (intQI_type_node))
if (TYPE_OK (intQI_type_node))
return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
#undef TYPE_OK
return type;
if (c_dialect_cxx ())
return type;
else
return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
}
/* The C version of the register_builtin_type langhook. */

View File

@ -5162,9 +5162,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
}
/* Install struct as DECL_CONTEXT of each field decl.
Also process specified field sizes,m which is found in the DECL_INITIAL.
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
Also process specified field sizes, found in the DECL_INITIAL,
storing 0 there after the type has been changed to precision equal
to its width, rather than the precision of the specified standard
type. (Correct layout requires the original type to have been preserved
until now.) */
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
@ -5208,8 +5210,6 @@ finish_struct (tree t, tree fieldlist, tree attributes)
SET_DECL_C_BIT_FIELD (x);
}
DECL_INITIAL (x) = 0;
/* Detect flexible array member in an invalid context. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
@ -5250,12 +5250,21 @@ finish_struct (tree t, tree fieldlist, tree attributes)
layout_type (t);
/* Delete all zero-width bit-fields from the fieldlist. */
/* Give bit-fields their proper types. */
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
*fieldlistp = TREE_CHAIN (*fieldlistp);
if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
&& TREE_TYPE (*fieldlistp) != error_mark_node)
{
unsigned HOST_WIDE_INT width
= tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
tree type = TREE_TYPE (*fieldlistp);
if (width != TYPE_PRECISION (type))
TREE_TYPE (*fieldlistp)
= build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
DECL_INITIAL (*fieldlistp) = 0;
}
else
fieldlistp = &TREE_CHAIN (*fieldlistp);
}

View File

@ -74,6 +74,8 @@ enum c_language_kind c_language = clk_c;
#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
#undef LANG_HOOKS_STATICP
#define LANG_HOOKS_STATICP c_staticp
#undef LANG_HOOKS_NO_BODY_BLOCKS

View File

@ -154,6 +154,7 @@ static int is_aligning_offset (tree, tree);
static rtx expand_increment (tree, int, int);
static void expand_operands (tree, tree, rtx, rtx*, rtx*,
enum expand_modifier);
static rtx reduce_to_bit_field_precision (rtx, rtx, tree);
static rtx do_store_flag (tree, rtx, enum machine_mode, int);
#ifdef PUSH_ROUNDING
static void emit_single_push_insn (enum machine_mode, rtx, tree);
@ -6430,9 +6431,26 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
rtx subtarget, original_target;
int ignore;
tree context;
bool reduce_bit_field = false;
#define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore \
? reduce_to_bit_field_precision ((expr), \
target, \
type) \
: (expr))
mode = TYPE_MODE (type);
unsignedp = TYPE_UNSIGNED (type);
if (lang_hooks.reduce_bit_field_operations
&& TREE_CODE (type) == INTEGER_TYPE
&& GET_MODE_PRECISION (mode) > TYPE_PRECISION (type))
{
/* An operation in what may be a bit-field type needs the
result to be reduced to the precision of the bit-field type,
which is narrower than that of the type's mode. */
reduce_bit_field = true;
if (modifier == EXPAND_STACK_PARM)
target = 0;
}
/* Use subtarget as the target for operand 0 of a binary operation. */
subtarget = get_subtarget (target);
@ -7423,10 +7441,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
&& GET_CODE (op0) == SUBREG)
SUBREG_PROMOTED_VAR_P (op0) = 0;
return op0;
return REDUCE_BIT_FIELD (op0);
}
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
op0 = REDUCE_BIT_FIELD (op0);
if (GET_MODE (op0) == mode)
return op0;
@ -7594,7 +7613,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op1 = plus_constant (op1, INTVAL (constant_part));
if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
op1 = force_operand (op1, target);
return op1;
return REDUCE_BIT_FIELD (op1);
}
else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
@ -7627,7 +7646,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
op0 = plus_constant (op0, INTVAL (constant_part));
if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
op0 = force_operand (op0, target);
return op0;
return REDUCE_BIT_FIELD (op0);
}
}
@ -7649,7 +7668,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
subtarget, &op0, &op1, modifier);
return simplify_gen_binary (PLUS, mode, op0, op1);
return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
case MINUS_EXPR:
/* For initializers, we are allowed to return a MINUS of two
@ -7667,9 +7686,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* If the last operand is a CONST_INT, use plus_constant of
the negated constant. Else make the MINUS. */
if (GET_CODE (op1) == CONST_INT)
return plus_constant (op0, - INTVAL (op1));
return REDUCE_BIT_FIELD (plus_constant (op0, - INTVAL (op1)));
else
return gen_rtx_MINUS (mode, op0, op1);
return REDUCE_BIT_FIELD (gen_rtx_MINUS (mode, op0, op1));
}
this_optab = ! unsignedp && flag_trapv
@ -7691,7 +7710,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (GET_CODE (op1) == CONST_INT)
{
op1 = negate_rtx (mode, op1);
return simplify_gen_binary (PLUS, mode, op0, op1);
return REDUCE_BIT_FIELD (simplify_gen_binary (PLUS, mode, op0, op1));
}
goto binop2;
@ -7723,9 +7742,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (!REG_P (op0))
op0 = copy_to_mode_reg (mode, op0);
return gen_rtx_MULT (mode, op0,
return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
gen_int_mode (tree_low_cst (exp1, 0),
TYPE_MODE (TREE_TYPE (exp1))));
TYPE_MODE (TREE_TYPE (exp1)))));
}
if (modifier == EXPAND_STACK_PARM)
@ -7803,13 +7822,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
zextend_p);
if (htem != hipart)
emit_move_insn (hipart, htem);
return temp;
return REDUCE_BIT_FIELD (temp);
}
}
}
expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
subtarget, &op0, &op1, 0);
return expand_mult (mode, op0, op1, target, unsignedp);
return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
case TRUNC_DIV_EXPR:
case FLOOR_DIV_EXPR:
@ -7885,7 +7904,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
? negv_optab : neg_optab, op0, target, 0);
if (temp == 0)
abort ();
return temp;
return REDUCE_BIT_FIELD (temp);
case ABS_EXPR:
op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
@ -8550,12 +8569,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
return expand_increment (exp, 0, ignore);
return REDUCE_BIT_FIELD (expand_increment (exp, 0, ignore));
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
/* Faster to treat as pre-increment if result is not used. */
return expand_increment (exp, ! ignore, ignore);
return REDUCE_BIT_FIELD (expand_increment (exp, ! ignore, ignore));
case ADDR_EXPR:
if (modifier == EXPAND_STACK_PARM)
@ -8915,7 +8934,37 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
unsignedp, OPTAB_LIB_WIDEN);
if (temp == 0)
abort ();
return temp;
return REDUCE_BIT_FIELD (temp);
}
#undef REDUCE_BIT_FIELD
/* Subroutine of above: reduce EXP to the precision of TYPE (in the
signedness of TYPE), possibly returning the result in TARGET. */
static rtx
reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
{
HOST_WIDE_INT prec = TYPE_PRECISION (type);
if (target && GET_MODE (target) != GET_MODE (exp))
target = 0;
if (TYPE_UNSIGNED (type))
{
rtx mask;
if (prec < HOST_BITS_PER_WIDE_INT)
mask = immed_double_const (((unsigned HOST_WIDE_INT) 1 << prec) - 1, 0,
GET_MODE (exp));
else
mask = immed_double_const ((unsigned HOST_WIDE_INT) -1,
((unsigned HOST_WIDE_INT) 1
<< (prec - HOST_BITS_PER_WIDE_INT)) - 1,
GET_MODE (exp));
return expand_and (GET_MODE (exp), exp, mask, target);
}
else
{
tree count = build_int_2 (GET_MODE_BITSIZE (GET_MODE (exp)) - prec, 0);
exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
return expand_shift (RSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
}
}
/* Subroutine of above: returns 1 if OFFSET corresponds to an offset that

View File

@ -116,6 +116,7 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
#define LANG_HOOKS_MAYBE_BUILD_CLEANUP lhd_return_null_tree
#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME lhd_set_decl_assembler_name
#define LANG_HOOKS_CAN_USE_BIT_FIELDS_P lhd_can_use_bit_fields_p
#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS false
#define LANG_HOOKS_HONOR_READONLY false
#define LANG_HOOKS_NO_BODY_BLOCKS false
#define LANG_HOOKS_PRINT_STATISTICS lhd_do_nothing
@ -294,6 +295,7 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_MAYBE_BUILD_CLEANUP, \
LANG_HOOKS_SET_DECL_ASSEMBLER_NAME, \
LANG_HOOKS_CAN_USE_BIT_FIELDS_P, \
LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS, \
LANG_HOOKS_HONOR_READONLY, \
LANG_HOOKS_NO_BODY_BLOCKS, \
LANG_HOOKS_PRINT_STATISTICS, \

View File

@ -347,6 +347,10 @@ struct lang_hooks
optimizations, for instance in fold_truthop(). */
bool (*can_use_bit_fields_p) (void);
/* Nonzero if operations on types narrower than their mode should
have their results reduced to the precision of the type. */
bool reduce_bit_field_operations;
/* Nonzero if TYPE_READONLY and TREE_READONLY should always be honored. */
bool honor_readonly;

View File

@ -4257,6 +4257,16 @@ check_ivars (tree inter, tree imp)
t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
if (TREE_VALUE (TREE_VALUE (rawimpdecls)))
{
/* t1 is the bit-field type, so t2 must be converted to the
bit-field type for comparison as well. */
unsigned HOST_WIDE_INT width
= tree_low_cst (TREE_VALUE (TREE_VALUE (rawimpdecls)), 1);
if (width != TYPE_PRECISION (t2))
t2 = build_nonstandard_integer_type (width, TYPE_UNSIGNED (t2));
}
if (!comptypes (t1, t2)
|| !tree_int_cst_equal (TREE_VALUE (TREE_VALUE (rawintdecls)),
TREE_VALUE (TREE_VALUE (rawimpdecls))))

View File

@ -71,6 +71,8 @@ enum c_language_kind c_language = clk_objc;
#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
#undef LANG_HOOKS_STATICP
#define LANG_HOOKS_STATICP c_staticp
#undef LANG_HOOKS_NO_BODY_BLOCKS

View File

@ -1,3 +1,9 @@
2004-07-08 Joseph S. Myers <jsm@polyomino.org.uk>
* gcc.c-torture/execute/bitfld-1.x: Remove.
* gcc.c-torture/execute/bitfld-3.c: New test.
* gcc.dg/bitfld-2.c: Remove XFAILs.
2004-07-07 H.J. Lu <hongjiu.lu@intel.com>
PR c++/16276

View File

@ -1,2 +0,0 @@
set torture_execute_xfail "*-*-*"
return 0

View File

@ -0,0 +1,54 @@
/* Test that operations on bit-fields yield results reduced to bit-field
type. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
extern void exit (int);
extern void abort (void);
struct s {
unsigned long long u33: 33;
unsigned long long u40: 40;
unsigned long long u41: 41;
};
struct s a = { 0x100000, 0x100000, 0x100000 };
struct s b = { 0x100000000ULL, 0x100000000ULL, 0x100000000ULL };
struct s c = { 0x1FFFFFFFFULL, 0, 0 };
int
main (void)
{
if (a.u33 * a.u33 != 0 || a.u33 * a.u40 != 0 || a.u40 * a.u33 != 0
|| a.u40 * a.u40 != 0)
abort ();
if (a.u33 * a.u41 != 0x10000000000ULL
|| a.u40 * a.u41 != 0x10000000000ULL
|| a.u41 * a.u33 != 0x10000000000ULL
|| a.u41 * a.u40 != 0x10000000000ULL
|| a.u41 * a.u41 != 0x10000000000ULL)
abort ();
if (b.u33 + b.u33 != 0)
abort ();
if (b.u33 + b.u40 != 0x200000000ULL
|| b.u33 + b.u41 != 0x200000000ULL
|| b.u40 + b.u33 != 0x200000000ULL
|| b.u40 + b.u40 != 0x200000000ULL
|| b.u40 + b.u41 != 0x200000000ULL
|| b.u41 + b.u33 != 0x200000000ULL
|| b.u41 + b.u40 != 0x200000000ULL
|| b.u41 + b.u41 != 0x200000000ULL)
abort ();
if (a.u33 - b.u33 != 0x100100000ULL
|| a.u33 - b.u40 != 0xFF00100000ULL
|| a.u33 - b.u41 != 0x1FF00100000ULL
|| a.u40 - b.u33 != 0xFF00100000ULL
|| a.u40 - b.u40 != 0xFF00100000ULL
|| a.u40 - b.u41 != 0x1FF00100000ULL
|| a.u41 - b.u33 != 0x1FF00100000ULL
|| a.u41 - b.u40 != 0x1FF00100000ULL
|| a.u41 - b.u41 != 0x1FF00100000ULL)
abort ();
if (++c.u33 != 0 || --c.u40 != 0xFFFFFFFFFFULL || c.u41-- != 0)
abort ();
exit (0);
}

View File

@ -11,13 +11,13 @@ struct bf
int b: 2;
};
struct bf p = {4, 0}; /* { dg-warning "truncated" "" { xfail *-*-* } } */
struct bf q = {0, 2}; /* { dg-warning "overflow" "" { xfail *-*-* } } */
struct bf p = {4, 0}; /* { dg-warning "truncated" "" } */
struct bf q = {0, 2}; /* { dg-warning "overflow" "" } */
struct bf r = {3, -2}; /* { dg-bogus "(truncated|overflow)" } */
void foo ()
{
p.a = 4, p.b = 0; /* { dg-warning "truncated" "" { xfail *-*-* } } */
q.a = 0, q.b = 2; /* { dg-warning "overflow" "" { xfail *-*-* } } */
p.a = 4, p.b = 0; /* { dg-warning "truncated" "" } */
q.a = 0, q.b = 2; /* { dg-warning "overflow" "" } */
r.a = 3, r.b = -2; /* { dg-bogus "(truncated|overflow)" } */
}

View File

@ -572,17 +572,22 @@ tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
/* If both the inner and outer types are integral types, then the
conversion is not necessary if they have the same mode and
signedness and precision. Note that type _Bool can have size of
4 (only happens on powerpc-darwin right now but can happen on any
target that defines BOOL_TYPE_SIZE to be INT_TYPE_SIZE) and a
precision of 1 while unsigned int is the same expect for a
precision of 4 so testing of precision is necessary. */
signedness and precision, and both or neither are boolean. Some
code assumes an invariant that boolean types stay boolean and do
not become 1-bit bit-field types. Note that types with precision
not using all bits of the mode (such as bit-field types in C)
mean that testing of precision is necessary. */
else if (INTEGRAL_TYPE_P (inner_type)
&& INTEGRAL_TYPE_P (outer_type)
&& TYPE_MODE (inner_type) == TYPE_MODE (outer_type)
&& TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type)
&& TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
return true;
{
bool first_boolean = (TREE_CODE (inner_type) == BOOLEAN_TYPE);
bool second_boolean = (TREE_CODE (outer_type) == BOOLEAN_TYPE);
if (first_boolean == second_boolean)
return true;
}
/* Recurse for complex types. */
else if (TREE_CODE (inner_type) == COMPLEX_TYPE

View File

@ -4133,6 +4133,28 @@ build_index_type (tree maxval)
return itype;
}
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
tree
build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
int unsignedp)
{
tree itype = make_node (INTEGER_TYPE);
TYPE_PRECISION (itype) = precision;
if (unsignedp)
fixup_unsigned_type (itype);
else
fixup_signed_type (itype);
if (host_integerp (TYPE_MAX_VALUE (itype), 1))
return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
return itype;
}
/* Create a range of some discrete type TYPE (an INTEGER_TYPE,
ENUMERAL_TYPE, BOOLEAN_TYPE, or CHAR_TYPE), with
low bound LOWVAL and high bound HIGHVAL.

View File

@ -3472,6 +3472,7 @@ extern int real_minus_onep (tree);
extern void init_ttree (void);
extern void build_common_tree_nodes (int);
extern void build_common_tree_nodes_2 (int);
extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_range_type (tree, tree, tree);
/* In function.c */