This is the mail archive of the gcc-patches@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]

C++ PATCH: Another size crash



This patch fixes another crash introduced by Kenner's recent changes.

The C++ front-end depends on being able to explicitly specify the
width of a field, even if it is not a bitfield, in order to handle
complex class-layout problems.  Conceivably, the front-end could be
changed to do these things differently, but there's no reason to deny
front-ends this ability.  If DECL_SIZE was always going to be the same
as TYPE_SIZE (TREE_TYPE (decl)), then we wouldn't really need
DECL_SIZE, except for bitfields -- and we could then combine the
DECL_SIZE field with some othe field that bitfields are guaranteed not
to use.

In any case, here's the patch.  Bootstrapped and tested on x86-linux-gnu.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-03-01  Mark Mitchell  <mark@codesourcery.com>

	* stor-layout.c (layout_decl): Allow front-ends to explicitly set
	the DECL_SIZE for a FIELD_DECL.

Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/stor-layout.c,v
retrieving revision 1.49
diff -c -p -r1.49 stor-layout.c
*** stor-layout.c	2000/02/29 02:34:46	1.49
--- stor-layout.c	2000/03/01 22:25:31
*************** layout_decl (decl, known_align)
*** 265,294 ****
  {
    register tree type = TREE_TYPE (decl);
    register enum tree_code code = TREE_CODE (decl);
-   HOST_WIDE_INT spec_size = 0;
  
    if (code == CONST_DECL)
      return;
-   else if (code == FIELD_DECL)
-     {
-       if (DECL_SIZE (decl) != 0)
- 	{
- 	  spec_size = TREE_INT_CST_LOW (DECL_SIZE (decl));
- 	  DECL_SIZE (decl) = 0;
- 	}
-     }
    else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
! 	   && code != TYPE_DECL)
      abort ();
  
    if (type == error_mark_node)
!     {
!       type = void_type_node;
!       spec_size = 0;
!     }
  
    /* Usually the size and mode come from the data type without change.  */
- 
    DECL_MODE (decl) = TYPE_MODE (type);
    TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
    if (DECL_SIZE (decl) == 0)
--- 265,281 ----
  {
    register tree type = TREE_TYPE (decl);
    register enum tree_code code = TREE_CODE (decl);
  
    if (code == CONST_DECL)
      return;
    else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
! 	   && code != TYPE_DECL && code != FIELD_DECL)
      abort ();
  
    if (type == error_mark_node)
!     type = void_type_node;
  
    /* Usually the size and mode come from the data type without change.  */
    DECL_MODE (decl) = TYPE_MODE (type);
    TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
    if (DECL_SIZE (decl) == 0)
*************** layout_decl (decl, known_align)
*** 296,309 ****
        DECL_SIZE (decl) = TYPE_SIZE (type);
        DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
      }
! 
!   if (code == FIELD_DECL && DECL_BIT_FIELD (decl))
      {
!       if (spec_size == 0 && DECL_NAME (decl) != 0)
  	abort ();
  
        /* Size is specified in number of bits.  */
!       DECL_SIZE (decl) = bitsize_int (spec_size);
        if (spec_size % BITS_PER_UNIT == 0)
  	DECL_SIZE_UNIT (decl) = size_int (spec_size / BITS_PER_UNIT);
        else
--- 283,305 ----
        DECL_SIZE (decl) = TYPE_SIZE (type);
        DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
      }
!   else if (code == FIELD_DECL)
      {
!       HOST_WIDE_INT spec_size;
! 
!       /* The front-end may set the explicit width of the field, so its
! 	 size may not be the same as the size of its type.  This happens
! 	 with bitfields, of course (an `int' bitfield may be only 2 bits,
! 	 say), but it also happens with other fields.  For example, the
! 	 C++ front-end creates zero-sized fields corresponding to empty
! 	 base classes, and depends on layout_type setting
! 	 DECL_FIELD_BITPOS correctly for the field.  */
!       if (integer_zerop (DECL_SIZE (decl)) 
! 	  && DECL_NAME (decl) != NULL_TREE)
  	abort ();
  
        /* Size is specified in number of bits.  */
!       spec_size = TREE_INT_CST_LOW (DECL_SIZE (decl));
        if (spec_size % BITS_PER_UNIT == 0)
  	DECL_SIZE_UNIT (decl) = size_int (spec_size / BITS_PER_UNIT);
        else
*************** layout_decl (decl, known_align)
*** 313,320 ****
    /* Force alignment required for the data type.
       But if the decl itself wants greater alignment, don't override that.
       Likewise, if the decl is packed, don't override it.  */
!   else if (DECL_ALIGN (decl) == 0
! 	   || (! DECL_PACKED (decl) &&  TYPE_ALIGN (type) > DECL_ALIGN (decl)))
      DECL_ALIGN (decl) = TYPE_ALIGN (type);
  
    /* See if we can use an ordinary integer mode for a bit-field. 
--- 309,317 ----
    /* Force alignment required for the data type.
       But if the decl itself wants greater alignment, don't override that.
       Likewise, if the decl is packed, don't override it.  */
!   if (!(code == FIELD_DECL && DECL_BIT_FIELD (decl))
!       && (DECL_ALIGN (decl) == 0
! 	  || (! DECL_PACKED (decl) &&  TYPE_ALIGN (type) > DECL_ALIGN (decl))))
      DECL_ALIGN (decl) = TYPE_ALIGN (type);
  
    /* See if we can use an ordinary integer mode for a bit-field. 
Index: crash14.C
===================================================================
RCS file: crash14.C
diff -N crash14.C
*** /dev/null	Tue May  5 13:32:27 1998
--- crash14.C	Wed Mar  1 14:29:16 2000
***************
*** 0 ****
--- 1,23 ----
+ // Build don't link:
+ // Special g++ Options: -fnew-abi
+ // Origin: Mark Mitchell <mark@codesourcery.com>
+ 
+ struct S 
+ {
+ };
+ 
+ struct T : public S 
+ {
+ };
+ 
+ struct U : public T 
+ {
+ };
+ 
+ void f (U);
+ 
+ int main ()
+ {
+   U u;
+   f (u);
+ }

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