From: swagiaal Date: Thu, 4 Nov 2010 20:43:22 +0000 (+0000) Subject: Fix derived class overload problem. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=7f05541bcc7d0969cc749ca6351cc352e1942b77;p=pf3gnuchains%2Fpf3gnuchains4x.git Fix derived class overload problem. 2010-11-04 Sami Wagiaalla * 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-11-04 Sami Wagiaalla * 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/ChangeLog b/gdb/ChangeLog index 6da3bcf218..ff6b5fd064 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2010-11-04 Sami Wagiaalla + * 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-11-04 Sami Wagiaalla + * gdbtypes.h: Create struct rank. Convert all 'BADNESS' macros to const struct rank declarations. (sum_ranks): New function. diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 3b29c54b45..d96d0f86ec 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] = { @@ -1967,32 +1967,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 @@ -2004,7 +2022,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 @@ -2013,7 +2031,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. */ @@ -2085,6 +2103,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; } @@ -2097,11 +2116,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; } @@ -2292,6 +2319,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; @@ -2332,9 +2360,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: @@ -2573,8 +2603,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 8ce2c82f57..51eb4456e4 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/ChangeLog b/gdb/testsuite/ChangeLog index 914d0449da..d68e8509b0 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-11-04 Sami Wagiaalla + + * gdb.cp/overload.exp: Added test for inheritance overload. + * gdb.cp/overload.cc: Ditto. + * gdb.cp/oranking.exp: Removed releveant kfails. + 2010-11-04 Jan Kratochvil Joel Brobecker diff --git a/gdb/testsuite/gdb.cp/oranking.exp b/gdb/testsuite/gdb.cp/oranking.exp index f1efb77283..9c4e9dcf23 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 dc117fb3f0..bd2f96ca70 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 25aeb07451..05ca315b89 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.