This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: ia64 linux doesn't bootstrap
- From: David Edelsohn <dje at watson dot ibm dot com>
- To: Janis Johnson <janis187 at us dot ibm dot com>, Mark Mitchell <mark at codesourcery dot com>
- Cc: Andreas Schwab <schwab at suse dot de>, Aldy Hernandez <aldyh at redhat dot com>, gcc at gcc dot gnu dot org
- Date: Fri, 18 Oct 2002 16:02:53 -0400
- Subject: Re: ia64 linux doesn't bootstrap
Tighten your seatbelt, the AIX failure is another case where the C
and C++ front-ends are not consistent with respect to the state of a DECL
after warnings. I am not sure which one is right.
The testcase in g++.dg/break/bitfield7_y.C creates a bitfield that
is too wide:
union U {
int i: 4096;
};
and accesses it:
void bitfield7_y (U* u)
{
if (u[0].i != 7)
abort ();
if (u[1].i != 8)
abort ();
This is based on g++.dg/abi/bitfield7.C which declares the union and looks
for both the ABI warning and the "width exceeds type" warning without
accessing a variable of that type.
The C++ testcase ICEs while the equivalent C testcase does not.
c-decl.c:finish_struct() ignores out of range field widths -- not
only warning but leaving a number of DECL fields undefined:
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'");
else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
pedwarn_with_decl (x, "width of `%s' exceeds its type"); <***
else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
error_with_decl (x, "zero width for bit-field `%s'");
else
{
...
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
SET_DECL_C_BIT_FIELD (x);
...
}
cp/class.c sometimes leaves the DECL fields undefined (by setting
error_mark_node) and sometimes proceeds with assigning the DECL fields, as
in the case of the "width exceeds type" warning:
if (TREE_CODE (w) != INTEGER_CST)
{
cp_error_at ("bit-field `%D' width not an integer constant",
field);
w = error_mark_node;
}
else if (tree_int_cst_sgn (w) < 0)
{
cp_error_at ("negative width in bit-field `%D'", field);
w = error_mark_node;
}
else if (integer_zerop (w) && DECL_NAME (field) != 0)
{
cp_error_at ("zero width for bit-field `%D'", field);
w = error_mark_node;
}
else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
&& TREE_CODE (type) != ENUMERAL_TYPE
&& TREE_CODE (type) != BOOLEAN_TYPE)
cp_warning_at ("width of `%D' exceeds its type", field); <***
else if (TREE_CODE (type) == ENUMERAL_TYPE
&& (0 > compare_tree_int (w,
min_precision (TYPE_MIN_VALUE (type),
TREE_UNSIGNED (type)))
|| 0 > compare_tree_int (w,
min_precision
(TYPE_MAX_VALUE (type),
TREE_UNSIGNED (type)))))
cp_warning_at ("`%D' is too small to hold all values of `%#T'",
field, type);
}
...
if (w != error_mark_node)
{
DECL_SIZE (field) = convert (bitsizetype, w);
DECL_BIT_FIELD (field) = 1;
...
}
To summarize the situation so far, a bitfield width exceeding the type
size will leave DECL_BIT_FIELD unset for the C front-end but will set it
for the C++ front-end.
Later in expr.c:expand_expr(), get_inner_reference() will
calculate the mode of the field as the mode of the outer expression for C
(because DECL_BIT_FIELD is false) and VOIDmode for C++ (because
DECL_BIT_FIELD is true).
For C++, the VOIDmode means the field is an unaligned field in an
aligned union. This invokes extract_bit_field() which calculates a crazy
bit offset handed to operand_subword() and simplify_gen_subreg() which
eventually ICEs. For C, the sane outer mode skips the extract_bit_field()
call and accesses the "component" directly.
I do not know whether C++ should behave like C and not set
DECL_BIT_FIELD. However, if DECL_BIT_FIELD should not be set for width
exceeding type then why should it ever be set? The non-VOIDmode case in
expand_expr() using adjust_address() and convert_move() appears to have
succeeded even though the inner mode was not aligned.
The various possibilities seem to be:
cp/class.c should not set DECL_BIT_FIELD when width exceeds type.
OR
c-decl.c should set DECL_BIT_FIELD when width exceeds type.
If DECL_BIT_FIELD is set when the width exceeds the type, there
needs to be some other change in the backend to prevent the ICE.
get_inner_reference() always should return the outer mode? expand_expr()
should use adjust_address() and convert_move() even when the inner mode is
VOIDmode?
I do not know which behavior is correct other than GCC should not
ICE.
Thanks, David