From: sami wagiaalla <swagiaal@redhat.com>
To: gdb-patches@sourceware.org
Subject: Re: [patch 2/2] Overload resolution among children of a common ancestor
Date: Tue, 19 Oct 2010 20:30:00 -0000 [thread overview]
Message-ID: <4CBDFFE1.6090903@redhat.com> (raw)
In-Reply-To: <4C7BD80C.1050906@redhat.com>
[-- 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.
next prev parent reply other threads:[~2010-10-19 20:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-30 16:11 [patch] " 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 ` sami wagiaalla [this message]
2010-10-22 17:16 ` [patch 2/2] " Tom Tromey
2010-11-02 18:05 ` sami wagiaalla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4CBDFFE1.6090903@redhat.com \
--to=swagiaal@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).