#include "hashtab.h"
+/* Initialize BADNESS constants. */
+
+const struct rank LENGTH_MISMATCH_BADNESS = {100,0};
+
+const struct rank TOO_FEW_PARAMS_BADNESS = {100,0};
+const struct rank INCOMPATIBLE_TYPE_BADNESS = {100,0};
+
+const struct rank EXACT_MATCH_BADNESS = {0,0};
+
+const struct rank INTEGER_PROMOTION_BADNESS = {1,0};
+const struct rank FLOAT_PROMOTION_BADNESS = {1,0};
+const struct rank BASE_PTR_CONVERSION_BADNESS = {1,0};
+const struct rank INTEGER_CONVERSION_BADNESS = {2,0};
+const struct rank FLOAT_CONVERSION_BADNESS = {2,0};
+const struct rank INT_FLOAT_CONVERSION_BADNESS = {2,0};
+const struct rank VOID_PTR_CONVERSION_BADNESS = {2,0};
+const struct rank BOOL_PTR_CONVERSION_BADNESS = {3,0};
+const struct rank BASE_CONVERSION_BADNESS = {2,0};
+const struct rank REFERENCE_CONVERSION_BADNESS = {2,0};
+
+const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
+
/* Floatformat pairs. */
const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = {
&floatformat_ieee_half_big,
}
}
+/* Assuming TYPE is a simple, non-empty array type, compute its upper
+ and lower bound. Save the low bound into LOW_BOUND if not NULL.
+ Save the high bound into HIGH_BOUND if not NULL.
+
+ Return 1 if the operation was successful. Return zero otherwise,
+ in which case the values of LOW_BOUND and HIGH_BOUNDS are unmodified.
+
+ We now simply use get_discrete_bounds call to get the values
+ of the low and high bounds.
+ get_discrete_bounds can return three values:
+ 1, meaning that index is a range,
+ 0, meaning that index is a discrete type,
+ or -1 for failure. */
+
+int
+get_array_bounds (struct type *type, LONGEST *low_bound, LONGEST *high_bound)
+{
+ struct type *index = TYPE_INDEX_TYPE (type);
+ LONGEST low = 0;
+ LONGEST high = 0;
+ int res;
+
+ if (index == NULL)
+ return 0;
+
+ res = get_discrete_bounds (index, &low, &high);
+ if (res == -1)
+ return 0;
+
+ /* Check if the array bounds are undefined. */
+ if (res == 1
+ && ((low_bound && TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type))
+ || (high_bound && TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))))
+ return 0;
+
+ if (low_bound)
+ *low_bound = low;
+
+ if (high_bound)
+ *high_bound = high;
+
+ return 1;
+}
+
/* Create an array type using either a blank type supplied in
RESULT_TYPE, or creating a new type, inheriting the objfile from
RANGE_TYPE.
complaint (&symfile_complaints, _("stub type has NULL name"));
}
-/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
+/* Find the real type of TYPE. This function returns the real type,
+ after removing all layers of typedefs, and completing opaque or stub
+ types. Completion changes the TYPE argument, but stripping of
+ typedefs does not.
+
+ Instance flags (e.g. const/volatile) are preserved as typedefs are
+ stripped. If necessary a new qualified form of the underlying type
+ is created.
+
+ NOTE: This will return a typedef if TYPE_TARGET_TYPE for the typedef has
+ not been computed and we're either in the middle of reading symbols, or
+ there was no name for the typedef in the debug info.
+
+ If TYPE is a TYPE_CODE_TYPEDEF, its length is updated to the length of
+ the target type.
If this is a stubbed struct (i.e. declared as struct foo *), see if
we can find a full definition in some other file. If so, copy this
(but not any code) that if we don't find a full definition, we'd
set a flag so we don't spend time in the future checking the same
type. That would be a mistake, though--we might load in more
- symbols which contain a full definition for the type.
-
- This used to be coded as a macro, but I don't think it is called
- often enough to merit such treatment.
-
- Find the real type of TYPE. This function returns the real type,
- after removing all layers of typedefs and completing opaque or stub
- types. Completion changes the TYPE argument, but stripping of
- typedefs does not.
-
- If TYPE is a TYPE_CODE_TYPEDEF, its length is (also) set to the length of
- the target type instead of zero. However, in the case of TYPE_CODE_TYPEDEF
- check_typedef can still return different type than the original TYPE
- pointer. */
+ symbols which contain a full definition for the type. */
struct type *
check_typedef (struct type *type)
{
struct type *orig_type = type;
- int is_const, is_volatile;
+ /* While we're removing typedefs, we don't want to lose qualifiers.
+ E.g., const/volatile. */
+ int instance_flags = TYPE_INSTANCE_FLAGS (type);
gdb_assert (type);
/* It is dangerous to call lookup_symbol if we are currently
reading a symtab. Infinite recursion is one danger. */
if (currently_reading_symtab)
- return type;
+ return make_qualified_type (type, instance_flags, NULL);
name = type_name_no_tag (type);
/* FIXME: shouldn't we separately check the TYPE_NAME and
if (name == NULL)
{
stub_noname_complaint ();
- return type;
+ return make_qualified_type (type, instance_flags, NULL);
}
sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
if (sym)
TYPE_TARGET_TYPE (type) = alloc_type_arch (get_type_arch (type));
}
type = TYPE_TARGET_TYPE (type);
- }
- is_const = TYPE_CONST (type);
- is_volatile = TYPE_VOLATILE (type);
+ /* Preserve the instance flags as we traverse down the typedef chain.
+
+ Handling address spaces/classes is nasty, what do we do if there's a
+ conflict?
+ E.g., what if an outer typedef marks the type as class_1 and an inner
+ typedef marks the type as class_2?
+ This is the wrong place to do such error checking. We leave it to
+ the code that created the typedef in the first place to flag the
+ error. We just pick the outer address space (akin to letting the
+ outer cast in a chain of casting win), instead of assuming
+ "it can't happen". */
+ {
+ const int ALL_SPACES = (TYPE_INSTANCE_FLAG_CODE_SPACE
+ | TYPE_INSTANCE_FLAG_DATA_SPACE);
+ const int ALL_CLASSES = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL;
+ int new_instance_flags = TYPE_INSTANCE_FLAGS (type);
+
+ /* Treat code vs data spaces and address classes separately. */
+ if ((instance_flags & ALL_SPACES) != 0)
+ new_instance_flags &= ~ALL_SPACES;
+ if ((instance_flags & ALL_CLASSES) != 0)
+ new_instance_flags &= ~ALL_CLASSES;
+
+ instance_flags |= new_instance_flags;
+ }
+ }
/* If this is a struct/class/union with no fields, then check
whether a full definition exists somewhere else. This is for
if (name == NULL)
{
stub_noname_complaint ();
- return type;
+ return make_qualified_type (type, instance_flags, NULL);
}
newtype = lookup_transparent_type (name);
move over any other types NEWTYPE refers to, which could
be an unbounded amount of stuff. */
if (TYPE_OBJFILE (newtype) == TYPE_OBJFILE (type))
- make_cv_type (is_const, is_volatile, newtype, &type);
+ type = make_qualified_type (newtype,
+ TYPE_INSTANCE_FLAGS (type),
+ type);
else
type = newtype;
}
if (name == NULL)
{
stub_noname_complaint ();
- return type;
+ return make_qualified_type (type, instance_flags, NULL);
}
sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
if (sym)
{
/* Same as above for opaque types, we can replace the stub
- with the complete type only if they are int the same
+ with the complete type only if they are in the same
objfile. */
if (TYPE_OBJFILE (SYMBOL_TYPE(sym)) == TYPE_OBJFILE (type))
- make_cv_type (is_const, is_volatile,
- SYMBOL_TYPE (sym), &type);
+ type = make_qualified_type (SYMBOL_TYPE (sym),
+ TYPE_INSTANCE_FLAGS (type),
+ type);
else
type = SYMBOL_TYPE (sym);
}
TYPE_TARGET_STUB (type) = 0;
}
}
+
+ type = make_qualified_type (type, instance_flags, NULL);
+
/* Cache TYPE_LENGTH for future use. */
TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
+
return type;
}
&& !strcmp (TYPE_NAME (a), TYPE_NAME (b))));
}
-/* Check whether BASE is an ancestor or base class of DCLASS
- Return 1 if so, and 0 if not. If PUBLIC is 1 then only public
- ancestors are considered, and the function returns 1 only if
- BASE is a public ancestor of DCLASS. */
+/* If BASE is an ancestor of DCLASS return the distance between them.
+ otherwise return -1;
+ eg:
+
+ class A {};
+ class B: public A {};
+ class C: public B {};
+ class D: C {};
+
+ distance_to_ancestor (A, A, 0) = 0
+ distance_to_ancestor (A, B, 0) = 1
+ distance_to_ancestor (A, C, 0) = 2
+ distance_to_ancestor (A, D, 0) = 3
+
+ If PUBLIC is 1 then only public ancestors are considered,
+ and the function returns the distance only if BASE is a public ancestor
+ of DCLASS.
+ Eg:
+
+ distance_to_ancestor (A, D, 1) = -1 */
static int
-do_is_ancestor (struct type *base, struct type *dclass, int public)
+distance_to_ancestor (struct type *base, struct type *dclass, int public)
{
int i;
+ int d;
CHECK_TYPEDEF (base);
CHECK_TYPEDEF (dclass);
if (class_types_same_p (base, dclass))
- return 1;
+ return 0;
for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
{
if (public && ! BASETYPE_VIA_PUBLIC (dclass, i))
continue;
- if (do_is_ancestor (base, TYPE_BASECLASS (dclass, i), public))
- return 1;
+ d = distance_to_ancestor (base, TYPE_BASECLASS (dclass, i), public);
+ if (d >= 0)
+ return 1 + d;
}
- return 0;
+ return -1;
}
/* Check whether BASE is an ancestor or base class or DCLASS
int
is_ancestor (struct type *base, struct type *dclass)
{
- return do_is_ancestor (base, dclass, 0);
+ return distance_to_ancestor (base, dclass, 0) >= 0;
}
/* Like is_ancestor, but only returns true when BASE is a public
int
is_public_ancestor (struct type *base, struct type *dclass)
{
- return do_is_ancestor (base, dclass, 1);
+ return distance_to_ancestor (base, dclass, 1) >= 0;
}
/* A helper function for is_unique_ancestor. */
\f
+/* Return the sum of the rank of A with the rank of B. */
+
+struct rank
+sum_ranks (struct rank a, struct rank b)
+{
+ struct rank c;
+ c.rank = a.rank + b.rank;
+ c.subrank = a.subrank + b.subrank;
+ return c;
+}
+
+/* Compare rank A and B and return:
+ 0 if a = b
+ 1 if a is better than b
+ -1 if b is better than a. */
+
+int
+compare_ranks (struct rank a, struct rank b)
+{
+ if (a.rank == b.rank)
+ {
+ if (a.subrank == b.subrank)
+ return 0;
+ if (a.subrank < b.subrank)
+ return 1;
+ if (a.subrank > b.subrank)
+ return -1;
+ }
+
+ if (a.rank < b.rank)
+ return 1;
+
+ /* a.rank > b.rank */
+ return -1;
+}
/* Functions for overload resolution begin here */
/* Subtract b from a */
for (i = 0; i < a->length; i++)
{
- tmp = a->rank[i] - b->rank[i];
+ tmp = compare_ranks (b->rank[i], a->rank[i]);
if (tmp > 0)
found_pos = 1;
else if (tmp < 0)
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;
+ LENGTH_MATCH (bv) = (nargs != nparms)
+ ? LENGTH_MISMATCH_BADNESS
+ : EXACT_MATCH_BADNESS;
/* Now rank all the parameters of the candidate function */
for (i = 1; i <= min_len; i++)
* PARM is to ARG. The higher the return value, the worse the match.
* Generally the "bad" conversions are all uniformly assigned a 100. */
-int
+struct rank
rank_one_type (struct type *parm, struct type *arg)
{
+ struct rank rank = {0,0};
if (types_equal (parm, arg))
- return 0;
+ return EXACT_MATCH_BADNESS;
/* Resolve typedefs */
if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
/* See through references, since we can almost make non-references
references. */
if (TYPE_CODE (arg) == TYPE_CODE_REF)
- return (rank_one_type (parm, TYPE_TARGET_TYPE (arg))
- + REFERENCE_CONVERSION_BADNESS);
+ return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg)),
+ REFERENCE_CONVERSION_BADNESS));
if (TYPE_CODE (parm) == TYPE_CODE_REF)
- return (rank_one_type (TYPE_TARGET_TYPE (parm), arg)
- + REFERENCE_CONVERSION_BADNESS);
+ return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg),
+ REFERENCE_CONVERSION_BADNESS));
if (overload_debug)
/* Debugging only. */
fprintf_filtered (gdb_stderr,
return VOID_PTR_CONVERSION_BADNESS;
/* (b) pointer to ancestor-pointer conversion. */
- if (is_ancestor (TYPE_TARGET_TYPE (parm),
- TYPE_TARGET_TYPE (arg)))
- return BASE_PTR_CONVERSION_BADNESS;
+ rank.subrank = distance_to_ancestor (TYPE_TARGET_TYPE (parm),
+ TYPE_TARGET_TYPE (arg),
+ 0);
+ if (rank.subrank >= 0)
+ return sum_ranks (BASE_PTR_CONVERSION_BADNESS, rank);
return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_ARRAY:
if (types_equal (TYPE_TARGET_TYPE (parm),
TYPE_TARGET_TYPE (arg)))
- return 0;
+ return EXACT_MATCH_BADNESS;
return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_FUNC:
return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
case TYPE_CODE_CHAR:
case TYPE_CODE_RANGE:
case TYPE_CODE_BOOL:
- return POINTER_CONVERSION_BADNESS;
default:
return INCOMPATIBLE_TYPE_BADNESS;
}
{
/* This case only for character types */
if (TYPE_NOSIGN (arg))
- return 0; /* plain char -> plain char */
+ return EXACT_MATCH_BADNESS; /* plain char -> plain char */
else /* signed/unsigned char -> plain char */
return INTEGER_CONVERSION_BADNESS;
}
unsigned long -> unsigned long */
if (integer_types_same_name_p (TYPE_NAME (parm),
TYPE_NAME (arg)))
- return 0;
+ return EXACT_MATCH_BADNESS;
else if (integer_types_same_name_p (TYPE_NAME (arg),
"int")
&& integer_types_same_name_p (TYPE_NAME (parm),
{
if (integer_types_same_name_p (TYPE_NAME (parm),
TYPE_NAME (arg)))
- return 0;
+ return EXACT_MATCH_BADNESS;
else if (integer_types_same_name_p (TYPE_NAME (arg),
"int")
&& integer_types_same_name_p (TYPE_NAME (parm),
if (TYPE_NOSIGN (parm))
{
if (TYPE_NOSIGN (arg))
- return 0;
+ return EXACT_MATCH_BADNESS;
else
return INTEGER_CONVERSION_BADNESS;
}
else if (TYPE_UNSIGNED (parm))
{
if (TYPE_UNSIGNED (arg))
- return 0;
+ return EXACT_MATCH_BADNESS;
else
return INTEGER_PROMOTION_BADNESS;
}
else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
- return 0;
+ return EXACT_MATCH_BADNESS;
else
return INTEGER_CONVERSION_BADNESS;
default:
case TYPE_CODE_RANGE:
case TYPE_CODE_ENUM:
case TYPE_CODE_FLT:
+ return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_PTR:
- return BOOLEAN_CONVERSION_BADNESS;
+ return BOOL_PTR_CONVERSION_BADNESS;
case TYPE_CODE_BOOL:
- return 0;
+ return EXACT_MATCH_BADNESS;
default:
return INCOMPATIBLE_TYPE_BADNESS;
}
if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
return FLOAT_PROMOTION_BADNESS;
else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
- return 0;
+ return EXACT_MATCH_BADNESS;
else
return FLOAT_CONVERSION_BADNESS;
case TYPE_CODE_INT:
case TYPE_CODE_FLT:
return FLOAT_PROMOTION_BADNESS;
case TYPE_CODE_COMPLEX:
- return 0;
+ return EXACT_MATCH_BADNESS;
default:
return INCOMPATIBLE_TYPE_BADNESS;
}
{
case TYPE_CODE_STRUCT:
/* Check for derivation */
- if (is_ancestor (parm, arg))
- return BASE_CONVERSION_BADNESS;
+ rank.subrank = distance_to_ancestor (parm, arg, 0);
+ if (rank.subrank >= 0)
+ return sum_ranks (BASE_CONVERSION_BADNESS, rank);
/* else fall through */
default:
return INCOMPATIBLE_TYPE_BADNESS;