public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [patch] Overload resolution among children of a common ancestor
@ 2010-08-30 16:11 sami wagiaalla
  2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla
  2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla
  0 siblings, 2 replies; 8+ messages in thread
From: sami wagiaalla @ 2010-08-30 16:11 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 362 bytes --]

This patch introduces a cost for converting types to their ancestor 
types that depends on the distance to that ancestor. It also disables 
the calling of functions which are inherited through non-public 
inheritance. I had to update a couple of test cases for that.

This patch was regression tested on Fedora 13 on x8664 with gcc 4.4.4. 
No regressions.

Sami

[-- Attachment #2: overload_inheritance.patch --]
[-- Type: text/x-patch, Size: 5858 bytes --]

Fix overload resolution between children of common ancestor.

2010-08-30  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdbtypes.h (distance_to_public_ancestor): New function.
	* gdbtypes.c (distance_to_public_ancestor): New function.
	(rank_one_type): Concider distance_to_public_ancestor when ranking
	two structs.
	(is_public_ancestor): Use distance_to_public_ancestor.

2010-08-30  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdb.cp/overload.cc: Add testing for overload resolution based on
	distance to ancestor.
	* gdb.cp/overload.exp: Ditto.
	* gdb.cp/virtfunc2.cc (Obj2): Change inheritance to public.
	Add calls to the function calls being tested.
	* gdb.cp/derivation.cc (G): Changed inheritance to public.
	Add calls to the function calls being tested.

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b7fb110..39912d6 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1903,23 +1903,48 @@ is_ancestor (struct type *base, struct type *dclass)
 int
 is_public_ancestor (struct type *base, struct type *dclass)
 {
+  return (distance_to_public_ancestor (base, dclass) >= 0);
+}
+
+/* If BASE is a public 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_public_ancestor (A, A) = 0
+   distance_to_public_ancestor (A, B) = 1
+   distance_to_public_ancestor (A, C) = 2
+   distance_to_public_ancestor (A, D) = -1
+
+   */
+int
+distance_to_public_ancestor (struct type *base, struct type *dclass)
+{
   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 (! BASETYPE_VIA_PUBLIC (dclass, i))
 	continue;
-      if (is_public_ancestor (base, TYPE_BASECLASS (dclass, i)))
-	return 1;
+
+      d = distance_to_public_ancestor (base, TYPE_BASECLASS (dclass, i));
+      if (d >= 0)
+        return 1 + d;
+
     }
 
-  return 0;
+  return -1;
 }
 
 /* A helper function for is_unique_ancestor.  */
@@ -2120,6 +2145,7 @@ integer_types_same_name_p (const char *first, const char *second)
 int
 rank_one_type (struct type *parm, struct type *arg)
 {
+  int d;
   /* Identical type pointers.  */
   /* However, this still doesn't catch all cases of same type for arg
      and param.  The reason is that builtin types are different from
@@ -2411,8 +2437,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;
+	  d = distance_to_public_ancestor (parm, arg);
+	  if (d >= 0)
+	    return BASE_CONVERSION_BADNESS + d;
 	  /* else fall through */
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index ed8d613..6a1eb80 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1358,6 +1358,8 @@ extern int class_types_same_p (const struct type *, const struct type *);
 
 extern int is_ancestor (struct type *, struct type *);
 
+extern int distance_to_public_ancestor (struct type *, struct type *);
+
 extern int is_public_ancestor (struct type *, struct type *);
 
 extern int is_unique_ancestor (struct type *, struct value *);
diff --git a/gdb/testsuite/gdb.cp/derivation.cc b/gdb/testsuite/gdb.cp/derivation.cc
index f6d42e7..02999c1 100644
--- a/gdb/testsuite/gdb.cp/derivation.cc
+++ b/gdb/testsuite/gdb.cp/derivation.cc
@@ -96,7 +96,7 @@ public:
     
 };
 
-class G : private A, public B, protected C {
+class G : public A, public B, public C {
 public:
     int g;
     int gg;
@@ -207,7 +207,10 @@ int main(void)
     E e_instance;
     F f_instance;
     G g_instance;
-    
+
+    g_instance.afoo();
+    g_instance.cfoo();
+
     #ifdef usestubs
        set_debug_traps();
        breakpoint();
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..048e074 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)" "Cannot resolve function bar to any overloaded instance"
+
 # ---
 
 # List overloaded functions.
diff --git a/gdb/testsuite/gdb.cp/virtfunc2.cc b/gdb/testsuite/gdb.cp/virtfunc2.cc
index 90f3eda..666a495 100644
--- a/gdb/testsuite/gdb.cp/virtfunc2.cc
+++ b/gdb/testsuite/gdb.cp/virtfunc2.cc
@@ -27,7 +27,7 @@ public:
   virtual int do_print() { return 123456; }
 };
 
