public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
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.

  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).