+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_PTR. */
+
+static struct rank
+rank_one_type_parm_ptr (struct type *parm, struct type *arg, struct value *value)
+{
+ struct rank rank = {0,0};
+
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+
+ /* Allowed pointer conversions are:
+ (a) pointer to void-pointer conversion. */
+ if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID)
+ return VOID_PTR_CONVERSION_BADNESS;
+
+ /* (b) pointer to ancestor-pointer conversion. */
+ 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:
+ {
+ struct type *t1 = TYPE_TARGET_TYPE (parm);
+ struct type *t2 = TYPE_TARGET_TYPE (arg);
+
+ if (types_equal (t1, t2))
+ {
+ /* Make sure they are CV equal. */
+ if (TYPE_CONST (t1) != TYPE_CONST (t2))
+ rank.subrank |= CV_CONVERSION_CONST;
+ if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
+ rank.subrank |= CV_CONVERSION_VOLATILE;
+ if (rank.subrank != 0)
+ return sum_ranks (CV_CONVERSION_BADNESS, rank);
+ return EXACT_MATCH_BADNESS;
+ }
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+ case TYPE_CODE_FUNC:
+ return rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL);
+ case TYPE_CODE_INT:
+ if (value != NULL && TYPE_CODE (value_type (value)) == TYPE_CODE_INT)
+ {
+ if (value_as_long (value) == 0)
+ {
+ /* Null pointer conversion: allow it to be cast to a pointer.
+ [4.10.1 of C++ standard draft n3290] */
+ return NULL_POINTER_CONVERSION_BADNESS;
+ }
+ else
+ {
+ /* If type checking is disabled, allow the conversion. */
+ if (!strict_type_checking)
+ return NS_INTEGER_POINTER_CONVERSION_BADNESS;
+ }
+ }
+ /* fall through */
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLAGS:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_ARRAY. */
+
+static struct rank
+rank_one_type_parm_array (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ return rank_one_type (TYPE_TARGET_TYPE (parm),
+ TYPE_TARGET_TYPE (arg), NULL);
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_FUNC. */
+
+static struct rank
+rank_one_type_parm_func (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_PTR: /* funcptr -> func */
+ return rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL);
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_INT. */
+
+static struct rank
+rank_one_type_parm_int (struct type *parm, struct type *arg, struct value *value)
+{
+ 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))
+ return EXACT_MATCH_BADNESS; /* plain char -> plain char */
+ else /* signed/unsigned char -> plain char */
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ else if (TYPE_UNSIGNED (parm))
+ {
+ if (TYPE_UNSIGNED (arg))
+ {
+ /* unsigned int -> unsigned int, or
+ unsigned long -> unsigned long */
+ if (integer_types_same_name_p (TYPE_NAME (parm),
+ TYPE_NAME (arg)))
+ return EXACT_MATCH_BADNESS;
+ else if (integer_types_same_name_p (TYPE_NAME (arg),
+ "int")
+ && integer_types_same_name_p (TYPE_NAME (parm),
+ "long"))
+ /* unsigned int -> unsigned long */
+ return INTEGER_PROMOTION_BADNESS;
+ else
+ /* unsigned long -> unsigned int */
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ else
+ {
+ if (integer_types_same_name_p (TYPE_NAME (arg),
+ "long")
+ && integer_types_same_name_p (TYPE_NAME (parm),
+ "int"))
+ /* signed long -> unsigned int */
+ return INTEGER_CONVERSION_BADNESS;
+ else
+ /* signed int/long -> unsigned int/long */
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ }
+ else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+ {
+ if (integer_types_same_name_p (TYPE_NAME (parm),
+ TYPE_NAME (arg)))
+ return EXACT_MATCH_BADNESS;
+ else if (integer_types_same_name_p (TYPE_NAME (arg),
+ "int")
+ && integer_types_same_name_p (TYPE_NAME (parm),
+ "long"))
+ return INTEGER_PROMOTION_BADNESS;
+ else
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ else
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+ return INTEGER_PROMOTION_BADNESS;
+ else
+ return INTEGER_CONVERSION_BADNESS;
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLAGS:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ if (TYPE_DECLARED_CLASS (arg))
+ return INCOMPATIBLE_TYPE_BADNESS;
+ 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;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_ENUM. */
+
+static struct rank
+rank_one_type_parm_enum (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ if (TYPE_DECLARED_CLASS (parm) || TYPE_DECLARED_CLASS (arg))
+ return INCOMPATIBLE_TYPE_BADNESS;
+ return INTEGER_CONVERSION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_CHAR. */
+
+static struct rank
+rank_one_type_parm_char (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ if (TYPE_DECLARED_CLASS (arg))
+ return INCOMPATIBLE_TYPE_BADNESS;
+ return INTEGER_CONVERSION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ case TYPE_CODE_INT:
+ if (TYPE_LENGTH (arg) > TYPE_LENGTH (parm))
+ return INTEGER_CONVERSION_BADNESS;
+ else if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
+ return INTEGER_PROMOTION_BADNESS;
+ /* 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 EXACT_MATCH_BADNESS;
+ else
+ return INTEGER_CONVERSION_BADNESS;
+ }
+ else if (TYPE_UNSIGNED (parm))
+ {
+ if (TYPE_UNSIGNED (arg))
+ return EXACT_MATCH_BADNESS;
+ else
+ return INTEGER_PROMOTION_BADNESS;
+ }
+ else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
+ return EXACT_MATCH_BADNESS;
+ else
+ return INTEGER_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_RANGE. */
+
+static struct rank
+rank_one_type_parm_range (struct type *parm, struct type *arg, struct value *value)
+{
+ 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_CONVERSION_BADNESS;
+ case TYPE_CODE_FLT:
+ return INT_FLOAT_CONVERSION_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_BOOL. */
+
+static struct rank
+rank_one_type_parm_bool (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ {
+ /* n3290 draft, section 4.12.1 (conv.bool):
+
+ "A prvalue of arithmetic, unscoped enumeration, pointer, or
+ pointer to member type can be converted to a prvalue of type
+ bool. A zero value, null pointer value, or null member pointer
+ value is converted to false; any other value is converted to
+ true. A prvalue of type std::nullptr_t can be converted to a
+ prvalue of type bool; the resulting value is false." */
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_MEMBERPTR:
+ case TYPE_CODE_PTR:
+ return BOOL_CONVERSION_BADNESS;
+ case TYPE_CODE_RANGE:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ case TYPE_CODE_BOOL:
+ return EXACT_MATCH_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_FLOAT. */
+
+static struct rank
+rank_one_type_parm_float (struct type *parm, struct type *arg, struct value *value)
+{
+ 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 EXACT_MATCH_BADNESS;
+ 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;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_COMPLEX. */
+
+static struct rank
+rank_one_type_parm_complex (struct type *parm, struct type *arg, struct value *value)
+{
+ switch (TYPE_CODE (arg))
+ { /* Strictly not needed for C++, but... */
+ case TYPE_CODE_FLT:
+ return FLOAT_PROMOTION_BADNESS;
+ case TYPE_CODE_COMPLEX:
+ return EXACT_MATCH_BADNESS;
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_STRUCT. */
+
+static struct rank
+rank_one_type_parm_struct (struct type *parm, struct type *arg, struct value *value)
+{
+ struct rank rank = {0, 0};
+
+ switch (TYPE_CODE (arg))
+ {
+ case TYPE_CODE_STRUCT:
+ /* Check for derivation */
+ rank.subrank = distance_to_ancestor (parm, arg, 0);
+ if (rank.subrank >= 0)
+ return sum_ranks (BASE_CONVERSION_BADNESS, rank);
+ /* fall through */
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+
+/* rank_one_type helper for when PARM's type code is TYPE_CODE_SET. */
+
+static struct rank
+rank_one_type_parm_set (struct type *parm, struct type *arg, struct value *value)
+{
+ 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), NULL);
+ default:
+ return INCOMPATIBLE_TYPE_BADNESS;
+ }
+}
+