This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]