summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSami Wagiaalla <swagiaal@redhat.com>2010-11-04 20:43:25 +0000
committerSami Wagiaalla <swagiaal@redhat.com>2010-11-04 20:43:25 +0000
commita9d5ef47f3a97fed25e4a5a507b2607e1adc629a (patch)
treec3e78f94bc101d9e7b62508d356f7b56241bb0ba
parent6403aeeaa1ebe388c0fc518f02569f9323a79981 (diff)
downloadbinutils-gdb-a9d5ef47f3a97fed25e4a5a507b2607e1adc629a.tar.gz
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/ChangeLog12
-rw-r--r--gdb/gdbtypes.c95
-rw-r--r--gdb/gdbtypes.h10
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.cp/oranking.exp3
-rw-r--r--gdb/testsuite/gdb.cp/overload.cc18
-rw-r--r--gdb/testsuite/gdb.cp/overload.exp5
7 files changed, 113 insertions, 36 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6da3bcf2181..ff6b5fd0644 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 3b29c54b458..d96d0f86ec1 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 8ce2c82f579..51eb4456e40 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 914d0449dab..d68e8509b0e 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 f1efb77283b..9c4e9dcf237 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 dc117fb3f05..bd2f96ca708 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 25aeb074515..05ca315b896 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.