This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch 2/2] Overload resolution among children of a common ancestor


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]