+
+ /* If this is the first time we need a fundamental type for this objfile
+ then we need to initialize the vector of type pointers. */
+
+ if (objfile->fundamental_types == NULL)
+ {
+ nbytes = FT_NUM_MEMBERS * sizeof (struct type *);
+ objfile->fundamental_types = (struct type **)
+ obstack_alloc (&objfile->type_obstack, nbytes);
+ memset ((char *) objfile->fundamental_types, 0, nbytes);
+ OBJSTAT (objfile, n_types += FT_NUM_MEMBERS);
+ }
+
+ /* Look for this particular type in the fundamental type vector. If one is
+ not found, create and install one appropriate for the current language. */
+
+ typep = objfile->fundamental_types + typeid;
+ if (*typep == NULL)
+ {
+ *typep = create_fundamental_type (objfile, typeid);
+ }
+
+ return (*typep);
+}
+
+int
+can_dereference (struct type *t)
+{
+ /* FIXME: Should we return true for references as well as pointers? */
+ CHECK_TYPEDEF (t);
+ return
+ (t != NULL
+ && TYPE_CODE (t) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (t)) != TYPE_CODE_VOID);
+}
+
+int
+is_integral_type (struct type *t)
+{
+ CHECK_TYPEDEF (t);
+ return
+ ((t != NULL)
+ && ((TYPE_CODE (t) == TYPE_CODE_INT)
+ || (TYPE_CODE (t) == TYPE_CODE_ENUM)
+ || (TYPE_CODE (t) == TYPE_CODE_CHAR)
+ || (TYPE_CODE (t) == TYPE_CODE_RANGE)
+ || (TYPE_CODE (t) == TYPE_CODE_BOOL)));
+}
+
+/* Chill varying string and arrays are represented as follows:
+
+ struct { int __var_length; ELEMENT_TYPE[MAX_SIZE] __var_data};
+
+ Return true if TYPE is such a Chill varying type. */
+
+int
+chill_varying_type (struct type *type)
+{
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ || TYPE_NFIELDS (type) != 2
+ || strcmp (TYPE_FIELD_NAME (type, 0), "__var_length") != 0)
+ return 0;
+ return 1;
+}
+
+/* Check whether BASE is an ancestor or base class or DCLASS
+ Return 1 if so, and 0 if not.
+ Note: callers may want to check for identity of the types before
+ calling this function -- identical types are considered to satisfy
+ the ancestor relationship even if they're identical */
+
+int
+is_ancestor (struct type *base, struct type *dclass)
+{
+ int i;
+
+ CHECK_TYPEDEF (base);
+ CHECK_TYPEDEF (dclass);
+
+ if (base == dclass)
+ return 1;
+ if (TYPE_NAME (base) && TYPE_NAME (dclass) &&
+ !strcmp (TYPE_NAME (base), TYPE_NAME (dclass)))
+ return 1;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ if (is_ancestor (base, TYPE_BASECLASS (dclass, i)))
+ return 1;
+
+ return 0;
+}
+
+
+
+/* See whether DCLASS has a virtual table. This routine is aimed at
+ the HP/Taligent ANSI C++ runtime model, and may not work with other
+ runtime models. Return 1 => Yes, 0 => No. */
+
+int
+has_vtable (struct type *dclass)
+{
+ /* In the HP ANSI C++ runtime model, a class has a vtable only if it
+ has virtual functions or virtual bases. */
+
+ register int i;
+
+ if (TYPE_CODE (dclass) != TYPE_CODE_CLASS)
+ return 0;
+
+ /* First check for the presence of virtual bases */
+ if (TYPE_FIELD_VIRTUAL_BITS (dclass))
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ if (B_TST (TYPE_FIELD_VIRTUAL_BITS (dclass), i))
+ return 1;
+
+ /* Next check for virtual functions */
+ if (TYPE_FN_FIELDLISTS (dclass))
+ for (i = 0; i < TYPE_NFN_FIELDS (dclass); i++)
+ if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (dclass, i), 0))
+ return 1;
+
+ /* Recurse on non-virtual bases to see if any of them needs a vtable */
+ if (TYPE_FIELD_VIRTUAL_BITS (dclass))
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ if ((!B_TST (TYPE_FIELD_VIRTUAL_BITS (dclass), i)) &&
+ (has_vtable (TYPE_FIELD_TYPE (dclass, i))))
+ return 1;
+
+ /* Well, maybe we don't need a virtual table */
+ return 0;
+}
+
+/* Return a pointer to the "primary base class" of DCLASS.
+
+ A NULL return indicates that DCLASS has no primary base, or that it
+ couldn't be found (insufficient information).
+
+ This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+ and may not work with other runtime models. */
+
+struct type *
+primary_base_class (struct type *dclass)
+{
+ /* In HP ANSI C++'s runtime model, a "primary base class" of a class
+ is the first directly inherited, non-virtual base class that
+ requires a virtual table */
+
+ register int i;
+
+ if (TYPE_CODE (dclass) != TYPE_CODE_CLASS)
+ return NULL;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ if (!TYPE_FIELD_VIRTUAL (dclass, i) &&
+ has_vtable (TYPE_FIELD_TYPE (dclass, i)))
+ return TYPE_FIELD_TYPE (dclass, i);
+
+ return NULL;
+}
+
+/* Global manipulated by virtual_base_list[_aux]() */
+
+static struct vbase *current_vbase_list = NULL;
+
+/* Return a pointer to a null-terminated list of struct vbase
+ items. The vbasetype pointer of each item in the list points to the
+ type information for a virtual base of the argument DCLASS.
+
+ Helper function for virtual_base_list().
+ Note: the list goes backward, right-to-left. virtual_base_list()
+ copies the items out in reverse order. */
+
+static void
+virtual_base_list_aux (struct type *dclass)
+{
+ struct vbase *tmp_vbase;
+ register int i;
+
+ if (TYPE_CODE (dclass) != TYPE_CODE_CLASS)
+ return;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
+ {
+ /* Recurse on this ancestor, first */
+ virtual_base_list_aux (TYPE_FIELD_TYPE (dclass, i));
+
+ /* If this current base is itself virtual, add it to the list */
+ if (BASETYPE_VIA_VIRTUAL (dclass, i))
+ {
+ struct type *basetype = TYPE_FIELD_TYPE (dclass, i);
+
+ /* Check if base already recorded */
+ tmp_vbase = current_vbase_list;
+ while (tmp_vbase)
+ {
+ if (tmp_vbase->vbasetype == basetype)
+ break; /* found it */
+ tmp_vbase = tmp_vbase->next;
+ }
+
+ if (!tmp_vbase) /* normal exit from loop */
+ {
+ /* Allocate new item for this virtual base */
+ tmp_vbase = (struct vbase *) xmalloc (sizeof (struct vbase));
+
+ /* Stick it on at the end of the list */
+ tmp_vbase->vbasetype = basetype;
+ tmp_vbase->next = current_vbase_list;
+ current_vbase_list = tmp_vbase;
+ }
+ } /* if virtual */
+ } /* for loop over bases */
+}
+
+
+/* Compute the list of virtual bases in the right order. Virtual
+ bases are laid out in the object's memory area in order of their
+ occurrence in a depth-first, left-to-right search through the
+ ancestors.
+
+ Argument DCLASS is the type whose virtual bases are required.
+ Return value is the address of a null-terminated array of pointers
+ to struct type items.
+
+ This routine is aimed at the HP/Taligent ANSI C++ runtime model,
+ and may not work with other runtime models.
+
+ This routine merely hands off the argument to virtual_base_list_aux()
+ and then copies the result into an array to save space. */
+
+struct type **
+virtual_base_list (struct type *dclass)
+{
+ register struct vbase *tmp_vbase;
+ register struct vbase *tmp_vbase_2;
+ register int i;
+ int count;
+ struct type **vbase_array;
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux (dclass);
+
+ for (i = 0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+ /* no body */ ;
+
+ count = i;
+
+ vbase_array = (struct type **) xmalloc ((count + 1) * sizeof (struct type *));
+
+ for (i = count - 1, tmp_vbase = current_vbase_list; i >= 0; i--, tmp_vbase = tmp_vbase->next)
+ vbase_array[i] = tmp_vbase->vbasetype;
+
+ /* Get rid of constructed chain */
+ tmp_vbase_2 = tmp_vbase = current_vbase_list;
+ while (tmp_vbase)
+ {
+ tmp_vbase = tmp_vbase->next;
+ xfree (tmp_vbase_2);
+ tmp_vbase_2 = tmp_vbase;
+ }
+
+ vbase_array[count] = NULL;
+ return vbase_array;
+}
+
+/* Return the length of the virtual base list of the type DCLASS. */
+
+int
+virtual_base_list_length (struct type *dclass)
+{
+ register int i;
+ register struct vbase *tmp_vbase;
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux (dclass);
+
+ for (i = 0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; i++, tmp_vbase = tmp_vbase->next)
+ /* no body */ ;
+ return i;
+}
+
+/* Return the number of elements of the virtual base list of the type
+ DCLASS, ignoring those appearing in the primary base (and its
+ primary base, recursively). */
+
+int
+virtual_base_list_length_skip_primaries (struct type *dclass)
+{
+ register int i;
+ register struct vbase *tmp_vbase;
+ struct type *primary;
+
+ primary = TYPE_RUNTIME_PTR (dclass) ? TYPE_PRIMARY_BASE (dclass) : NULL;
+
+ if (!primary)
+ return virtual_base_list_length (dclass);
+
+ current_vbase_list = NULL;
+ virtual_base_list_aux (dclass);
+
+ for (i = 0, tmp_vbase = current_vbase_list; tmp_vbase != NULL; tmp_vbase = tmp_vbase->next)
+ {
+ if (virtual_base_index (tmp_vbase->vbasetype, primary) >= 0)
+ continue;
+ i++;
+ }
+ return i;
+}
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+ class of DCLASS, in the latter's virtual base list. A return of -1
+ indicates "not found" or a problem. */
+
+int
+virtual_base_index (struct type *base, struct type *dclass)
+{
+ register struct type *vbase;
+ register int i;
+
+ if ((TYPE_CODE (dclass) != TYPE_CODE_CLASS) ||
+ (TYPE_CODE (base) != TYPE_CODE_CLASS))
+ return -1;
+
+ i = 0;
+ vbase = virtual_base_list (dclass)[0];
+ while (vbase)
+ {
+ if (vbase == base)
+ break;
+ vbase = virtual_base_list (dclass)[++i];
+ }
+
+ return vbase ? i : -1;
+}
+
+
+
+/* Return the index (position) of type BASE, which is a virtual base
+ class of DCLASS, in the latter's virtual base list. Skip over all
+ bases that may appear in the virtual base list of the primary base
+ class of DCLASS (recursively). A return of -1 indicates "not
+ found" or a problem. */
+
+int
+virtual_base_index_skip_primaries (struct type *base, struct type *dclass)
+{
+ register struct type *vbase;
+ register int i, j;
+ struct type *primary;
+
+ if ((TYPE_CODE (dclass) != TYPE_CODE_CLASS) ||
+ (TYPE_CODE (base) != TYPE_CODE_CLASS))
+ return -1;
+
+ primary = TYPE_RUNTIME_PTR (dclass) ? TYPE_PRIMARY_BASE (dclass) : NULL;
+
+ j = -1;
+ i = 0;
+ vbase = virtual_base_list (dclass)[0];
+ while (vbase)
+ {
+ if (!primary || (virtual_base_index_skip_primaries (vbase, primary) < 0))
+ j++;
+ if (vbase == base)
+ break;
+ vbase = virtual_base_list (dclass)[++i];
+ }
+
+ return vbase ? j : -1;
+}
+
+/* Return position of a derived class DCLASS in the list of
+ * primary bases starting with the remotest ancestor.
+ * Position returned is 0-based. */
+
+int
+class_index_in_primary_list (struct type *dclass)
+{
+ struct type *pbc; /* primary base class */
+
+ /* Simply recurse on primary base */
+ pbc = TYPE_PRIMARY_BASE (dclass);
+ if (pbc)
+ return 1 + class_index_in_primary_list (pbc);
+ else
+ return 0;
+}
+
+/* Return a count of the number of virtual functions a type has.
+ * This includes all the virtual functions it inherits from its
+ * base classes too.
+ */
+
+/* pai: FIXME This doesn't do the right thing: count redefined virtual
+ * functions only once (latest redefinition)
+ */
+
+int
+count_virtual_fns (struct type *dclass)
+{
+ int fn, oi; /* function and overloaded instance indices */
+ int vfuncs; /* count to return */
+
+ /* recurse on bases that can share virtual table */
+ struct type *pbc = primary_base_class (dclass);
+ if (pbc)
+ vfuncs = count_virtual_fns (pbc);