-class Obj2 : Obj,  virtual public interface
+class Obj2 : public Obj,  virtual public interface
 {
   virtual int do_print2() { return 654321; }
 };
@@ -35,5 +35,7 @@ class Obj2 : Obj,  virtual public interface
 int main(int argc, char** argv) {
   Obj o;
   Obj2 o2;
+  o2.do_print();
+
   return 0;	// marker 1
 }

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 1/2] Overload resolution among children of a common ancestor
  2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor sami wagiaalla
@ 2010-10-19 20:27 ` sami wagiaalla
  2010-10-22 15:39   ` Tom Tromey
  2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla
  1 sibling, 1 reply; 8+ messages in thread
From: sami wagiaalla @ 2010-10-19 20:27 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 128 bytes --]

This patch introduces a rank struct to be used instead of the int that 
is normally used to represent the rank of a conversion.

[-- Attachment #2: overload_rank.patch --]
[-- Type: text/x-patch, Size: 11508 bytes --]

Create and use struct rank.

2010-10-18  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdbtypes.h: Create struct rank.
	Convert all 'BADNESS' macros to const struct rank declarations.
	(sum_ranks): New function.
	(compare_ranks): New function.
	* valops.c (find_oload_champ): Updated.
	(classify_oload_match): Use compare_ranks.
	Improved comments.
	(compare_parameters): Use compare_ranks.
	* gdbtypes.c (sum_ranks): New function.
	(compare_ranks): New function.
	(compare_badness): Use compare_ranks.
	(rank_function): Use global constants instead of literals.
	(rank_one_type): Ditto.
	Return struct rank.
	Use sum_ranks.

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index d08dbfe..6213f3c 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2012,6 +2012,30 @@ is_unique_ancestor (struct type *base, struct value *val)
 
 \f
 
+/* Return the sum of the rank of A with the rank of B.  */
+struct rank
+sum_ranks (struct rank a, struct rank b)
+{
+  struct rank c;
+  c.rank = a.rank + b.rank;
+  return c;
+}
+
+/* Compare rank A and B and return:
+   0 if a = b
+   1 if a is better than b
+  -1 if b is better than a.  */
+int
+compare_ranks (struct rank a, struct rank b)
+{
+  if (a.rank == b.rank)
+    return 0;
+
+  if (a.rank < b.rank)
+    return 1;
+
+  return -1;
+}
 
 /* Functions for overload resolution begin here */
 
@@ -2036,7 +2060,7 @@ compare_badness (struct badness_vector *a, struct badness_vector *b)
   /* Subtract b from a */
   for (i = 0; i < a->length; i++)
     {
-      tmp = a->rank[i] - b->rank[i];
+      tmp = compare_ranks (b->rank[i], a->rank[i]);
       if (tmp > 0)
 	found_pos = 1;
       else if (tmp < 0)
@@ -2084,7 +2108,7 @@ rank_function (struct type **parms, int nparms,
      arguments and ellipsis parameter lists, we should consider those
      and rank the length-match more finely.  */
 
-  LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0;
+  LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : EXACT_MATCH_BADNESS;
 
   /* Now rank all the parameters of the candidate function */
   for (i = 1; i <= min_len; i++)
@@ -2195,12 +2219,12 @@ types_equal (struct type *a, struct type *b)
  * PARM is to ARG.  The higher the return value, the worse the match.
  * Generally the "bad" conversions are all uniformly assigned a 100.  */
 
-int
+struct rank
 rank_one_type (struct type *parm, struct type *arg)
 {
 
   if (types_equal (parm, arg))
-    return 0;
+    return EXACT_MATCH_BADNESS;
 
   /* Resolve typedefs */
   if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
@@ -2211,11 +2235,11 @@ rank_one_type (struct type *parm, struct type *arg)
   /* See through references, since we can almost make non-references
      references.  */
   if (TYPE_CODE (arg) == TYPE_CODE_REF)
-    return (rank_one_type (parm, TYPE_TARGET_TYPE (arg))
-	    + REFERENCE_CONVERSION_BADNESS);
+    return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg)),
+                       REFERENCE_CONVERSION_BADNESS));
   if (TYPE_CODE (parm) == TYPE_CODE_REF)
