* [patch] Overload resolution among children of a common ancestor @ 2010-08-30 16:11 sami wagiaalla 2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla 2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla 0 siblings, 2 replies; 8+ messages in thread From: sami wagiaalla @ 2010-08-30 16:11 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 362 bytes --] This patch introduces a cost for converting types to their ancestor types that depends on the distance to that ancestor. It also disables the calling of functions which are inherited through non-public inheritance. I had to update a couple of test cases for that. This patch was regression tested on Fedora 13 on x8664 with gcc 4.4.4. No regressions. Sami [-- Attachment #2: overload_inheritance.patch --] [-- Type: text/x-patch, Size: 5858 bytes --] Fix overload resolution between children of common ancestor. 2010-08-30 Sami Wagiaalla <swagiaal@redhat.com> * gdbtypes.h (distance_to_public_ancestor): New function. * gdbtypes.c (distance_to_public_ancestor): New function. (rank_one_type): Concider distance_to_public_ancestor when ranking two structs. (is_public_ancestor): Use distance_to_public_ancestor. 2010-08-30 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/overload.cc: Add testing for overload resolution based on distance to ancestor. * gdb.cp/overload.exp: Ditto. * gdb.cp/virtfunc2.cc (Obj2): Change inheritance to public. Add calls to the function calls being tested. * gdb.cp/derivation.cc (G): Changed inheritance to public. Add calls to the function calls being tested. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index b7fb110..39912d6 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1903,23 +1903,48 @@ is_ancestor (struct type *base, struct type *dclass) int is_public_ancestor (struct type *base, struct type *dclass) { + return (distance_to_public_ancestor (base, dclass) >= 0); +} + +/* If BASE is a public 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_public_ancestor (A, A) = 0 + distance_to_public_ancestor (A, B) = 1 + distance_to_public_ancestor (A, C) = 2 + distance_to_public_ancestor (A, D) = -1 + + */ +int +distance_to_public_ancestor (struct type *base, struct type *dclass) +{ 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 (! BASETYPE_VIA_PUBLIC (dclass, i)) continue; - if (is_public_ancestor (base, TYPE_BASECLASS (dclass, i))) - return 1; + + d = distance_to_public_ancestor (base, TYPE_BASECLASS (dclass, i)); + if (d >= 0) + return 1 + d; + } - return 0; + return -1; } /* A helper function for is_unique_ancestor. */ @@ -2120,6 +2145,7 @@ integer_types_same_name_p (const char *first, const char *second) int rank_one_type (struct type *parm, struct type *arg) { + int d; /* 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 @@ -2411,8 +2437,9 @@ rank_one_type (struct type *parm, struct type *arg) { case TYPE_CODE_STRUCT: /* Check for derivation */ - if (is_ancestor (parm, arg)) - return BASE_CONVERSION_BADNESS; + d = distance_to_public_ancestor (parm, arg); + if (d >= 0) + return BASE_CONVERSION_BADNESS + d; /* else fall through */ default: return INCOMPATIBLE_TYPE_BADNESS; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index ed8d613..6a1eb80 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -1358,6 +1358,8 @@ extern int class_types_same_p (const struct type *, const struct type *); extern int is_ancestor (struct type *, struct type *); +extern int distance_to_public_ancestor (struct type *, struct type *); + extern int is_public_ancestor (struct type *, struct type *); extern int is_unique_ancestor (struct type *, struct value *); diff --git a/gdb/testsuite/gdb.cp/derivation.cc b/gdb/testsuite/gdb.cp/derivation.cc index f6d42e7..02999c1 100644 --- a/gdb/testsuite/gdb.cp/derivation.cc +++ b/gdb/testsuite/gdb.cp/derivation.cc @@ -96,7 +96,7 @@ public: }; -class G : private A, public B, protected C { +class G : public A, public B, public C { public: int g; int gg; @@ -207,7 +207,10 @@ int main(void) E e_instance; F f_instance; G g_instance; - + + g_instance.afoo(); + g_instance.cfoo(); + #ifdef usestubs set_debug_traps(); breakpoint(); diff --git a/gdb/testsuite/gdb.cp/overload.cc b/gdb/testsuite/gdb.cp/overload.cc index dc117fb..bd2f96c 100644 --- a/gdb/testsuite/gdb.cp/overload.cc +++ b/gdb/testsuite/gdb.cp/overload.cc @@ -89,6 +89,14 @@ namespace XXX { void marker2() {} } +class A {}; +class B: public A {}; +class C: public B {}; +class D: C {}; + +int bar (A) { return 11; } +int bar (B) { return 22; } + int main () { char arg2 = 2; @@ -105,6 +113,15 @@ int main () int arg13 = 200.0; char arg14 = 'a'; + A a; + B b; + C c; + D d; + + bar (a); + bar (b); + bar (c); + char *str = (char *) "A"; foo foo_instance1(111); foo foo_instance2(222, str); @@ -132,6 +149,7 @@ int main () marker1(); // marker1-returns-here XXX::marker2(); // marker1-returns-here + return 0; } diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp index 25aeb07..048e074 100644 --- a/gdb/testsuite/gdb.cp/overload.exp +++ b/gdb/testsuite/gdb.cp/overload.exp @@ -266,6 +266,11 @@ gdb_test "print foo_instance1.overload1arg(&arg14)" \ "\\$\[0-9\]+ = 14" \ "print call overloaded func char\\* arg" +gdb_test "print bar(a)" "= 11" +gdb_test "print bar(b)" "= 22" +gdb_test "print bar(c)" "= 22" +gdb_test "print bar(d)" "Cannot resolve function bar to any overloaded instance" + # --- # List overloaded functions. diff --git a/gdb/testsuite/gdb.cp/virtfunc2.cc b/gdb/testsuite/gdb.cp/virtfunc2.cc index 90f3eda..666a495 100644 --- a/gdb/testsuite/gdb.cp/virtfunc2.cc +++ b/gdb/testsuite/gdb.cp/virtfunc2.cc @@ -27,7 +27,7 @@ public: virtual int do_print() { return 123456; } }; -class Obj2 : Obj, virtual public interface +class Obj2 : public Obj, virtual public interface { virtual int do_print2() { return 654321; } }; @@ -35,5 +35,7 @@ class Obj2 : Obj, virtual public interface int main(int argc, char** argv) { Obj o; Obj2 o2; + o2.do_print(); + return 0; // marker 1 } ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 1/2] Overload resolution among children of a common ancestor 2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor sami wagiaalla @ 2010-10-19 20:27 ` sami wagiaalla 2010-10-22 15:39 ` Tom Tromey 2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla 1 sibling, 1 reply; 8+ messages in thread From: sami wagiaalla @ 2010-10-19 20:27 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 128 bytes --] This patch introduces a rank struct to be used instead of the int that is normally used to represent the rank of a conversion. [-- Attachment #2: overload_rank.patch --] [-- Type: text/x-patch, Size: 11508 bytes --] Create and use struct rank. 2010-10-18 Sami Wagiaalla <swagiaal@redhat.com> * gdbtypes.h: Create struct rank. Convert all 'BADNESS' macros to const struct rank declarations. (sum_ranks): New function. (compare_ranks): New function. * valops.c (find_oload_champ): Updated. (classify_oload_match): Use compare_ranks. Improved comments. (compare_parameters): Use compare_ranks. * gdbtypes.c (sum_ranks): New function. (compare_ranks): New function. (compare_badness): Use compare_ranks. (rank_function): Use global constants instead of literals. (rank_one_type): Ditto. Return struct rank. Use sum_ranks. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index d08dbfe..6213f3c 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -2012,6 +2012,30 @@ is_unique_ancestor (struct type *base, struct value *val) \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; + 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) + return 0; + + if (a.rank < b.rank) + return 1; + + return -1; +} /* Functions for overload resolution begin here */ @@ -2036,7 +2060,7 @@ compare_badness (struct badness_vector *a, struct badness_vector *b) /* 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) @@ -2084,7 +2108,7 @@ rank_function (struct type **parms, int nparms, 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++) @@ -2195,12 +2219,12 @@ types_equal (struct type *a, struct type *b) * 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) { if (types_equal (parm, arg)) - return 0; + return EXACT_MATCH_BADNESS; /* Resolve typedefs */ if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF) @@ -2211,11 +2235,11 @@ rank_one_type (struct type *parm, struct type *arg) /* 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, @@ -2246,7 +2270,7 @@ rank_one_type (struct type *parm, struct type *arg) 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); @@ -2289,7 +2313,7 @@ rank_one_type (struct type *parm, struct type *arg) { /* 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; } @@ -2301,7 +2325,7 @@ rank_one_type (struct type *parm, struct type *arg) 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), @@ -2325,7 +2349,7 @@ rank_one_type (struct type *parm, struct type *arg) { 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), @@ -2391,19 +2415,19 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2437,7 +2461,7 @@ rank_one_type (struct type *parm, struct type *arg) case TYPE_CODE_PTR: return BOOL_PTR_CONVERSION_BADNESS; case TYPE_CODE_BOOL: - return 0; + return EXACT_MATCH_BADNESS; default: return INCOMPATIBLE_TYPE_BADNESS; } @@ -2449,7 +2473,7 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2468,7 +2492,7 @@ rank_one_type (struct type *parm, struct type *arg) case TYPE_CODE_FLT: return FLOAT_PROMOTION_BADNESS; case TYPE_CODE_COMPLEX: - return 0; + return EXACT_MATCH_BADNESS; default: return INCOMPATIBLE_TYPE_BADNESS; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 5617a1d..56590b2 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -849,11 +849,17 @@ struct vbase struct vbase *next; /* next in chain */ }; +/* Struct used to store conversion rankings. */ +struct rank + { + int rank; + }; + /* Struct used for ranking a function for overload resolution */ struct badness_vector { int length; - int *rank; + struct rank *rank; }; /* GNAT Ada-specific information for various Ada types. */ @@ -1396,45 +1402,52 @@ extern int is_unique_ancestor (struct type *, struct value *); #define LENGTH_MATCH(bv) ((bv)->rank[0]) /* Badness if parameter list length doesn't match arg list length */ -#define LENGTH_MISMATCH_BADNESS 100 +static const struct rank LENGTH_MISMATCH_BADNESS = {100}; + /* Dummy badness value for nonexistent parameter positions */ -#define TOO_FEW_PARAMS_BADNESS 100 +static const struct rank TOO_FEW_PARAMS_BADNESS = {100}; /* Badness if no conversion among types */ -#define INCOMPATIBLE_TYPE_BADNESS 100 +static const struct rank INCOMPATIBLE_TYPE_BADNESS = {100}; + +/* Badness of an exact match. */ +static const struct rank EXACT_MATCH_BADNESS = {0}; /* Badness of integral promotion */ -#define INTEGER_PROMOTION_BADNESS 1 +static const struct rank INTEGER_PROMOTION_BADNESS = {1}; /* Badness of floating promotion */ -#define FLOAT_PROMOTION_BADNESS 1 +static const struct rank FLOAT_PROMOTION_BADNESS = {1}; /* Badness of converting a derived class pointer to a base class pointer. */ -#define BASE_PTR_CONVERSION_BADNESS 1 +static const struct rank BASE_PTR_CONVERSION_BADNESS = {1}; /* Badness of integral conversion */ -#define INTEGER_CONVERSION_BADNESS 2 +static const struct rank INTEGER_CONVERSION_BADNESS = {2}; /* Badness of floating conversion */ -#define FLOAT_CONVERSION_BADNESS 2 +static const struct rank FLOAT_CONVERSION_BADNESS = {2}; /* Badness of integer<->floating conversions */ -#define INT_FLOAT_CONVERSION_BADNESS 2 +static const struct rank INT_FLOAT_CONVERSION_BADNESS = {2}; /* Badness of conversion of pointer to void pointer */ -#define VOID_PTR_CONVERSION_BADNESS 2 +static const struct rank VOID_PTR_CONVERSION_BADNESS = {2}; /* Badness of conversion of pointer to boolean. */ -#define BOOL_PTR_CONVERSION_BADNESS 3 +static const struct rank BOOL_PTR_CONVERSION_BADNESS = {3}; /* Badness of converting derived to base class */ -#define BASE_CONVERSION_BADNESS 2 +static const struct rank BASE_CONVERSION_BADNESS = {2}; /* Badness of converting from non-reference to reference */ -#define REFERENCE_CONVERSION_BADNESS 2 +static const struct rank REFERENCE_CONVERSION_BADNESS = {2}; /* Non-standard conversions allowed by the debugger */ /* Converting a pointer to an int is usually OK */ -#define NS_POINTER_CONVERSION_BADNESS 10 +static const struct rank NS_POINTER_CONVERSION_BADNESS = {10}; + +extern struct rank sum_ranks (struct rank a, struct rank b); +extern int compare_ranks (struct rank a, struct rank b); extern int compare_badness (struct badness_vector *, struct badness_vector *); extern struct badness_vector *rank_function (struct type **, int, struct type **, int); -extern int rank_one_type (struct type *, struct type *); +extern struct rank rank_one_type (struct type *, struct type *); extern void recursive_dump_type (struct type *, int); diff --git a/gdb/valops.c b/gdb/valops.c index fe4576e..eb0bb7d 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2884,7 +2884,7 @@ find_oload_champ (struct type **arg_types, int nargs, int method, for (jj = 0; jj < nargs - static_offset; jj++) fprintf_filtered (gdb_stderr, "...Badness @ %d : %d\n", - jj, bv->rank[jj]); + jj, bv->rank[jj].rank); fprintf_filtered (gdb_stderr, "Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous); @@ -2918,9 +2918,15 @@ classify_oload_match (struct badness_vector *oload_champ_bv, for (ix = 1; ix <= nargs - static_offset; ix++) { - if (oload_champ_bv->rank[ix] >= 100) + /* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS + or worse return INCOMPATIBLE. */ + if (compare_ranks (oload_champ_bv->rank[ix], + INCOMPATIBLE_TYPE_BADNESS) <= 0) return INCOMPATIBLE; /* Truly mismatched types. */ - else if (oload_champ_bv->rank[ix] >= 10) + /* Otherwise If this conversion is as bad as + NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD. */ + else if (compare_ranks (oload_champ_bv->rank[ix], + NS_POINTER_CONVERSION_BADNESS) <= 0) return NON_STANDARD; /* Non-standard type conversions needed. */ } @@ -3056,9 +3062,9 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial) for (i = 0; i < TYPE_NFIELDS (t2); ++i) { - if (rank_one_type (TYPE_FIELD_TYPE (t1, start + i), - TYPE_FIELD_TYPE (t2, i)) - != 0) + if (compare_ranks (rank_one_type (TYPE_FIELD_TYPE (t1, start + i), + TYPE_FIELD_TYPE (t2, i)), + EXACT_MATCH_BADNESS) != 0) return 0; } ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 1/2] Overload resolution among children of a common ancestor 2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla @ 2010-10-22 15:39 ` Tom Tromey 2010-11-02 18:04 ` sami wagiaalla 0 siblings, 1 reply; 8+ messages in thread From: Tom Tromey @ 2010-10-22 15:39 UTC (permalink / raw) To: sami wagiaalla; +Cc: gdb-patches >>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes: Sami> This patch introduces a rank struct to be used instead of the int that Sami> is normally used to represent the rank of a conversion. Thanks. I have a few nits to pick but nothing serious. Sami> +/* Return the sum of the rank of A with the rank of B. */ Sami> +struct rank Blank line between comment and start of function. Sami> +/* Compare rank A and B and return: Sami> + 0 if a = b Sami> + 1 if a is better than b Sami> + -1 if b is better than a. */ Sami> +int Sami> +compare_ranks (struct rank a, struct rank b) Likewise. Sami> - LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0; Sami> + LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : EXACT_MATCH_BADNESS; I think this needs a line break. Sami> /* Badness if parameter list length doesn't match arg list length */ Sami> -#define LENGTH_MISMATCH_BADNESS 100 Sami> +static const struct rank LENGTH_MISMATCH_BADNESS = {100}; Instead of defining a static instance in the header, define a single instance with a different (not upper-case) name in a .c file, put an extern declaration in the header, and then make the #define refer to it. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 1/2] Overload resolution among children of a common ancestor 2010-10-22 15:39 ` Tom Tromey @ 2010-11-02 18:04 ` sami wagiaalla 2010-11-02 20:31 ` Tom Tromey 0 siblings, 1 reply; 8+ messages in thread From: sami wagiaalla @ 2010-11-02 18:04 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 606 bytes --] Revised patch attached. > Sami> /* Badness if parameter list length doesn't match arg list length */ > Sami> -#define LENGTH_MISMATCH_BADNESS 100 > Sami> +static const struct rank LENGTH_MISMATCH_BADNESS = {100}; > > Instead of defining a static instance in the header, define a single > instance with a different (not upper-case) name in a .c file, put an > extern declaration in the header, and then make the #define refer to it. > Hmm.. is it cool if I just declare the constants 'extern const' in the header and then define them in gdbtypes.c, without #defines ? As in the attached patch. [-- Attachment #2: overload_rank.patch --] [-- Type: text/x-patch, Size: 12482 bytes --] Create and use struct rank. 2010-10-18 Sami Wagiaalla <swagiaal@redhat.com> * gdbtypes.h: Create struct rank. Convert all 'BADNESS' macros to const struct rank declarations. (sum_ranks): New function. (compare_ranks): New function. * valops.c (find_oload_champ): Updated. (classify_oload_match): Use compare_ranks. Improved comments. (compare_parameters): Use compare_ranks. * gdbtypes.c: Initialize 'BADNESS' constants. (sum_ranks): New function. (compare_ranks): New function. (compare_badness): Use compare_ranks. (rank_function): Use global constants instead of literals. (rank_one_type): Ditto. Return struct rank. Use sum_ranks. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index d08dbfe..bfeae90 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -41,6 +41,28 @@ #include "hashtab.h" +/* Initialize BADNESS constants. */ + +const struct rank LENGTH_MISMATCH_BADNESS = {100}; + +const struct rank TOO_FEW_PARAMS_BADNESS = {100}; +const struct rank INCOMPATIBLE_TYPE_BADNESS = {100}; + +const struct rank EXACT_MATCH_BADNESS = {0}; + +const struct rank INTEGER_PROMOTION_BADNESS = {1}; +const struct rank FLOAT_PROMOTION_BADNESS = {1}; +const struct rank BASE_PTR_CONVERSION_BADNESS = {1}; +const struct rank INTEGER_CONVERSION_BADNESS = {2}; +const struct rank FLOAT_CONVERSION_BADNESS = {2}; +const struct rank INT_FLOAT_CONVERSION_BADNESS = {2}; +const struct rank VOID_PTR_CONVERSION_BADNESS = {2}; +const struct rank BOOL_PTR_CONVERSION_BADNESS = {3}; +const struct rank BASE_CONVERSION_BADNESS = {2}; +const struct rank REFERENCE_CONVERSION_BADNESS = {2}; + +const struct rank NS_POINTER_CONVERSION_BADNESS = {10}; + /* Floatformat pairs. */ const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = { &floatformat_ieee_half_big, @@ -2012,6 +2034,32 @@ is_unique_ancestor (struct type *base, struct value *val) \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; + 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) + return 0; + + if (a.rank < b.rank) + return 1; + + return -1; +} /* Functions for overload resolution begin here */ @@ -2036,7 +2084,7 @@ compare_badness (struct badness_vector *a, struct badness_vector *b) /* 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) @@ -2084,7 +2132,9 @@ rank_function (struct type **parms, int nparms, 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++) @@ -2195,12 +2245,12 @@ types_equal (struct type *a, struct type *b) * 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) { if (types_equal (parm, arg)) - return 0; + return EXACT_MATCH_BADNESS; /* Resolve typedefs */ if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF) @@ -2211,11 +2261,11 @@ rank_one_type (struct type *parm, struct type *arg) /* 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, @@ -2246,7 +2296,7 @@ rank_one_type (struct type *parm, struct type *arg) 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); @@ -2289,7 +2339,7 @@ rank_one_type (struct type *parm, struct type *arg) { /* 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; } @@ -2301,7 +2351,7 @@ rank_one_type (struct type *parm, struct type *arg) 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), @@ -2325,7 +2375,7 @@ rank_one_type (struct type *parm, struct type *arg) { 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), @@ -2391,19 +2441,19 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2437,7 +2487,7 @@ rank_one_type (struct type *parm, struct type *arg) case TYPE_CODE_PTR: return BOOL_PTR_CONVERSION_BADNESS; case TYPE_CODE_BOOL: - return 0; + return EXACT_MATCH_BADNESS; default: return INCOMPATIBLE_TYPE_BADNESS; } @@ -2449,7 +2499,7 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2468,7 +2518,7 @@ rank_one_type (struct type *parm, struct type *arg) case TYPE_CODE_FLT: return FLOAT_PROMOTION_BADNESS; case TYPE_CODE_COMPLEX: - return 0; + return EXACT_MATCH_BADNESS; default: return INCOMPATIBLE_TYPE_BADNESS; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 5617a1d..917938a 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -849,11 +849,17 @@ struct vbase struct vbase *next; /* next in chain */ }; +/* Struct used to store conversion rankings. */ +struct rank + { + int rank; + }; + /* Struct used for ranking a function for overload resolution */ struct badness_vector { int length; - int *rank; + struct rank *rank; }; /* GNAT Ada-specific information for various Ada types. */ @@ -1396,45 +1402,52 @@ extern int is_unique_ancestor (struct type *, struct value *); #define LENGTH_MATCH(bv) ((bv)->rank[0]) /* Badness if parameter list length doesn't match arg list length */ -#define LENGTH_MISMATCH_BADNESS 100 +extern const struct rank LENGTH_MISMATCH_BADNESS; + /* Dummy badness value for nonexistent parameter positions */ -#define TOO_FEW_PARAMS_BADNESS 100 +extern const struct rank TOO_FEW_PARAMS_BADNESS; /* Badness if no conversion among types */ -#define INCOMPATIBLE_TYPE_BADNESS 100 +extern const struct rank INCOMPATIBLE_TYPE_BADNESS; + +/* Badness of an exact match. */ +extern const struct rank EXACT_MATCH_BADNESS; /* Badness of integral promotion */ -#define INTEGER_PROMOTION_BADNESS 1 +extern const struct rank INTEGER_PROMOTION_BADNESS; /* Badness of floating promotion */ -#define FLOAT_PROMOTION_BADNESS 1 +extern const struct rank FLOAT_PROMOTION_BADNESS; /* Badness of converting a derived class pointer to a base class pointer. */ -#define BASE_PTR_CONVERSION_BADNESS 1 +extern const struct rank BASE_PTR_CONVERSION_BADNESS; /* Badness of integral conversion */ -#define INTEGER_CONVERSION_BADNESS 2 +extern const struct rank INTEGER_CONVERSION_BADNESS; /* Badness of floating conversion */ -#define FLOAT_CONVERSION_BADNESS 2 +extern const struct rank FLOAT_CONVERSION_BADNESS; /* Badness of integer<->floating conversions */ -#define INT_FLOAT_CONVERSION_BADNESS 2 +extern const struct rank INT_FLOAT_CONVERSION_BADNESS; /* Badness of conversion of pointer to void pointer */ -#define VOID_PTR_CONVERSION_BADNESS 2 +extern const struct rank VOID_PTR_CONVERSION_BADNESS; /* Badness of conversion of pointer to boolean. */ -#define BOOL_PTR_CONVERSION_BADNESS 3 +extern const struct rank BOOL_PTR_CONVERSION_BADNESS; /* Badness of converting derived to base class */ -#define BASE_CONVERSION_BADNESS 2 +extern const struct rank BASE_CONVERSION_BADNESS; /* Badness of converting from non-reference to reference */ -#define REFERENCE_CONVERSION_BADNESS 2 +extern const struct rank REFERENCE_CONVERSION_BADNESS; /* Non-standard conversions allowed by the debugger */ /* Converting a pointer to an int is usually OK */ -#define NS_POINTER_CONVERSION_BADNESS 10 +extern const struct rank NS_POINTER_CONVERSION_BADNESS; + +extern struct rank sum_ranks (struct rank a, struct rank b); +extern int compare_ranks (struct rank a, struct rank b); extern int compare_badness (struct badness_vector *, struct badness_vector *); extern struct badness_vector *rank_function (struct type **, int, struct type **, int); -extern int rank_one_type (struct type *, struct type *); +extern struct rank rank_one_type (struct type *, struct type *); extern void recursive_dump_type (struct type *, int); diff --git a/gdb/valops.c b/gdb/valops.c index fe4576e..eb0bb7d 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -2884,7 +2884,7 @@ find_oload_champ (struct type **arg_types, int nargs, int method, for (jj = 0; jj < nargs - static_offset; jj++) fprintf_filtered (gdb_stderr, "...Badness @ %d : %d\n", - jj, bv->rank[jj]); + jj, bv->rank[jj].rank); fprintf_filtered (gdb_stderr, "Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous); @@ -2918,9 +2918,15 @@ classify_oload_match (struct badness_vector *oload_champ_bv, for (ix = 1; ix <= nargs - static_offset; ix++) { - if (oload_champ_bv->rank[ix] >= 100) + /* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS + or worse return INCOMPATIBLE. */ + if (compare_ranks (oload_champ_bv->rank[ix], + INCOMPATIBLE_TYPE_BADNESS) <= 0) return INCOMPATIBLE; /* Truly mismatched types. */ - else if (oload_champ_bv->rank[ix] >= 10) + /* Otherwise If this conversion is as bad as + NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD. */ + else if (compare_ranks (oload_champ_bv->rank[ix], + NS_POINTER_CONVERSION_BADNESS) <= 0) return NON_STANDARD; /* Non-standard type conversions needed. */ } @@ -3056,9 +3062,9 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial) for (i = 0; i < TYPE_NFIELDS (t2); ++i) { - if (rank_one_type (TYPE_FIELD_TYPE (t1, start + i), - TYPE_FIELD_TYPE (t2, i)) - != 0) + if (compare_ranks (rank_one_type (TYPE_FIELD_TYPE (t1, start + i), + TYPE_FIELD_TYPE (t2, i)), + EXACT_MATCH_BADNESS) != 0) return 0; } ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 1/2] Overload resolution among children of a common ancestor 2010-11-02 18:04 ` sami wagiaalla @ 2010-11-02 20:31 ` Tom Tromey 0 siblings, 0 replies; 8+ messages in thread From: Tom Tromey @ 2010-11-02 20:31 UTC (permalink / raw) To: sami wagiaalla; +Cc: gdb-patches >>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes: Sami> Hmm.. is it cool if I just declare the constants 'extern const' in the Sami> header and then define them in gdbtypes.c, without #defines ? As in Sami> the attached patch. Yeah, that is fine. It is a little weird to have uppercased names, but I think it is fine in this case. This patch is ok. Thanks. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] Overload resolution among children of a common ancestor 2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor sami wagiaalla 2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla @ 2010-10-19 20:30 ` sami wagiaalla 2010-10-22 17:16 ` Tom Tromey 1 sibling, 1 reply; 8+ messages in thread From: sami wagiaalla @ 2010-10-19 20:30 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 448 bytes --] On 08/30/2010 12:10 PM, sami wagiaalla wrote: > This patch introduces a cost for converting types to their ancestor > types that depends on the distance to that ancestor. This patch does the quoted above, but through a subrank field int the newly created rank struct. This prevents the ranking amongst children of a common ancestor from interfering with other rankings. This patch series was regression tested with gcc-4.4.4-f13 on x8664 Sami [-- Attachment #2: overload_inheritance.patch --] [-- Type: text/x-patch, Size: 9941 bytes --] Fix derived class overload problem. 2010-10-19 Sami Wagiaalla <swagiaal@redhat.com> * gdbtypes.h (struct rank): Created subrank. initialized subrank for all 'BADNESS' constants. * gdbtypes.c (distance_to_ancestor): New function. (is_ancestor): Use distance_to_ancestor. (is_public_ancestor): Ditto. (sum_ranks): Handle subrank. (compare_ranks): Ditto. (rank_one_type): Subrank base conversions. 2010-10-19 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/overload.exp: Added test for inheritance overload. * gdb.cp/overload.cc: Ditto. * gdb.cp/oranking.exp: Removed releveant kfails. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 6213f3c..1b6fb21 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1901,32 +1901,50 @@ class_types_same_p (const struct type *a, const struct type *b) && !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 @@ -1938,7 +1956,7 @@ do_is_ancestor (struct type *base, struct type *dclass, int public) 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 @@ -1947,7 +1965,7 @@ is_ancestor (struct type *base, struct type *dclass) 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. */ @@ -2018,6 +2036,7 @@ 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; } @@ -2029,11 +2048,19 @@ int compare_ranks (struct rank a, struct rank b) { if (a.rank == b.rank) - return 0; + { + 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; } @@ -2222,6 +2249,7 @@ types_equal (struct type *a, struct type *b) struct rank rank_one_type (struct type *parm, struct type *arg) { + struct rank rank = {0,0}; if (types_equal (parm, arg)) return EXACT_MATCH_BADNESS; @@ -2262,9 +2290,11 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2503,8 +2533,9 @@ rank_one_type (struct type *parm, struct type *arg) { 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; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 56590b2..e36d292 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -852,7 +852,8 @@ struct vbase /* Struct used to store conversion rankings. */ struct rank { - int rank; + short rank; + short subrank; }; /* Struct used for ranking a function for overload resolution */ @@ -1402,41 +1403,41 @@ extern int is_unique_ancestor (struct type *, struct value *); #define LENGTH_MATCH(bv) ((bv)->rank[0]) /* Badness if parameter list length doesn't match arg list length */ -static const struct rank LENGTH_MISMATCH_BADNESS = {100}; +static const struct rank LENGTH_MISMATCH_BADNESS = {100,0}; /* Dummy badness value for nonexistent parameter positions */ -static const struct rank TOO_FEW_PARAMS_BADNESS = {100}; +static const struct rank TOO_FEW_PARAMS_BADNESS = {100,0}; /* Badness if no conversion among types */ -static const struct rank INCOMPATIBLE_TYPE_BADNESS = {100}; +static const struct rank INCOMPATIBLE_TYPE_BADNESS = {100,0}; /* Badness of an exact match. */ -static const struct rank EXACT_MATCH_BADNESS = {0}; +static const struct rank EXACT_MATCH_BADNESS = {0,0}; /* Badness of integral promotion */ -static const struct rank INTEGER_PROMOTION_BADNESS = {1}; +static const struct rank INTEGER_PROMOTION_BADNESS = {1,0}; /* Badness of floating promotion */ -static const struct rank FLOAT_PROMOTION_BADNESS = {1}; +static const struct rank FLOAT_PROMOTION_BADNESS = {1,0}; /* Badness of converting a derived class pointer to a base class pointer. */ -static const struct rank BASE_PTR_CONVERSION_BADNESS = {1}; +static const struct rank BASE_PTR_CONVERSION_BADNESS = {1,0}; /* Badness of integral conversion */ -static const struct rank INTEGER_CONVERSION_BADNESS = {2}; +static const struct rank INTEGER_CONVERSION_BADNESS = {2,0}; /* Badness of floating conversion */ -static const struct rank FLOAT_CONVERSION_BADNESS = {2}; +static const struct rank FLOAT_CONVERSION_BADNESS = {2,0}; /* Badness of integer<->floating conversions */ -static const struct rank INT_FLOAT_CONVERSION_BADNESS = {2}; +static const struct rank INT_FLOAT_CONVERSION_BADNESS = {2,0}; /* Badness of conversion of pointer to void pointer */ -static const struct rank VOID_PTR_CONVERSION_BADNESS = {2}; +static const struct rank VOID_PTR_CONVERSION_BADNESS = {2,0}; /* Badness of conversion of pointer to boolean. */ -static const struct rank BOOL_PTR_CONVERSION_BADNESS = {3}; +static const struct rank BOOL_PTR_CONVERSION_BADNESS = {3,0}; /* Badness of converting derived to base class */ -static const struct rank BASE_CONVERSION_BADNESS = {2}; +static const struct rank BASE_CONVERSION_BADNESS = {2,0}; /* Badness of converting from non-reference to reference */ -static const struct rank REFERENCE_CONVERSION_BADNESS = {2}; +static const struct rank REFERENCE_CONVERSION_BADNESS = {2,0}; /* Non-standard conversions allowed by the debugger */ /* Converting a pointer to an int is usually OK */ -static const struct rank NS_POINTER_CONVERSION_BADNESS = {10}; +static const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0}; extern struct rank sum_ranks (struct rank a, struct rank b); diff --git a/gdb/testsuite/gdb.cp/oranking.exp b/gdb/testsuite/gdb.cp/oranking.exp index f1efb77..9c4e9dc 100644 --- a/gdb/testsuite/gdb.cp/oranking.exp +++ b/gdb/testsuite/gdb.cp/oranking.exp @@ -58,15 +58,12 @@ gdb_test "p test6()" "28" gdb_test "p foo6(bp)" "28" gdb_test "p test7()" "210" -setup_kfail "gdb/10343" *-*-* gdb_test "p foo7(cp)" "210" gdb_test "p test8()" "212" -setup_kfail "gdb/10343" *-*-* gdb_test "p foo8(co)" "212" gdb_test "p test9()" "214" -setup_kfail "gdb/12098" *-*-* gdb_test "p foo9(co)" "214" gdb_test "p test10()" "216" diff --git a/gdb/testsuite/gdb.cp/overload.cc b/gdb/testsuite/gdb.cp/overload.cc index dc117fb..bd2f96c 100644 --- a/gdb/testsuite/gdb.cp/overload.cc +++ b/gdb/testsuite/gdb.cp/overload.cc @@ -89,6 +89,14 @@ namespace XXX { void marker2() {} } +class A {}; +class B: public A {}; +class C: public B {}; +class D: C {}; + +int bar (A) { return 11; } +int bar (B) { return 22; } + int main () { char arg2 = 2; @@ -105,6 +113,15 @@ int main () int arg13 = 200.0; char arg14 = 'a'; + A a; + B b; + C c; + D d; + + bar (a); + bar (b); + bar (c); + char *str = (char *) "A"; foo foo_instance1(111); foo foo_instance2(222, str); @@ -132,6 +149,7 @@ int main () marker1(); // marker1-returns-here XXX::marker2(); // marker1-returns-here + return 0; } diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp index 25aeb07..05ca315 100644 --- a/gdb/testsuite/gdb.cp/overload.exp +++ b/gdb/testsuite/gdb.cp/overload.exp @@ -266,6 +266,11 @@ gdb_test "print foo_instance1.overload1arg(&arg14)" \ "\\$\[0-9\]+ = 14" \ "print call overloaded func char\\* arg" +gdb_test "print bar(a)" "= 11" +gdb_test "print bar(b)" "= 22" +gdb_test "print bar(c)" "= 22" +gdb_test "print bar(d)" "= 22" + # --- # List overloaded functions. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] Overload resolution among children of a common ancestor 2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla @ 2010-10-22 17:16 ` Tom Tromey 2010-11-02 18:05 ` sami wagiaalla 0 siblings, 1 reply; 8+ messages in thread From: Tom Tromey @ 2010-10-22 17:16 UTC (permalink / raw) To: sami wagiaalla; +Cc: gdb-patches >>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes: Sami> This patch does the quoted above, but through a subrank field int the Sami> newly created rank struct. This prevents the ranking amongst children Sami> of a common ancestor from interfering with other rankings. This looks good. Sami> /* Struct used to store conversion rankings. */ Sami> struct rank Sami> { Sami> - int rank; Sami> + short rank; Sami> + short subrank; I think the subrank field should have a comment explaining its purpose. This is ok with that change, with whatever minor changes are needed to account for the changes to patch #1. Tom ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [patch 2/2] Overload resolution among children of a common ancestor 2010-10-22 17:16 ` Tom Tromey @ 2010-11-02 18:05 ` sami wagiaalla 0 siblings, 0 replies; 8+ messages in thread From: sami wagiaalla @ 2010-11-02 18:05 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 179 bytes --] > This is ok with that change, with whatever minor changes are needed to > account for the changes to patch #1. > Updated patch attached, will commit once patch 1 is approved. [-- Attachment #2: overload_inheritance.patch --] [-- Type: text/x-patch, Size: 9279 bytes --] Fix derived class overload problem. 2010-10-19 Sami Wagiaalla <swagiaal@redhat.com> * gdbtypes.h (struct rank): Created subrank. * gdbtypes.c: Initialized subrank for all 'BADNESS' constants. (distance_to_ancestor): New function. (is_ancestor): Use distance_to_ancestor. (is_public_ancestor): Ditto. (sum_ranks): Handle subrank. (compare_ranks): Ditto. (rank_one_type): Subrank base conversions. 2010-10-19 Sami Wagiaalla <swagiaal@redhat.com> * gdb.cp/overload.exp: Added test for inheritance overload. * gdb.cp/overload.cc: Ditto. * gdb.cp/oranking.exp: Removed releveant kfails. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index bfeae90..a88cc38 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -43,25 +43,25 @@ /* Initialize BADNESS constants. */ -const struct rank LENGTH_MISMATCH_BADNESS = {100}; +const struct rank LENGTH_MISMATCH_BADNESS = {100,0}; -const struct rank TOO_FEW_PARAMS_BADNESS = {100}; -const struct rank INCOMPATIBLE_TYPE_BADNESS = {100}; +const struct rank TOO_FEW_PARAMS_BADNESS = {100,0}; +const struct rank INCOMPATIBLE_TYPE_BADNESS = {100,0}; -const struct rank EXACT_MATCH_BADNESS = {0}; +const struct rank EXACT_MATCH_BADNESS = {0,0}; -const struct rank INTEGER_PROMOTION_BADNESS = {1}; -const struct rank FLOAT_PROMOTION_BADNESS = {1}; -const struct rank BASE_PTR_CONVERSION_BADNESS = {1}; -const struct rank INTEGER_CONVERSION_BADNESS = {2}; -const struct rank FLOAT_CONVERSION_BADNESS = {2}; -const struct rank INT_FLOAT_CONVERSION_BADNESS = {2}; -const struct rank VOID_PTR_CONVERSION_BADNESS = {2}; -const struct rank BOOL_PTR_CONVERSION_BADNESS = {3}; -const struct rank BASE_CONVERSION_BADNESS = {2}; -const struct rank REFERENCE_CONVERSION_BADNESS = {2}; +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}; +const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0}; /* Floatformat pairs. */ const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = { @@ -1923,32 +1923,50 @@ class_types_same_p (const struct type *a, const struct type *b) && !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 @@ -1960,7 +1978,7 @@ do_is_ancestor (struct type *base, struct type *dclass, int public) 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 @@ -1969,7 +1987,7 @@ is_ancestor (struct type *base, struct type *dclass) 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. */ @@ -2041,6 +2059,7 @@ 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; } @@ -2053,11 +2072,19 @@ int compare_ranks (struct rank a, struct rank b) { if (a.rank == b.rank) - return 0; + { + 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; } @@ -2248,6 +2275,7 @@ types_equal (struct type *a, struct type *b) struct rank rank_one_type (struct type *parm, struct type *arg) { + struct rank rank = {0,0}; if (types_equal (parm, arg)) return EXACT_MATCH_BADNESS; @@ -2288,9 +2316,11 @@ rank_one_type (struct type *parm, struct type *arg) 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: @@ -2529,8 +2559,9 @@ rank_one_type (struct type *parm, struct type *arg) { 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; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 917938a..52447f3 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -852,7 +852,15 @@ struct vbase /* Struct used to store conversion rankings. */ struct rank { - int rank; + short rank; + + /* When two conversions are of the same type and therefore have the same + rank, subrank is used to differentiate the two. + Eg: Two derived-class-pointer to base-class-pointer conversions would + both have base pointer conversion rank, but the conversion with the + shorter distance to the ancestor is preferable. 'subrank' would be used + to reflect that. */ + short subrank; }; /* Struct used for ranking a function for overload resolution */ diff --git a/gdb/testsuite/gdb.cp/oranking.exp b/gdb/testsuite/gdb.cp/oranking.exp index f1efb77..9c4e9dc 100644 --- a/gdb/testsuite/gdb.cp/oranking.exp +++ b/gdb/testsuite/gdb.cp/oranking.exp @@ -58,15 +58,12 @@ gdb_test "p test6()" "28" gdb_test "p foo6(bp)" "28" gdb_test "p test7()" "210" -setup_kfail "gdb/10343" *-*-* gdb_test "p foo7(cp)" "210" gdb_test "p test8()" "212" -setup_kfail "gdb/10343" *-*-* gdb_test "p foo8(co)" "212" gdb_test "p test9()" "214" -setup_kfail "gdb/12098" *-*-* gdb_test "p foo9(co)" "214" gdb_test "p test10()" "216" diff --git a/gdb/testsuite/gdb.cp/overload.cc b/gdb/testsuite/gdb.cp/overload.cc index dc117fb..bd2f96c 100644 --- a/gdb/testsuite/gdb.cp/overload.cc +++ b/gdb/testsuite/gdb.cp/overload.cc @@ -89,6 +89,14 @@ namespace XXX { void marker2() {} } +class A {}; +class B: public A {}; +class C: public B {}; +class D: C {}; + +int bar (A) { return 11; } +int bar (B) { return 22; } + int main () { char arg2 = 2; @@ -105,6 +113,15 @@ int main () int arg13 = 200.0; char arg14 = 'a'; + A a; + B b; + C c; + D d; + + bar (a); + bar (b); + bar (c); + char *str = (char *) "A"; foo foo_instance1(111); foo foo_instance2(222, str); @@ -132,6 +149,7 @@ int main () marker1(); // marker1-returns-here XXX::marker2(); // marker1-returns-here + return 0; } diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp index 25aeb07..05ca315 100644 --- a/gdb/testsuite/gdb.cp/overload.exp +++ b/gdb/testsuite/gdb.cp/overload.exp @@ -266,6 +266,11 @@ gdb_test "print foo_instance1.overload1arg(&arg14)" \ "\\$\[0-9\]+ = 14" \ "print call overloaded func char\\* arg" +gdb_test "print bar(a)" "= 11" +gdb_test "print bar(b)" "= 22" +gdb_test "print bar(c)" "= 22" +gdb_test "print bar(d)" "= 22" + # --- # List overloaded functions. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-11-02 20:31 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor sami wagiaalla 2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla 2010-10-22 15:39 ` Tom Tromey 2010-11-02 18:04 ` sami wagiaalla 2010-11-02 20:31 ` Tom Tromey 2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla 2010-10-22 17:16 ` Tom Tromey 2010-11-02 18:05 ` sami wagiaalla
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).