FreeBSD/contrib/gcc/cp/class.c
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
   accordingly.  If a new vfield was created (because T doesn't have a
   primary base class), then the newly created field is returned.  It
   is not added to the TYPE_FIELDS list; it is the caller's
   responsibility to do that.  Accumulate declared virtual functions
   on VIRTUALS_P.  */
If T needs a pointer to its virtual function table, set TYPE_VFIELD
accordingly.  If a new vfield was created (because T doesn't have a
primary base class), then the newly created field is returned.  It
is not added to the TYPE_FIELDS list; it is the caller's
responsibility to do that.  Accumulate declared virtual functions
on VIRTUALS_P.
If T needs a pointer to its virtual function table set TYPE_VFIELD accordingly . If a new vfield was created ( because T doesn ' t have a primary base class ) then the newly created field is returned . It is not added to the TYPE_FIELDS list ; it is the caller ' s responsibility to do that . Accumulate declared virtual functions on VIRTUALS_P .
static tree
create_vtable_ptr (tree t, tree* virtuals_p)
{
  tree fn;
  for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
    if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
	&& TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
      {
	tree new_virtual = make_node (TREE_LIST);
	BV_FN (new_virtual) = fn;
	BV_DELTA (new_virtual) = integer_zero_node;
	BV_VCALL_INDEX (new_virtual) = NULL_TREE;
	TREE_CHAIN (new_virtual) = *virtuals_p;
	*virtuals_p = new_virtual;
      }
  if (!TYPE_VFIELD (t) && (*virtuals_p || TYPE_CONTAINS_VPTR_P (t)))
    {
      tree field;
      field = build_decl (FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node);
      DECL_VIRTUAL_P (field) = 1;
      DECL_ARTIFICIAL (field) = 1;
      DECL_FIELD_CONTEXT (field) = t;
      DECL_FCONTEXT (field) = t;
      TYPE_VFIELD (t) = field;
      CLASSTYPE_EMPTY_P (t) = 0;
      return field;
    }
  return NULL_TREE;
}
static tree create_vtable_ptr ( tree t , tree * virtuals_p ) { tree fn ; for ( fn = TYPE_METHODS ( t ) ; fn ; fn = TREE_CHAIN ( fn ) ) if ( DECL_VINDEX ( fn ) && ! DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P ( fn ) && TREE_CODE ( DECL_VINDEX ( fn ) ) != INTEGER_CST ) { tree new_virtual = make_node ( TREE_LIST ) ; BV_FN ( new_virtual ) = fn ; BV_DELTA ( new_virtual ) = integer_zero_node ; BV_VCALL_INDEX ( new_virtual ) = NULL_TREE ; TREE_CHAIN ( new_virtual ) = * virtuals_p ; * virtuals_p = new_virtual ; } if ( ! TYPE_VFIELD ( t ) && ( * virtuals_p || TYPE_CONTAINS_VPTR_P ( t ) ) ) { tree field ; field = build_decl ( FIELD_DECL , get_vfield_name ( t ) , vtbl_ptr_type_node ) ; DECL_VIRTUAL_P ( field ) = 1 ; DECL_ARTIFICIAL ( field ) = 1 ; DECL_FIELD_CONTEXT ( field ) = t ; DECL_FCONTEXT ( field ) = t ; TYPE_VFIELD ( t ) = field ; CLASSTYPE_EMPTY_P ( t ) = 0 ; return field ; } return NULL_TREE ; }
If T needs a pointer to its virtual function table, set TYPE_VFIELD
accordingly.
If T needs a pointer to its virtual function table set TYPE_VFIELD accordingly .
/* Collect the virtual functions declared in T.  */ /* If we couldn't find an appropriate base class, create a new field
     here.  Even if there weren't any new virtual functions, we might need a
     new virtual function table if we're supposed to include vptrs in
     all classes that need them.  */ /* We build this decl with vtbl_ptr_type_node, which is a
	 `vtable_entry_type*'.  It might seem more precise to use
	 `vtable_entry_type (*)[N]' where N is the number of virtual
	 functions.  However, that would require the vtable pointer in
	 base classes to have a different type than the vtable pointer
	 in derived classes.  We could make that happen, but that
	 still wouldn't solve all the problems.  In particular, the
	 type-based alias analysis code would decide that assignments
	 to the base class vtable pointer can't alias assignments to
	 the derived class vtable pointer, since they have different
	 types.  Thus, in a derived class destructor, where the base
	 class constructor was inlined, we could generate bad code for
	 setting up the vtable pointer.

	 Therefore, we use one type for all vtable pointers.  We still
	 use a type-correct type; it's just doesn't indicate the array
	 bounds.  That's better than using `void*' or some such; it's
	 cleaner, and it let's the alias analysis code know that these
	 stores cannot alias stores to void*!  */ /* This class is non-empty.  */