-    return (rank_one_type (TYPE_TARGET_TYPE (parm), arg)
-	    + REFERENCE_CONVERSION_BADNESS);
+    return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg),
+                       REFERENCE_CONVERSION_BADNESS));
   if (overload_debug)
   /* Debugging only.  */
     fprintf_filtered (gdb_stderr, 
@@ -2246,7 +2270,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_ARRAY:
 	  if (types_equal (TYPE_TARGET_TYPE (parm),
 	                   TYPE_TARGET_TYPE (arg)))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	case TYPE_CODE_FUNC:
 	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
@@ -2289,7 +2313,7 @@ rank_one_type (struct type *parm, struct type *arg)
 		{
 		  /* This case only for character types */
 		  if (TYPE_NOSIGN (arg))
-		    return 0;	/* plain char -> plain char */
+		    return EXACT_MATCH_BADNESS;	/* plain char -> plain char */
 		  else		/* signed/unsigned char -> plain char */
 		    return INTEGER_CONVERSION_BADNESS;
 		}
@@ -2301,7 +2325,7 @@ rank_one_type (struct type *parm, struct type *arg)
 			 unsigned long -> unsigned long */
 		      if (integer_types_same_name_p (TYPE_NAME (parm), 
 						     TYPE_NAME (arg)))
-			return 0;
+			return EXACT_MATCH_BADNESS;
 		      else if (integer_types_same_name_p (TYPE_NAME (arg), 
 							  "int")
 			       && integer_types_same_name_p (TYPE_NAME (parm),
@@ -2325,7 +2349,7 @@ rank_one_type (struct type *parm, struct type *arg)
 		{
 		  if (integer_types_same_name_p (TYPE_NAME (parm), 
 						 TYPE_NAME (arg)))
-		    return 0;
+		    return EXACT_MATCH_BADNESS;
 		  else if (integer_types_same_name_p (TYPE_NAME (arg), 
 						      "int")
 			   && integer_types_same_name_p (TYPE_NAME (parm), 
@@ -2391,19 +2415,19 @@ rank_one_type (struct type *parm, struct type *arg)
 	  if (TYPE_NOSIGN (parm))
 	    {
 	      if (TYPE_NOSIGN (arg))
-		return 0;
+		return EXACT_MATCH_BADNESS;
 	      else
 		return INTEGER_CONVERSION_BADNESS;
 	    }
 	  else if (TYPE_UNSIGNED (parm))
 	    {
 	      if (TYPE_UNSIGNED (arg))
-		return 0;
+		return EXACT_MATCH_BADNESS;
 	      else
 		return INTEGER_PROMOTION_BADNESS;
 	    }
 	  else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  else
 	    return INTEGER_CONVERSION_BADNESS;
 	default:
@@ -2437,7 +2461,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_PTR:
 	  return BOOL_PTR_CONVERSION_BADNESS;
 	case TYPE_CODE_BOOL:
-	  return 0;
+	  return EXACT_MATCH_BADNESS;
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
@@ -2449,7 +2473,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	  if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
 	    return FLOAT_PROMOTION_BADNESS;
 	  else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  else
 	    return FLOAT_CONVERSION_BADNESS;
 	case TYPE_CODE_INT:
@@ -2468,7 +2492,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_FLT:
 	  return FLOAT_PROMOTION_BADNESS;
 	case TYPE_CODE_COMPLEX:
-	  return 0;
+	  return EXACT_MATCH_BADNESS;
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 5617a1d..56590b2 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -849,11 +849,17 @@ struct vbase
     struct vbase *next;		/* next in chain */
   };
 
+/* Struct used to store conversion rankings.  */
+struct rank
+  {
+    int rank;
+  };
+
 /* Struct used for ranking a function for overload resolution */
 struct badness_vector
   {
     int length;
-    int *rank;
+    struct rank *rank;
   };
 
 /* GNAT Ada-specific information for various Ada types.  */
@@ -1396,45 +1402,52 @@ 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 */
-#define LENGTH_MISMATCH_BADNESS      100
+static const struct rank LENGTH_MISMATCH_BADNESS = {100};
+
 /* Dummy badness value for nonexistent parameter positions */
-#define TOO_FEW_PARAMS_BADNESS       100
+static const struct rank TOO_FEW_PARAMS_BADNESS = {100};
 /* Badness if no conversion among types */
-#define INCOMPATIBLE_TYPE_BADNESS    100
+static const struct rank INCOMPATIBLE_TYPE_BADNESS = {100};
+
+/* Badness of an exact match.  */
+static const struct rank EXACT_MATCH_BADNESS = {0};
 
 /* Badness of integral promotion */
-#define INTEGER_PROMOTION_BADNESS      1
+static const struct rank INTEGER_PROMOTION_BADNESS = {1};
 /* Badness of floating promotion */
-#define FLOAT_PROMOTION_BADNESS        1
+static const struct rank FLOAT_PROMOTION_BADNESS = {1};
 /* Badness of converting a derived class pointer
    to a base class pointer.  */
-#define BASE_PTR_CONVERSION_BADNESS    1
+static const struct rank BASE_PTR_CONVERSION_BADNESS = {1};
 /* Badness of integral conversion */
-#define INTEGER_CONVERSION_BADNESS     2
+static const struct rank INTEGER_CONVERSION_BADNESS = {2};
 /* Badness of floating conversion */
-#define FLOAT_CONVERSION_BADNESS       2
+static const struct rank FLOAT_CONVERSION_BADNESS = {2};
 /* Badness of integer<->floating conversions */
-#define INT_FLOAT_CONVERSION_BADNESS   2
+static const struct rank INT_FLOAT_CONVERSION_BADNESS = {2};
 /* Badness of conversion of pointer to void pointer */
-#define VOID_PTR_CONVERSION_BADNESS    2
+static const struct rank VOID_PTR_CONVERSION_BADNESS = {2};
 /* Badness of conversion of pointer to boolean.  */
-#define BOOL_PTR_CONVERSION_BADNESS    3
+static const struct rank BOOL_PTR_CONVERSION_BADNESS = {3};
 /* Badness of converting derived to base class */
-#define BASE_CONVERSION_BADNESS        2
+static const struct rank BASE_CONVERSION_BADNESS = {2};
 /* Badness of converting from non-reference to reference */
-#define REFERENCE_CONVERSION_BADNESS   2
+static const struct rank REFERENCE_CONVERSION_BADNESS = {2};
 
 /* Non-standard conversions allowed by the debugger */
 /* Converting a pointer to an int is usually OK */
-#define NS_POINTER_CONVERSION_BADNESS 10
+static const struct rank NS_POINTER_CONVERSION_BADNESS = {10};
+
 
+extern struct rank sum_ranks (struct rank a, struct rank b);
+extern int compare_ranks (struct rank a, struct rank b);
 
 extern int compare_badness (struct badness_vector *, struct badness_vector *);
 
 extern struct badness_vector *rank_function (struct type **, int,
 					     struct type **, int);
 
-extern int rank_one_type (struct type *, struct type *);
+extern struct rank rank_one_type (struct type *, struct type *);
 
 extern void recursive_dump_type (struct type *, int);
 
diff --git a/gdb/valops.c b/gdb/valops.c
index fe4576e..eb0bb7d 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2884,7 +2884,7 @@ find_oload_champ (struct type **arg_types, int nargs, int method,
 	  for (jj = 0; jj < nargs - static_offset; jj++)
 	    fprintf_filtered (gdb_stderr,
 			      "...Badness @ %d : %d\n", 
-			      jj, bv->rank[jj]);
+			      jj, bv->rank[jj].rank);
 	  fprintf_filtered (gdb_stderr,
 			    "Overload resolution champion is %d, ambiguous? %d\n", 
 			    oload_champ, oload_ambiguous);
@@ -2918,9 +2918,15 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
 
   for (ix = 1; ix <= nargs - static_offset; ix++)
     {
-      if (oload_champ_bv->rank[ix] >= 100)
+      /* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS
+         or worse return INCOMPATIBLE.  */
+      if (compare_ranks (oload_champ_bv->rank[ix],
+                         INCOMPATIBLE_TYPE_BADNESS) <= 0)
 	return INCOMPATIBLE;	/* Truly mismatched types.  */
-      else if (oload_champ_bv->rank[ix] >= 10)
+      /* Otherwise If this conversion is as bad as
+         NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD.  */
+      else if (compare_ranks (oload_champ_bv->rank[ix],
+                              NS_POINTER_CONVERSION_BADNESS) <= 0)
 	return NON_STANDARD;	/* Non-standard type conversions
 				   needed.  */
     }
@@ -3056,9 +3062,9 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial)
 
       for (i = 0; i < TYPE_NFIELDS (t2); ++i)
 	{
-	  if (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
-			      TYPE_FIELD_TYPE (t2, i))
-	      != 0)
+	  if (compare_ranks (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
+	                                   TYPE_FIELD_TYPE (t2, i)),
+	                     EXACT_MATCH_BADNESS) != 0)
 	    return 0;
 	}
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 2/2] Overload resolution among children of a common ancestor
  2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor sami wagiaalla
  2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla
@ 2010-10-19 20:30 ` sami wagiaalla
  2010-10-22 17:16   ` Tom Tromey
  1 sibling, 1 reply; 8+ messages in thread
From: sami wagiaalla @ 2010-10-19 20:30 UTC (permalink / raw)
  To: gdb-patches

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 1/2] Overload resolution among children of a common ancestor
  2010-10-19 20:27 ` [patch 1/2] " sami wagiaalla
@ 2010-10-22 15:39   ` Tom Tromey
  2010-11-02 18:04     ` sami wagiaalla
  0 siblings, 1 reply; 8+ messages in thread
From: Tom Tromey @ 2010-10-22 15:39 UTC (permalink / raw)
  To: sami wagiaalla; +Cc: gdb-patches

>>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes:

Sami> This patch introduces a rank struct to be used instead of the int that
Sami> is normally used to represent the rank of a conversion.

Thanks.

I have a few nits to pick but nothing serious.

Sami> +/* Return the sum of the rank of A with the rank of B.  */
Sami> +struct rank

Blank line between comment and start of function.

Sami> +/* Compare rank A and B and return:
Sami> +   0 if a = b
Sami> +   1 if a is better than b
Sami> +  -1 if b is better than a.  */
Sami> +int
Sami> +compare_ranks (struct rank a, struct rank b)

Likewise.

Sami> -  LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0;
Sami> +  LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : EXACT_MATCH_BADNESS;

I think this needs a line break.

Sami>  /* Badness if parameter list length doesn't match arg list length */
Sami> -#define LENGTH_MISMATCH_BADNESS      100
Sami> +static const struct rank LENGTH_MISMATCH_BADNESS = {100};

Instead of defining a static instance in the header, define a single
instance with a different (not upper-case) name in a .c file, put an
extern declaration in the header, and then make the #define refer to it.

Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 2/2] Overload resolution among children of a common ancestor
  2010-10-19 20:30 ` [patch 2/2] " sami wagiaalla
