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:
parent
942e59391c
commit
bc15d0efe4
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
25
gcc/c-decl.c
25
gcc/c-decl.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
79
gcc/expr.c
79
gcc/expr.c
|
@ -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
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
set torture_execute_xfail "*-*-*"
|
||||
return 0
|
|
@ -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);
|
||||
}
|
|
@ -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)" } */
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
22
gcc/tree.c
22
gcc/tree.c
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue