diff options
author | Sami Wagiaalla <swagiaal@redhat.com> | 2010-11-04 20:43:25 +0000 |
---|---|---|
committer | Sami Wagiaalla <swagiaal@redhat.com> | 2010-11-04 20:43:25 +0000 |
commit | a9d5ef47f3a97fed25e4a5a507b2607e1adc629a (patch) | |
tree | c3e78f94bc101d9e7b62508d356f7b56241bb0ba | |
parent | 6403aeeaa1ebe388c0fc518f02569f9323a79981 (diff) | |
download | gdb-a9d5ef47f3a97fed25e4a5a507b2607e1adc629a.zip gdb-a9d5ef47f3a97fed25e4a5a507b2607e1adc629a.tar.gz gdb-a9d5ef47f3a97fed25e4a5a507b2607e1adc629a.tar.bz2 |
Fix derived class overload problem.
2010-11-04 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-11-04 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.
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 95 | ||||
-rw-r--r-- | gdb/gdbtypes.h | 10 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/oranking.exp | 3 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/overload.cc | 18 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/overload.exp | 5 |
7 files changed, 113 insertions, 36 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6da3bcf..ff6b5fd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2010-11-04 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-11-04 Sami Wagiaalla <swagiaal@redhat.com> + * 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 3b29c54..d96d0f8 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 8ce2c82..51eb445 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 914d044..d68e850 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-11-04 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. + 2010-11-04 Jan Kratochvil <jan.kratochvil@redhat.com> Joel Brobecker <brobecker@adacore.com> 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. |