@ 2010-10-22 17:16   ` Tom Tromey
  2010-11-02 18:05     ` sami wagiaalla
  0 siblings, 1 reply; 8+ messages in thread
From: Tom Tromey @ 2010-10-22 17:16 UTC (permalink / raw)
  To: sami wagiaalla; +Cc: gdb-patches

>>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes:

Sami> This patch does the quoted above, but through a subrank field int the
Sami> newly created rank struct. This prevents the ranking amongst children
Sami> of a common ancestor from interfering with other rankings.

This looks good.

Sami>  /* Struct used to store conversion rankings.  */
Sami>  struct rank
Sami>    {
Sami> -    int rank;
Sami> +    short rank;
Sami> +    short subrank;

I think the subrank field should have a comment explaining its purpose.

This is ok with that change, with whatever minor changes are needed to
account for the changes to patch #1.

Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 1/2] Overload resolution among children of a common ancestor
  2010-10-22 15:39   ` Tom Tromey
@ 2010-11-02 18:04     ` sami wagiaalla
  2010-11-02 20:31       ` Tom Tromey
  0 siblings, 1 reply; 8+ messages in thread
From: sami wagiaalla @ 2010-11-02 18:04 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 606 bytes --]

Revised patch attached.

> Sami>   /* Badness if parameter list length doesn't match arg list length */
> Sami>  -#define LENGTH_MISMATCH_BADNESS      100
> Sami>  +static const struct rank LENGTH_MISMATCH_BADNESS = {100};
>
> Instead of defining a static instance in the header, define a single
> instance with a different (not upper-case) name in a .c file, put an
> extern declaration in the header, and then make the #define refer to it.
>

Hmm.. is it cool if I just declare the constants 'extern const' in the 
header and then define them in gdbtypes.c, without #defines ? As in the 
attached patch.

[-- Attachment #2: overload_rank.patch --]
[-- Type: text/x-patch, Size: 12482 bytes --]

Create and use struct rank.

2010-10-18  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdbtypes.h: Create struct rank.
	Convert all 'BADNESS' macros to const struct rank declarations.
	(sum_ranks): New function.
	(compare_ranks): New function.
	* valops.c (find_oload_champ): Updated.
	(classify_oload_match): Use compare_ranks.
	Improved comments.
	(compare_parameters): Use compare_ranks.
	* gdbtypes.c: Initialize 'BADNESS' constants.
	(sum_ranks): New function.
	(compare_ranks): New function.
	(compare_badness): Use compare_ranks.
	(rank_function): Use global constants instead of literals.
	(rank_one_type): Ditto.
	Return struct rank.
	Use sum_ranks.

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index d08dbfe..bfeae90 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -41,6 +41,28 @@
 #include "hashtab.h"
 
 
+/* Initialize BADNESS constants.  */
+
+const struct rank LENGTH_MISMATCH_BADNESS = {100};
+
+const struct rank TOO_FEW_PARAMS_BADNESS = {100};
+const struct rank INCOMPATIBLE_TYPE_BADNESS = {100};
+
+const struct rank EXACT_MATCH_BADNESS = {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 NS_POINTER_CONVERSION_BADNESS = {10};
+
 /* Floatformat pairs.  */
 const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = {
   &floatformat_ieee_half_big,
@@ -2012,6 +2034,32 @@ is_unique_ancestor (struct type *base, struct value *val)
 
 \f
 
+/* Return the sum of the rank of A with the rank of B.  */
+
+struct rank
+sum_ranks (struct rank a, struct rank b)
+{
+  struct rank c;
+  c.rank = a.rank + b.rank;
+  return c;
+}
+
+/* Compare rank A and B and return:
+   0 if a = b
+   1 if a is better than b
+  -1 if b is better than a.  */
+
+int
+compare_ranks (struct rank a, struct rank b)
+{
+  if (a.rank == b.rank)
+    return 0;
+
+  if (a.rank < b.rank)
+    return 1;
+
+  return -1;
+}
 
 /* Functions for overload resolution begin here */
 
@@ -2036,7 +2084,7 @@ compare_badness (struct badness_vector *a, struct badness_vector *b)
   /* Subtract b from a */
   for (i = 0; i < a->length; i++)
     {
-      tmp = a->rank[i] - b->rank[i];
+      tmp = compare_ranks (b->rank[i], a->rank[i]);
       if (tmp > 0)
 	found_pos = 1;
       else if (tmp < 0)
@@ -2084,7 +2132,9 @@ rank_function (struct type **parms, int nparms,
      arguments and ellipsis parameter lists, we should consider those
      and rank the length-match more finely.  */
 
-  LENGTH_MATCH (bv) = (nargs != nparms) ? LENGTH_MISMATCH_BADNESS : 0;
+  LENGTH_MATCH (bv) = (nargs != nparms)
+		      ? LENGTH_MISMATCH_BADNESS
+		      : EXACT_MATCH_BADNESS;
 
   /* Now rank all the parameters of the candidate function */
   for (i = 1; i <= min_len; i++)
@@ -2195,12 +2245,12 @@ types_equal (struct type *a, struct type *b)
  * PARM is to ARG.  The higher the return value, the worse the match.
  * Generally the "bad" conversions are all uniformly assigned a 100.  */
 
-int
+struct rank
 rank_one_type (struct type *parm, struct type *arg)
 {
 
   if (types_equal (parm, arg))
-    return 0;
+    return EXACT_MATCH_BADNESS;
 
   /* Resolve typedefs */
   if (TYPE_CODE (parm) == TYPE_CODE_TYPEDEF)
@@ -2211,11 +2261,11 @@ rank_one_type (struct type *parm, struct type *arg)
   /* See through references, since we can almost make non-references
      references.  */
   if (TYPE_CODE (arg) == TYPE_CODE_REF)
-    return (rank_one_type (parm, TYPE_TARGET_TYPE (arg))
-	    + REFERENCE_CONVERSION_BADNESS);
+    return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg)),
+                       REFERENCE_CONVERSION_BADNESS));
   if (TYPE_CODE (parm) == TYPE_CODE_REF)
-    return (rank_one_type (TYPE_TARGET_TYPE (parm), arg)
-	    + REFERENCE_CONVERSION_BADNESS);
+    return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg),
+                       REFERENCE_CONVERSION_BADNESS));
   if (overload_debug)
   /* Debugging only.  */
     fprintf_filtered (gdb_stderr, 
@@ -2246,7 +2296,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_ARRAY:
 	  if (types_equal (TYPE_TARGET_TYPE (parm),
 	                   TYPE_TARGET_TYPE (arg)))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	case TYPE_CODE_FUNC:
 	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
@@ -2289,7 +2339,7 @@ rank_one_type (struct type *parm, struct type *arg)
 		{
 		  /* This case only for character types */
 		  if (TYPE_NOSIGN (arg))
-		    return 0;	/* plain char -> plain char */
+		    return EXACT_MATCH_BADNESS;	/* plain char -> plain char */
 		  else		/* signed/unsigned char -> plain char */
 		    return INTEGER_CONVERSION_BADNESS;
 		}
@@ -2301,7 +2351,7 @@ rank_one_type (struct type *parm, struct type *arg)
 			 unsigned long -> unsigned long */
 		      if (integer_types_same_name_p (TYPE_NAME (parm), 
 						     TYPE_NAME (arg)))
-			return 0;
+			return EXACT_MATCH_BADNESS;
 		      else if (integer_types_same_name_p (TYPE_NAME (arg), 
 							  "int")
 			       && integer_types_same_name_p (TYPE_NAME (parm),
@@ -2325,7 +2375,7 @@ rank_one_type (struct type *parm, struct type *arg)
 		{
 		  if (integer_types_same_name_p (TYPE_NAME (parm), 
 						 TYPE_NAME (arg)))
-		    return 0;
+		    return EXACT_MATCH_BADNESS;
 		  else if (integer_types_same_name_p (TYPE_NAME (arg), 
 						      "int")
 			   && integer_types_same_name_p (TYPE_NAME (parm), 
@@ -2391,19 +2441,19 @@ rank_one_type (struct type *parm, struct type *arg)
 	  if (TYPE_NOSIGN (parm))
 	    {
 	      if (TYPE_NOSIGN (arg))
-		return 0;
+		return EXACT_MATCH_BADNESS;
 	      else
 		return INTEGER_CONVERSION_BADNESS;
 	    }
 	  else if (TYPE_UNSIGNED (parm))
 	    {
 	      if (TYPE_UNSIGNED (arg))
-		return 0;
+		return EXACT_MATCH_BADNESS;
 	      else
 		return INTEGER_PROMOTION_BADNESS;
 	    }
 	  else if (!TYPE_NOSIGN (arg) && !TYPE_UNSIGNED (arg))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  else
 	    return INTEGER_CONVERSION_BADNESS;
 	default:
@@ -2437,7 +2487,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_PTR:
 	  return BOOL_PTR_CONVERSION_BADNESS;
 	case TYPE_CODE_BOOL:
-	  return 0;
+	  return EXACT_MATCH_BADNESS;
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
@@ -2449,7 +2499,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	  if (TYPE_LENGTH (arg) < TYPE_LENGTH (parm))
 	    return FLOAT_PROMOTION_BADNESS;
 	  else if (TYPE_LENGTH (arg) == TYPE_LENGTH (parm))
-	    return 0;
+	    return EXACT_MATCH_BADNESS;
 	  else
 	    return FLOAT_CONVERSION_BADNESS;
 	case TYPE_CODE_INT:
@@ -2468,7 +2518,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_FLT:
 	  return FLOAT_PROMOTION_BADNESS;
 	case TYPE_CODE_COMPLEX:
-	  return 0;
+	  return EXACT_MATCH_BADNESS;
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 5617a1d..917938a 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -849,11 +849,17 @@ struct vbase
     struct vbase *next;		/* next in chain */
   };
 
+/* Struct used to store conversion rankings.  */
+struct rank
+  {
+    int rank;
+  };
+
 /* Struct used for ranking a function for overload resolution */
 struct badness_vector
   {
     int length;
-    int *rank;
+    struct rank *rank;
   };
 
 /* GNAT Ada-specific information for various Ada types.  */
@@ -1396,45 +1402,52 @@ 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 */
-#define LENGTH_MISMATCH_BADNESS      100
+extern const struct rank LENGTH_MISMATCH_BADNESS;
+
 /* Dummy badness value for nonexistent parameter positions */
-#define TOO_FEW_PARAMS_BADNESS       100
+extern const struct rank TOO_FEW_PARAMS_BADNESS;
 /* Badness if no conversion among types */
-#define INCOMPATIBLE_TYPE_BADNESS    100
+extern const struct rank INCOMPATIBLE_TYPE_BADNESS;
+
+/* Badness of an exact match.  */
+extern const struct rank EXACT_MATCH_BADNESS;
 
 /* Badness of integral promotion */
-#define INTEGER_PROMOTION_BADNESS      1
+extern const struct rank INTEGER_PROMOTION_BADNESS;
 /* Badness of floating promotion */
-#define FLOAT_PROMOTION_BADNESS        1
+extern const struct rank FLOAT_PROMOTION_BADNESS;
 /* Badness of converting a derived class pointer
    to a base class pointer.  */
-#define BASE_PTR_CONVERSION_BADNESS    1
+extern const struct rank BASE_PTR_CONVERSION_BADNESS;
 /* Badness of integral conversion */
-#define INTEGER_CONVERSION_BADNESS     2
+extern const struct rank INTEGER_CONVERSION_BADNESS;
 /* Badness of floating conversion */
-#define FLOAT_CONVERSION_BADNESS       2
+extern const struct rank FLOAT_CONVERSION_BADNESS;
 /* Badness of integer<->floating conversions */
-#define INT_FLOAT_CONVERSION_BADNESS   2
+extern const struct rank INT_FLOAT_CONVERSION_BADNESS;
 /* Badness of conversion of pointer to void pointer */
-#define VOID_PTR_CONVERSION_BADNESS    2
+extern const struct rank VOID_PTR_CONVERSION_BADNESS;
 /* Badness of conversion of pointer to boolean.  */
-#define BOOL_PTR_CONVERSION_BADNESS    3
+extern const struct rank BOOL_PTR_CONVERSION_BADNESS;
 /* Badness of converting derived to base class */
-#define BASE_CONVERSION_BADNESS        2
+extern const struct rank BASE_CONVERSION_BADNESS;
 /* Badness of converting from non-reference to reference */
-#define REFERENCE_CONVERSION_BADNESS   2
+extern const struct rank REFERENCE_CONVERSION_BADNESS;
 
 /* Non-standard conversions allowed by the debugger */
 /* Converting a pointer to an int is usually OK */
-#define NS_POINTER_CONVERSION_BADNESS 10
+extern const struct rank NS_POINTER_CONVERSION_BADNESS;
+
 
+extern struct rank sum_ranks (struct rank a, struct rank b);
+extern int compare_ranks (struct rank a, struct rank b);
 
 extern int compare_badness (struct badness_vector *, struct badness_vector *);
 
 extern struct badness_vector *rank_function (struct type **, int,
 					     struct type **, int);
 
-extern int rank_one_type (struct type *, struct type *);
+extern struct rank rank_one_type (struct type *, struct type *);
 
 extern void recursive_dump_type (struct type *, int);
 
diff --git a/gdb/valops.c b/gdb/valops.c
index fe4576e..eb0bb7d 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2884,7 +2884,7 @@ find_oload_champ (struct type **arg_types, int nargs, int method,
 	  for (jj = 0; jj < nargs - static_offset; jj++)
 	    fprintf_filtered (gdb_stderr,
 			      "...Badness @ %d : %d\n", 
-			      jj, bv->rank[jj]);
+			      jj, bv->rank[jj].rank);
 	  fprintf_filtered (gdb_stderr,
 			    "Overload resolution champion is %d, ambiguous? %d\n", 
 			    oload_champ, oload_ambiguous);
@@ -2918,9 +2918,15 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
 
   for (ix = 1; ix <= nargs - static_offset; ix++)
     {
-      if (oload_champ_bv->rank[ix] >= 100)
+      /* If this conversion is as bad as INCOMPATIBLE_TYPE_BADNESS
+         or worse return INCOMPATIBLE.  */
+      if (compare_ranks (oload_champ_bv->rank[ix],
+                         INCOMPATIBLE_TYPE_BADNESS) <= 0)
 	return INCOMPATIBLE;	/* Truly mismatched types.  */
-      else if (oload_champ_bv->rank[ix] >= 10)
+      /* Otherwise If this conversion is as bad as
+         NS_POINTER_CONVERSION_BADNESS or worse return NON_STANDARD.  */
+      else if (compare_ranks (oload_champ_bv->rank[ix],
+                              NS_POINTER_CONVERSION_BADNESS) <= 0)
 	return NON_STANDARD;	/* Non-standard type conversions
 				   needed.  */
     }
@@ -3056,9 +3062,9 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial)
 
       for (i = 0; i < TYPE_NFIELDS (t2); ++i)
 	{
-	  if (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
-			      TYPE_FIELD_TYPE (t2, i))
-	      != 0)
+	  if (compare_ranks (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
+	                                   TYPE_FIELD_TYPE (t2, i)),
+	                     EXACT_MATCH_BADNESS) != 0)
 	    return 0;
 	}
 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 2/2] Overload resolution among children of a common ancestor
  2010-10-22 17:16   ` Tom Tromey
