FreeBSD/contrib/gcc/cp/class.c
/* 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
   is returned.  Otherwise, returns zero.  */
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
is returned.  Otherwise, returns zero.
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 is returned . Otherwise returns zero .
static int
walk_subobject_offsets (tree type,
			subobject_offset_fn f,
			tree offset,
			splay_tree offsets,
			tree max_offset,
			int vbases_p)
{
  int r = 0;
  tree type_binfo = NULL_TREE;
  if (max_offset && INT_CST_LT (max_offset, offset))
    return 0;
  if (type == error_mark_node)
    return 0;
  if (!TYPE_P (type))
    {
      if (abi_version_at_least (2))
	type_binfo = type;
      type = BINFO_TYPE (type);
    }
  if (CLASS_TYPE_P (type))
    {
      tree field;
      tree binfo;
      int i;
      if (!CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
	return 0;
      r = (*f) (type, offset, offsets);
      if (r)
	return r;
      if (!type_binfo)
	type_binfo = TYPE_BINFO (type);
      for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, binfo); i++)
	{
	  tree binfo_offset;
	  if (abi_version_at_least (2)
	      && BINFO_VIRTUAL_P (binfo))
	    continue;
	  if (!vbases_p
	      && BINFO_VIRTUAL_P (binfo)
	      && !BINFO_PRIMARY_P (binfo))
	    continue;
	  if (!abi_version_at_least (2))
	    binfo_offset = size_binop (PLUS_EXPR,
				       offset,
				       BINFO_OFFSET (binfo));
	  else
	    {
	      tree orig_binfo;
	      orig_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
	      binfo_offset = size_binop (PLUS_EXPR,
					 offset,
					 BINFO_OFFSET (orig_binfo));
	    }
	  r = walk_subobject_offsets (binfo,
				      f,
				      binfo_offset,
				      offsets,
				      max_offset,
				      (abi_version_at_least (2)
				       ? 0 : vbases_p));
	  if (r)
	    return r;
	}
      if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
	{
	  unsigned ix;
	  VEC(tree,gc) *vbases;
	  if (vbases_p)
	    for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
		 VEC_iterate (tree, vbases, ix, binfo); ix++)
	      {
		r = walk_subobject_offsets (binfo,
					    f,
					    size_binop (PLUS_EXPR,
							offset,
							BINFO_OFFSET (binfo)),
					    offsets,
					    max_offset,
					    0);
		if (r)
		  return r;
	      }
	  else
	    {
	      tree vbase = get_primary_binfo (type_binfo);
	      if (vbase && BINFO_VIRTUAL_P (vbase)
		  && BINFO_PRIMARY_P (vbase)
		  && BINFO_INHERITANCE_CHAIN (vbase) == type_binfo)
		{
		  r = (walk_subobject_offsets
		       (vbase, f, offset,
			offsets, max_offset, 0));
		  if (r)
		    return r;
		}
	    }
	}
      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
	if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
	  {
	    tree field_offset;
	    if (abi_version_at_least (2))
	      field_offset = byte_position (field);
	    else
	      field_offset = DECL_FIELD_OFFSET (field);
	    r = walk_subobject_offsets (TREE_TYPE (field),
					f,
					size_binop (PLUS_EXPR,
						    offset,
						    field_offset),
					offsets,
					max_offset,
					1);
	    if (r)
	      return r;
	  }
    }
  else if (TREE_CODE (type) == ARRAY_TYPE)
    {
      tree element_type = strip_array_types (type);
      tree domain = TYPE_DOMAIN (type);
      tree index;
      if (!CLASS_TYPE_P (element_type)
	  || !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
	return 0;
      for (index = size_zero_node;
	   (abi_version_at_least (2)
	    ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
	    : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
	   index = size_binop (PLUS_EXPR, index, size_one_node))
	{
	  r = walk_subobject_offsets (TREE_TYPE (type),
				      f,
				      offset,
				      offsets,
				      max_offset,
				      1);
	  if (r)
	    return r;
	  offset = size_binop (PLUS_EXPR, offset,
			       TYPE_SIZE_UNIT (TREE_TYPE (type)));
	  if (max_offset && INT_CST_LT (max_offset, offset))
	    break;
	}
    }
  return 0;
}
static int walk_subobject_offsets ( tree type , subobject_offset_fn f , tree offset , splay_tree offsets , tree max_offset , int vbases_p ) { int r = 0 ; tree type_binfo = NULL_TREE ; if ( max_offset && INT_CST_LT ( max_offset , offset ) ) return 0 ; if ( type == error_mark_node ) return 0 ; if ( ! TYPE_P ( type ) ) { if ( abi_version_at_least ( 2 ) ) type_binfo = type ; type = BINFO_TYPE ( type ) ; } if ( CLASS_TYPE_P ( type ) ) { tree field ; tree binfo ; int i ; if ( ! CLASSTYPE_CONTAINS_EMPTY_CLASS_P ( type ) ) return 0 ; r = ( * f ) ( type , offset , offsets ) ; if ( r ) return r ; if ( ! type_binfo ) type_binfo = TYPE_BINFO ( type ) ; for ( i = 0 ; BINFO_BASE_ITERATE ( type_binfo , i , binfo ) ; i ++ ) { tree binfo_offset ; if ( abi_version_at_least ( 2 ) && BINFO_VIRTUAL_P ( binfo ) ) continue ; if ( ! vbases_p && BINFO_VIRTUAL_P ( binfo ) && ! BINFO_PRIMARY_P ( binfo ) ) continue ; if ( ! abi_version_at_least ( 2 ) ) binfo_offset = size_binop ( PLUS_EXPR , offset , BINFO_OFFSET ( binfo ) ) ; else { tree orig_binfo ; orig_binfo = BINFO_BASE_BINFO ( TYPE_BINFO ( type ) , i ) ; binfo_offset = size_binop ( PLUS_EXPR , offset , BINFO_OFFSET ( orig_binfo ) ) ; } r = walk_subobject_offsets ( binfo , f , binfo_offset , offsets , max_offset , ( abi_version_at_least ( 2 ) ? 0 : vbases_p ) ) ; if ( r ) return r ; } if ( abi_version_at_least ( 2 ) && CLASSTYPE_VBASECLASSES ( type ) ) { unsigned ix ; VEC ( tree , gc ) * vbases ; if ( vbases_p ) for ( vbases = CLASSTYPE_VBASECLASSES ( type ) , ix = 0 ; VEC_iterate ( tree , vbases , ix , binfo ) ; ix ++ ) { r = walk_subobject_offsets ( binfo , f , size_binop ( PLUS_EXPR , offset , BINFO_OFFSET ( binfo ) ) , offsets , max_offset , 0 ) ; if ( r ) return r ; } else { tree vbase = get_primary_binfo ( type_binfo ) ; if ( vbase && BINFO_VIRTUAL_P ( vbase ) && BINFO_PRIMARY_P ( vbase ) && BINFO_INHERITANCE_CHAIN ( vbase ) == type_binfo ) { r = ( walk_subobject_offsets ( vbase , f , offset , offsets , max_offset , 0 ) ) ; if ( r ) return r ; } } } for ( field = TYPE_FIELDS ( type ) ; field ; field = TREE_CHAIN ( field ) ) if ( TREE_CODE ( field ) == FIELD_DECL && ! DECL_ARTIFICIAL ( field ) ) { tree field_offset ; if ( abi_version_at_least ( 2 ) ) field_offset = byte_position ( field ) ; else field_offset = DECL_FIELD_OFFSET ( field ) ; r = walk_subobject_offsets ( TREE_TYPE ( field ) , f , size_binop ( PLUS_EXPR , offset , field_offset ) , offsets , max_offset , 1 ) ; if ( r ) return r ; } } else if ( TREE_CODE ( type ) == ARRAY_TYPE ) { tree element_type = strip_array_types ( type ) ; tree domain = TYPE_DOMAIN ( type ) ; tree index ; if ( ! CLASS_TYPE_P ( element_type ) || ! CLASSTYPE_CONTAINS_EMPTY_CLASS_P ( element_type ) ) return 0 ; for ( index = size_zero_node ; ( abi_version_at_least ( 2 ) ? ! INT_CST_LT ( TYPE_MAX_VALUE ( domain ) , index ) : INT_CST_LT ( index , TYPE_MAX_VALUE ( domain ) ) ) ; index = size_binop ( PLUS_EXPR , index , size_one_node ) ) { r = walk_subobject_offsets ( TREE_TYPE ( type ) , f , offset , offsets , max_offset , 1 ) ; if ( r ) return r ; offset = size_binop ( PLUS_EXPR , offset , TYPE_SIZE_UNIT ( TREE_TYPE ( type ) ) ) ; if ( max_offset && INT_CST_LT ( max_offset , offset ) ) break ; } } return 0 ; }
Walk through all the subobjects of TYPE (located at OFFSET).
Walk through all the subobjects of TYPE ( located at OFFSET ) .
/* If this OFFSET is bigger than the MAX_OFFSET, then we should
     stop.  */ /* Avoid recursing into objects that are not interesting.  */ /* Record the location of TYPE.  */ /* Iterate through the direct base classes of TYPE.  */ /* We cannot rely on BINFO_OFFSET being set for the base
		 class yet, but the offsets for direct non-virtual
		 bases can be calculated by going back to the TYPE.  */ /*vbases_p=*/ /* Iterate through the virtual base classes of TYPE.  In G++
	     3.2, we included virtual bases in the direct base class
	     loop above, which results in incorrect results; the
	     correct offsets for virtual bases are only known when
	     working with the most derived type.  */ /*vbases_p=*/ /* We still have to walk the primary base, if it is
		 virtual.  (If it is non-virtual, then it was walked
		 above.)  */ /*vbases_p=*/ /* Iterate through the fields of TYPE.  */ /* In G++ 3.2, DECL_FIELD_OFFSET was used.  */ /*vbases_p=*/ /* Avoid recursing into objects that are not interesting.  */ /* Step through each of the elements in the array.  */ /* G++ 3.2 had an off-by-one error here.  */ /*vbases_p=*/ /* If this new OFFSET is bigger than the MAX_OFFSET, then
	     there's no point in iterating through the remaining
	     elements of the array.  */