diff options
author | David Taylor <taylor@redhat.com> | 1998-12-28 23:06:13 +0000 |
---|---|---|
committer | David Taylor <taylor@redhat.com> | 1998-12-28 23:06:13 +0000 |
commit | 4ef1f4677390c085543fe80eec41b0fe5d58ddca (patch) | |
tree | d0e8320e4871a81733155e8ce653507dd3d64825 /gdb/gdbtypes.c | |
parent | d6fdf61c78fbce1dad62cd1022e606fdaaad4202 (diff) | |
download | fsf-binutils-gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.zip fsf-binutils-gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.tar.gz fsf-binutils-gdb-4ef1f4677390c085543fe80eec41b0fe5d58ddca.tar.bz2 |
hp merge changes -- too numerous to mention here; see ChangeLog and
ChangeLog-gdbtk for details.
Diffstat (limited to 'gdb/gdbtypes.c')
-rw-r--r-- | gdb/gdbtypes.c | 941 |
1 files changed, 927 insertions, 14 deletions
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 8d3f320..c7cabba 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "value.h" #include "demangle.h" #include "complaints.h" +#include "gdbcmd.h" /* These variables point to the objects representing the predefined C data types. */ @@ -61,11 +62,15 @@ struct type *builtin_type_int32; struct type *builtin_type_uint32; struct type *builtin_type_int64; struct type *builtin_type_uint64; +struct type *builtin_type_bool; /* start-sanitize-r5900 */ struct type *builtin_type_int128; struct type *builtin_type_uint128; /* end-sanitize-r5900 */ +int opaque_type_resolution = 1; + + struct extra { char str[128]; int len; }; /* maximum extention is 128! FIXME */ static void add_name PARAMS ((struct extra *, char *)); @@ -107,6 +112,7 @@ alloc_type (objfile) TYPE_CODE (type) = TYPE_CODE_UNDEF; TYPE_OBJFILE (type) = objfile; TYPE_VPTR_FIELDNO (type) = -1; + TYPE_CV_TYPE (type) = type; /* chain back to itself */ return (type); } @@ -288,6 +294,89 @@ lookup_function_type (type) return make_function_type (type, (struct type **)0); } + +/* Make a "c-v" variant of a type -- a type that is identical to the + one supplied except that it may have const or volatile attributes + CNST is a flag for setting the const attribute + VOLTL is a flag for setting the volatile attribute + TYPE is the base type whose variant we are creating. + TYPEPTR, if nonzero, points + to a pointer to memory where the reference type should be stored. + If *TYPEPTR is zero, update it to point to the reference type we return. + We allocate new memory if needed. */ + +struct type * +make_cv_type (cnst, voltl, type, typeptr) + int cnst; + int voltl; + struct type *type; + struct type **typeptr; +{ + register struct type *ntype; /* New type */ + register struct type *tmp_type = type; /* tmp type */ + struct objfile *objfile; + + ntype = TYPE_CV_TYPE (type); + + while (ntype != type) + { + if ((TYPE_CONST (ntype) == cnst) && + (TYPE_VOLATILE (ntype) == voltl)) + { + if (typeptr == 0) + return ntype; + else if (*typeptr == 0) + { + *typeptr = ntype; /* Tracking alloc, and we have new type. */ + return ntype; + } + } + tmp_type = ntype; + ntype = TYPE_CV_TYPE (ntype); + } + + if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */ + { + ntype = alloc_type (TYPE_OBJFILE (type)); + if (typeptr) + *typeptr = ntype; + } + else /* We have storage, but need to reset it. */ + { + ntype = *typeptr; + objfile = TYPE_OBJFILE (ntype); + /* memset ((char *) ntype, 0, sizeof (struct type)); */ + TYPE_OBJFILE (ntype) = objfile; + } + + /* Copy original type */ + memcpy ((char *) ntype, (char *) type, sizeof (struct type)); + /* But zero out fields that shouldn't be copied */ + TYPE_POINTER_TYPE (ntype) = (struct type *) 0; /* Need new pointer kind */ + TYPE_REFERENCE_TYPE (ntype) = (struct type *) 0; /* Need new referene kind */ + /* Note: TYPE_TARGET_TYPE can be left as is */ + + /* Set flags appropriately */ + if (cnst) + TYPE_FLAGS (ntype) |= TYPE_FLAG_CONST; + else + TYPE_FLAGS (ntype) &= ~TYPE_FLAG_CONST; + + if (voltl) + TYPE_FLAGS (ntype) |= TYPE_FLAG_VOLATILE; + else + TYPE_FLAGS (ntype) &= ~TYPE_FLAG_VOLATILE; + + /* Fix the chain of cv variants */ + TYPE_CV_TYPE (ntype) = type; + TYPE_CV_TYPE (tmp_type) = ntype; + + return ntype; +} + + + + /* Implement direct support for MEMBER_TYPE in GNU C++. May need to construct such a type if this is the first use. The TYPE is the type of the member. The DOMAIN is the type @@ -719,21 +808,31 @@ lookup_union (name, block) struct block *block; { register struct symbol *sym; + struct type * t; sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0, (struct symtab **) NULL); if (sym == NULL) - { - error ("No union type named %s.", name); - } - if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION) - { - error ("This context has class, struct or enum %s, not a union.", name); - } - return (SYMBOL_TYPE (sym)); + error ("No union type named %s.", name); + + t = SYMBOL_TYPE(sym); + + if (TYPE_CODE (t) == TYPE_CODE_UNION) + return (t); + + /* C++ unions may come out with TYPE_CODE_CLASS, but we look at + * a further "declared_type" field to discover it is really a union. + */ + if (HAVE_CPLUS_STRUCT (t)) + if (TYPE_DECLARED_TYPE(t) == DECLARED_TYPE_UNION) + return (t); + + /* If we get here, it's not a union */ + error ("This context has class, struct or enum %s, not a union.", name); } + /* Lookup an enum type named "enum NAME", visible in lexical block BLOCK. */ @@ -990,7 +1089,28 @@ check_typedef (type) type = TYPE_TARGET_TYPE (type); } - if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab) + /* If this is a struct/class/union with no fields, then check whether a + full definition exists somewhere else. This is for systems where a + type definition with no fields is issued for such types, instead of + identifying them as stub types in the first place */ + + if (TYPE_IS_OPAQUE (type) && opaque_type_resolution && !currently_reading_symtab) + { + char * name = type_name_no_tag (type); + struct type * newtype; + if (name == NULL) + { + complain (&stub_noname_complaint); + return type; + } + newtype = lookup_transparent_type (name); + if (newtype) + { + memcpy ((char *) type, (char *) newtype, sizeof (struct type)); + } + } + /* Otherwise, rely on the stub flag being set for opaque/stubbed types */ + else if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab) { char* name = type_name_no_tag (type); /* FIXME: shouldn't we separately check the TYPE_NAME and the @@ -1003,13 +1123,10 @@ check_typedef (type) complain (&stub_noname_complaint); return type; } - sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, - (struct symtab **) NULL); + sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0, (struct symtab **) NULL); if (sym) { - memcpy ((char *)type, - (char *)SYMBOL_TYPE(sym), - sizeof (struct type)); + memcpy ((char *)type, (char *)SYMBOL_TYPE(sym), sizeof (struct type)); } } @@ -1498,6 +1615,787 @@ chill_varying_type (type) 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 (base, dclass) + struct type * base; + struct type * dclass; +{ + int i; + + CHECK_TYPEDEF (base); + CHECK_TYPEDEF (dclass); + + if (base == 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 (dclass) + 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 (dclass) + 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. */ + +struct vbase * +virtual_base_list_aux (dclass) + struct type * dclass; +{ + struct vbase * tmp_vbase; + register int i; + + if (TYPE_CODE(dclass) != TYPE_CODE_CLASS) + return NULL; + + 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 (dclass) + 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; + free(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 (dclass) + 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 (dclass) + 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(base, dclass) + 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 = TYPE_VIRTUAL_BASE_LIST(dclass)[0]; + while (vbase) + { + if (vbase == base) + break; + vbase = TYPE_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(base, dclass) + 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 = TYPE_VIRTUAL_BASE_LIST(dclass)[0]; + while (vbase) + { + if (!primary || (virtual_base_index_skip_primaries(vbase, primary) < 0)) + j++; + if (vbase == base) + break; + vbase = TYPE_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 (dclass) + 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 (dclass) + struct type * dclass; +{ + int base; /* index for base classes */ + 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); + + for (fn = 0; fn < TYPE_NFN_FIELDS (dclass); fn++) + for (oi = 0; oi < TYPE_FN_FIELDLIST_LENGTH (dclass, fn); oi++) + if (TYPE_FN_FIELD_VIRTUAL_P (TYPE_FN_FIELDLIST1 (dclass, fn), oi)) + vfuncs++; + + return vfuncs; +} + + + +/* Functions for overload resolution begin here */ + +/* Compare two badness vectors A and B and return the result. + * 0 => A and B are identical + * 1 => A and B are incomparable + * 2 => A is better than B + * 3 => A is worse than B */ + +int +compare_badness (a, b) + struct badness_vector * a; + struct badness_vector * b; +{ + int i; + int tmp; + short found_pos = 0; /* any positives in c? */ + short found_neg = 0; /* any negatives in c? */ + + /* differing lengths => incomparable */ + if (a->length != b->length) + return 1; + + /* Subtract b from a */ + for (i=0; i < a->length; i++) + { + tmp = a->rank[i] - b->rank[i]; + if (tmp > 0) + found_pos = 1; + else if (tmp < 0) + found_neg = 1; + } + + if (found_pos) + { + if (found_neg) + return 1; /* incomparable */ + else + return 3; /* A > B */ + } + else /* no positives */ + { + if (found_neg) + return 2; /* A < B */ + else + return 0; /* A == B */ + } +} + +/* Rank a function by comparing its parameter types (PARMS, length NPARMS), + * to the types of an argument list (ARGS, length NARGS). + * Return a pointer to a badness vector. This has NARGS + 1 entries. */ + +struct badness_vector * +rank_function (parms, nparms, args, nargs) + struct type ** parms; + int nparms; + struct type ** args; + int nargs; +{ + int i; + struct badness_vector * bv; + int min_len = nparms < nargs ? nparms : nargs; + + bv = xmalloc (sizeof (struct badness_vector)); + bv->length = nargs + 1; /* add 1 for the length-match rank */ + bv->rank = xmalloc ((nargs + 1) * sizeof (int)); + + /* First compare the lengths of the supplied lists. + * If there is a mismatch, set it to a high value. */ + + /* pai/1997-06-03 FIXME: when we have debug info about default + * arguments and ellipsis parameter lists, we should consider those + * and rank the length-match more finely. */ + + LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0; + + /* Now rank all the parameters of the candidate function */ + for (i=1; i <= min_len; i++) + bv->rank[i] = rank_one_type (parms[i-1], args[i-1]); + + /* If more arguments than parameters, add dummy entries */ + for (i = min_len +1; i <= nargs; i++) + bv->rank[i] = TOO_FEW_PARAMS_BADNESS; + + return bv; +} + +/* Compare one type (PARM) for compatibility with another (ARG). + * PARM is intended to be the parameter type of a function; and + * ARG is the supplied argument's type. This function tests if + * the latter can be converted to the former. + * + * Return 0 if they are identical types; + * Otherwise, return an integer which corresponds to how compatible + * PARM is to ARG. The higher the return value, the worse the match. + * Generally the "bad" conversions are all uniformly assigned a 100 */ + +int +rank_one_type (parm, arg) + struct type * parm; + struct type * arg; +{ + /* Identical type pointers */ + /* However, this still doesn't catch all cases of same type for arg + * and param. The reason is that builtin types are different from + * the same ones constructed from the object. */ + if (parm == arg) + return 0; + + /* Resolve typedefs */ + if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF) + parm = check_typedef (parm); + if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF) + arg = check_typedef (arg); + + /* Check if identical after resolving typedefs */ + if (parm == arg) + return 0; + +#if 0 + /* Debugging only */ + printf("------ Arg is %s [%d], parm is %s [%d]\n", + TYPE_NAME (arg), TYPE_CODE (arg), TYPE_NAME (parm), TYPE_CODE (parm)); +#endif + + /* x -> y means arg of type x being supplied for parameter of type y */ + + switch (TYPE_CODE (parm)) + { + case TYPE_CODE_PTR: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: + if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID) + return VOID_PTR_CONVERSION_BADNESS; + else + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + case TYPE_CODE_ARRAY: + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + case TYPE_CODE_FUNC: + return rank_one_type (TYPE_TARGET_TYPE (parm), arg); + case TYPE_CODE_INT: + case TYPE_CODE_ENUM: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + return POINTER_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_ARRAY: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: + case TYPE_CODE_ARRAY: + return rank_one_type (TYPE_TARGET_TYPE (parm), TYPE_TARGET_TYPE (arg)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_FUNC: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_PTR: /* funcptr -> func */ + return rank_one_type (parm, TYPE_TARGET_TYPE (arg)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + case TYPE_CODE_INT: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm)) + { + /* Deal with signed, unsigned, and plain chars and + signed and unsigned ints */ + if (TYPE_NOSIGN (parm)) + { + /* This case only for character types */ + if (TYPE_NOSIGN (arg)) /* plain char -> plain char */ + return 0; + else + return INTEGER_COERCION_BADNESS; /* signed/unsigned char -> plain char */ + } + else if (TYPE_UNSIGNED (parm)) + { + if (TYPE_UNSIGNED (arg)) + { + if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg))) + return 0; /* unsigned int -> unsigned int, or unsigned long -> unsigned long */ + else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long")) + return INTEGER_PROMOTION_BADNESS; /* unsigned int -> unsigned long */ + else + return INTEGER_COERCION_BADNESS; /* unsigned long -> unsigned int */ + } + else + { + if (!strcmp (TYPE_NAME (arg), "long") && !strcmp (TYPE_NAME (parm), "int")) + return INTEGER_COERCION_BADNESS; /* signed long -> unsigned int */ + else + return INTEGER_CONVERSION_BADNESS; /* signed int/long -> unsigned int/long */ + } + } + else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg)) + { + if (!strcmp (TYPE_NAME (parm), TYPE_NAME (arg))) + return 0; + else if (!strcmp (TYPE_NAME (arg), "int") && !strcmp (TYPE_NAME (parm), "long")) + return INTEGER_PROMOTION_BADNESS; + else + return INTEGER_COERCION_BADNESS; + } + else + return INTEGER_COERCION_BADNESS; + } + else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return INTEGER_PROMOTION_BADNESS; + else + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_ENUM: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + return INTEGER_PROMOTION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_PTR: + return NS_POINTER_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_ENUM: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_CHAR: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_INT: + if (TYPE_LENGTH (arg) > TYPE_LENGTH (parm)) + return INTEGER_COERCION_BADNESS; + else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return INTEGER_PROMOTION_BADNESS; + /* >>> !! else fall through !! <<< */ + case TYPE_CODE_CHAR: + /* Deal with signed, unsigned, and plain chars for C++ + and with int cases falling through from previous case */ + if (TYPE_NOSIGN (parm)) + { + if (TYPE_NOSIGN (arg)) + return 0; + else + return INTEGER_COERCION_BADNESS; + } + else if (TYPE_UNSIGNED (parm)) + { + if (TYPE_UNSIGNED (arg)) + return 0; + else + return INTEGER_PROMOTION_BADNESS; + } + else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg)) + return 0; + else + return INTEGER_COERCION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_RANGE: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + return INTEGER_COERCION_BADNESS; + case TYPE_CODE_FLT: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_BOOL: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_INT: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + case TYPE_CODE_FLT: + case TYPE_CODE_PTR: + return BOOLEAN_CONVERSION_BADNESS; + case TYPE_CODE_BOOL: + return 0; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_FLT: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_FLT: + if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm)) + return FLOAT_PROMOTION_BADNESS; + else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm)) + return 0; + else + return FLOAT_CONVERSION_BADNESS; + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_ENUM: + case TYPE_CODE_RANGE: + case TYPE_CODE_CHAR: + return INT_FLOAT_CONVERSION_BADNESS; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_COMPLEX: + switch (TYPE_CODE (arg)) + { /* Strictly not needed for C++, but... */ + case TYPE_CODE_FLT: + return FLOAT_PROMOTION_BADNESS; + case TYPE_CODE_COMPLEX: + return 0; + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_STRUCT: + /* currently same as TYPE_CODE_CLASS */ + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_STRUCT: + /* Check for derivation */ + if (is_ancestor (parm, arg)) + return BASE_CONVERSION_BADNESS; + /* else fall through */ + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_UNION: + switch (TYPE_CODE (arg)) + { + case TYPE_CODE_UNION: + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_MEMBER: + switch (TYPE_CODE (arg)) + { + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_METHOD: + switch (TYPE_CODE (arg)) + { + + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_REF: + switch (TYPE_CODE (arg)) + { + + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + + break; + case TYPE_CODE_SET: + switch (TYPE_CODE (arg)) + { + /* Not in C++ */ + case TYPE_CODE_SET: + return rank_one_type (TYPE_FIELD_TYPE (parm, 0), TYPE_FIELD_TYPE (arg, 0)); + default: + return INCOMPATIBLE_TYPE_BADNESS; + } + break; + case TYPE_CODE_VOID: + default: + return INCOMPATIBLE_TYPE_BADNESS; + } /* switch (TYPE_CODE (arg)) */ +} + + +/* End of functions for overload resolution */ + + + #if MAINTENANCE_CMDS static void @@ -1887,6 +2785,8 @@ build_gdbtypes () init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0, "char", (struct objfile *) NULL); + TYPE_FLAGS (builtin_type_char) |= TYPE_FLAG_NOSIGN; + builtin_type_signed_char = init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT, 0, @@ -1985,6 +2885,19 @@ build_gdbtypes () init_type (TYPE_CODE_INT, 64 / 8, TYPE_FLAG_UNSIGNED, "uint64_t", (struct objfile *) NULL); + builtin_type_bool = + init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT, + 0, + "bool", (struct objfile *) NULL); + + /* Add user knob for controlling resolution of opaque types */ + add_show_from_set + (add_set_cmd ("opaque-type-resolution", class_support, var_boolean, (char *)&opaque_type_resolution, + "Set resolution of opaque struct/class/union types (if set before loading symbols).", + &setlist), + &showlist); + opaque_type_resolution = 1; + /* start-sanitize-r5900 */ builtin_type_int128 = init_type (TYPE_CODE_INT, 128 / 8, |