C++ PATCH: Another layout bug

Mark Mitchell mark@codesourcery.com
Mon Nov 25 23:26:00 GMT 2002


Jeffrey and Ricardo keep finding bugs.

This patch fixes a layout bug (we were missing yet more empty base
conflicts).  I absolutely hate empty bases at this point; I cannot
figure out why it is so hard to get this stuff right, but our crazy
binfo data structures sure don't help.  Post 3.3, we'll have to look
at eliminating that non-canonical base madness once and for all.

Tested on i686-pc-linux-gnu, applied on the mainline.

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

2002-11-25  Mark Mitchell  <mark@codesourcery.com>

	* class.c (walk_subobject_offsets): Fix thinko.
	(build_base_field): Record offsets of empty bases in primary
	virtual bases.
	(layout_class_type): Record offsets of empty bases in fields.

2002-11-25  Mark Mitchell  <mark@codesourcery.com>

	* testsuite/g++.dg/abi/empty11.C: New test.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.495
diff -c -5 -p -r1.495 class.c
*** cp/class.c	24 Nov 2002 23:26:10 -0000	1.495
--- cp/class.c	26 Nov 2002 07:12:50 -0000
*************** check_subobject_offset (type, offset, of
*** 3389,3400 ****
    return 0;
  }
  
  /* Walk through all the subobjects of TYPE (located at OFFSET).  Call
     F for every subobject, passing it the type, offset, and table of
!    OFFSETS.  If VBASES_P is nonzero, then even virtual non-primary
!    bases should be traversed; otherwise, they are ignored.  
  
     If MAX_OFFSET is non-NULL, then subobjects with an offset greater
     than MAX_OFFSET will not be walked.
  
     If F returns a nonzero value, the traversal ceases, and that value
--- 3389,3400 ----
    return 0;
  }
  
  /* Walk through all the subobjects of TYPE (located at OFFSET).  Call
     F for every subobject, passing it the type, offset, and table of
!    OFFSETS.  If VBASES_P is one, then virtual non-primary bases should
!    be traversed.
  
     If MAX_OFFSET is non-NULL, then subobjects with an offset greater
     than MAX_OFFSET will not be walked.
  
     If F returns a nonzero value, the traversal ceases, and that value
*************** walk_subobject_offsets (type, f, offset,
*** 3478,3487 ****
--- 3478,3489 ----
  						      offset,
  						      BINFO_OFFSET (binfo)),
  					  offsets,
  					  max_offset,
  					  /*vbases_p=*/0);
+ 	      if (r)
+ 		return r;
  	    }
  	}
  
        /* Iterate through the fields of TYPE.  */
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
*************** build_base_field (record_layout_info rli
*** 3849,3858 ****
--- 3851,3881 ----
    record_subobject_offsets (BINFO_TYPE (binfo), 
  			    BINFO_OFFSET (binfo),
  			    offsets, 
  			    /*vbases_p=*/0);
  
+   if (abi_version_at_least (2))
+     {
+       /* If BINFO has a primary virtual base that is really going to
+ 	 be located at the same offset as binfo, it will have been
+ 	 skipped -- but we should record empty bases from there too.  */
+       while (true) 
+ 	{
+ 	  tree b;
+ 
+ 	  b = get_primary_binfo (binfo);
+ 	  if (!b || BINFO_PRIMARY_BASE_OF (b) != binfo)
+ 	    break;
+ 	  if (TREE_VIA_VIRTUAL (b))
+ 	    record_subobject_offsets (BINFO_TYPE (b),
+ 				      BINFO_OFFSET (b),
+ 				      offsets,
+ 				      /*vbases_p=*/0);
+ 	  binfo = b;
+ 	}
+     }
+ 
    return next_field;
  }
  
  /* Layout all of the non-virtual base classes.  Record empty
     subobjects in OFFSETS.  T is the most derived type.  Return nonzero
*************** layout_class_type (tree t, tree *virtual
*** 4937,4946 ****
--- 4960,4976 ----
        else
  	padding = NULL_TREE;
  
        layout_nonempty_base_or_field (rli, field, NULL_TREE,
  				     empty_base_offsets);
+ 
+       /* Remember the location of any empty classes in FIELD.  */
+       if (abi_version_at_least (2))
+ 	record_subobject_offsets (TREE_TYPE (field), 
+ 				  byte_position(field),
+ 				  empty_base_offsets,
+ 				  /*vbases_p=*/1);
  
        /* If a bit-field does not immediately follow another bit-field,
  	 and yet it starts in the middle of a byte, we have failed to
  	 comply with the ABI.  */
        if (warn_abi
Index: testsuite/g++.dg/abi/empty11.C
===================================================================
RCS file: testsuite/g++.dg/abi/empty11.C
diff -N testsuite/g++.dg/abi/empty11.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/empty11.C	26 Nov 2002 07:12:54 -0000
***************
*** 0 ****
--- 1,19 ----
+ // { dg-do run }
+ // { dg-options "-w -fabi-version=0" }
+ 
+ struct E {};
+ struct E2 : public E {};
+ struct E3 : public E, public E2 {};
+ struct E4 : public E, public E2, public E3 { };
+ struct E5 : public E, public E2, public E3, public E4 {};
+ 
+ struct S : public virtual E5 {
+   E e;
+ };
+ 
+ S s;
+ 
+ int main () {
+   if ((char*)(E4*)&s - (char*)&s == 0)
+     return 1;
+ }



More information about the Gcc-patches mailing list