@ 2010-11-02 18:05     ` sami wagiaalla
  0 siblings, 0 replies; 8+ messages in thread
From: sami wagiaalla @ 2010-11-02 18:05 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 179 bytes --]


> This is ok with that change, with whatever minor changes are needed to
> account for the changes to patch #1.
>

Updated patch attached, will commit once patch 1 is approved.


[-- Attachment #2: overload_inheritance.patch --]
[-- Type: text/x-patch, Size: 9279 bytes --]

Fix derived class overload problem.

2010-10-19  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-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 bfeae90..a88cc38 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] = {
@@ -1923,32 +1923,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
@@ -1960,7 +1978,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
@@ -1969,7 +1987,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.  */
@@ -2041,6 +2059,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;
 }
 
@@ -2053,11 +2072,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;
 }
 
@@ -2248,6 +2275,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;
@@ -2288,9 +2316,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:
@@ -2529,8 +2559,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 917938a..52447f3 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/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.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch 1/2] Overload resolution among children of a common ancestor
  2010-11-02 18:04     ` sami wagiaalla
@ 2010-11-02 20:31       ` Tom Tromey
  0 siblings, 0 replies; 8+ messages in thread
From: Tom Tromey @ 2010-11-02 20:31 UTC (permalink / raw)
  To: sami wagiaalla; +Cc: gdb-patches

>>>>> "Sami" == sami wagiaalla <swagiaal@redhat.com> writes:

Sami> Hmm.. is it cool if I just declare the constants 'extern const' in the
Sami> header and then define them in gdbtypes.c, without #defines ? As in
Sami> the attached patch.

Yeah, that is fine.  It is a little weird to have uppercased names, but
I think it is fine in this case.

This patch is ok.  Thanks.

Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-11-02 20:31 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-30 16:11 [patch] Overload resolution among children of a common ancestor 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 ` [patch 2/2] " sami wagiaalla
2010-10-22 17:16   ` Tom Tromey
2010-11-02 18:05     ` sami wagiaalla

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