OSDN Git Service

Fix derived class overload problem.
authorswagiaal <swagiaal>
Thu, 4 Nov 2010 20:43:22 +0000 (20:43 +0000)
committerswagiaal <swagiaal>
Thu, 4 Nov 2010 20:43:22 +0000 (20:43 +0000)
2010-11-04  Sami Wagiaalla  <swagiaal@redhat.com>

* gdbtypes.h (struct rank): Created subrank.
* gdbtypes.c: Initialized subrank for all
'BADNESS' constants.
(distance_to_ancestor): New function.
(is_ancestor): Use distance_to_ancestor.
(is_public_ancestor): Ditto.
(sum_ranks): Handle subrank.
(compare_ranks): Ditto.
(rank_one_type): Subrank base conversions.

2010-11-04  Sami Wagiaalla  <swagiaal@redhat.com>

* gdb.cp/overload.exp: Added test for inheritance
overload.
* gdb.cp/overload.cc: Ditto.
* gdb.cp/oranking.exp: Removed releveant kfails.

gdb/ChangeLog
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/oranking.exp
gdb/testsuite/gdb.cp/overload.cc
gdb/testsuite/gdb.cp/overload.exp

index 6da3bcf..ff6b5fd 100644 (file)
@@ -1,5 +1,17 @@
 2010-11-04  Sami Wagiaalla  <swagiaal@redhat.com>
 
+       * gdbtypes.h (struct rank): Created subrank.
+       * gdbtypes.c: Initialized subrank for all
+       'BADNESS' constants.
+       (distance_to_ancestor): New function.
+       (is_ancestor): Use distance_to_ancestor.
+       (is_public_ancestor): Ditto.
+       (sum_ranks): Handle subrank.
+       (compare_ranks): Ditto.
+       (rank_one_type): Subrank base conversions.
+
+2010-11-04  Sami Wagiaalla  <swagiaal@redhat.com>
+
        * gdbtypes.h: Create struct rank.
        Convert all 'BADNESS' macros to const struct rank declarations.
        (sum_ranks): New function.
index 3b29c54..d96d0f8 100644 (file)
 
 /* Initialize BADNESS constants.  */
 
-const struct rank LENGTH_MISMATCH_BADNESS = {100};
+const struct rank LENGTH_MISMATCH_BADNESS = {100,0};
 
-const struct rank TOO_FEW_PARAMS_BADNESS = {100};
-const struct rank INCOMPATIBLE_TYPE_BADNESS = {100};
+const struct rank TOO_FEW_PARAMS_BADNESS = {100,0};
+const struct rank INCOMPATIBLE_TYPE_BADNESS = {100,0};
 
-const struct rank EXACT_MATCH_BADNESS = {0};
+const struct rank EXACT_MATCH_BADNESS = {0,0};
 
-const struct rank INTEGER_PROMOTION_BADNESS = {1};
-const struct rank FLOAT_PROMOTION_BADNESS = {1};
-const struct rank BASE_PTR_CONVERSION_BADNESS = {1};
-const struct rank INTEGER_CONVERSION_BADNESS = {2};
-const struct rank FLOAT_CONVERSION_BADNESS = {2};
-const struct rank INT_FLOAT_CONVERSION_BADNESS = {2};
-const struct rank VOID_PTR_CONVERSION_BADNESS = {2};
-const struct rank BOOL_PTR_CONVERSION_BADNESS = {3};
-const struct rank BASE_CONVERSION_BADNESS = {2};
-const struct rank REFERENCE_CONVERSION_BADNESS = {2};
+const struct rank INTEGER_PROMOTION_BADNESS = {1,0};
+const struct rank FLOAT_PROMOTION_BADNESS = {1,0};
+const struct rank BASE_PTR_CONVERSION_BADNESS = {1,0};
+const struct rank INTEGER_CONVERSION_BADNESS = {2,0};
+const struct rank FLOAT_CONVERSION_BADNESS = {2,0};
+const struct rank INT_FLOAT_CONVERSION_BADNESS = {2,0};
+const struct rank VOID_PTR_CONVERSION_BADNESS = {2,0};
+const struct rank BOOL_PTR_CONVERSION_BADNESS = {3,0};
+const struct rank BASE_CONVERSION_BADNESS = {2,0};
+const struct rank REFERENCE_CONVERSION_BADNESS = {2,0};
 
-const struct rank NS_POINTER_CONVERSION_BADNESS = {10};
+const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
 
 /* Floatformat pairs.  */
 const struct floatformat *floatformats_ieee_half[BFD_ENDIAN_UNKNOWN] = {
@@ -1967,32 +1967,50 @@ class_types_same_p (const struct type *a, const struct type *b)
              && !strcmp (TYPE_NAME (a), TYPE_NAME (b))));
 }
 
-/* Check whether BASE is an ancestor or base class of DCLASS
-   Return 1 if so, and 0 if not.  If PUBLIC is 1 then only public
-   ancestors are considered, and the function returns 1 only if
-   BASE is a public ancestor of DCLASS.  */
+/* If BASE is an ancestor of DCLASS return the distance between them.
+   otherwise return -1;
+   eg:
+
+   class A {};
+   class B: public A {};
+   class C: public B {};
+   class D: C {};
+
+   distance_to_ancestor (A, A, 0) = 0
+   distance_to_ancestor (A, B, 0) = 1
+   distance_to_ancestor (A, C, 0) = 2
+   distance_to_ancestor (A, D, 0) = 3
+
+   If PUBLIC is 1 then only public ancestors are considered,
+   and the function returns the distance only if BASE is a public ancestor
+   of DCLASS.
+   Eg:
+
+   distance_to_ancestor (A, D, 1) = -1  */
 
 static int
-do_is_ancestor (struct type *base, struct type *dclass, int public)
+distance_to_ancestor (struct type *base, struct type *dclass, int public)
 {
   int i;
+  int d;
 
   CHECK_TYPEDEF (base);
   CHECK_TYPEDEF (dclass);
 
   if (class_types_same_p (base, dclass))
-    return 1;
+    return 0;
 
   for (i = 0; i < TYPE_N_BASECLASSES (dclass); i++)
     {
       if (public && ! BASETYPE_VIA_PUBLIC (dclass, i))
        continue;
 
-      if (do_is_ancestor (base, TYPE_BASECLASS (dclass, i), public))
-       return 1;
+      d = distance_to_ancestor (base, TYPE_BASECLASS (dclass, i), public);
+      if (d >= 0)
+       return 1 + d;
     }
 
-  return 0;
+  return -1;
 }
 
 /* Check whether BASE is an ancestor or base class or DCLASS
@@ -2004,7 +2022,7 @@ do_is_ancestor (struct type *base, struct type *dclass, int public)
 int
 is_ancestor (struct type *base, struct type *dclass)
 {
-  return do_is_ancestor (base, dclass, 0);
+  return distance_to_ancestor (base, dclass, 0) >= 0;
 }
 
 /* Like is_ancestor, but only returns true when BASE is a public
@@ -2013,7 +2031,7 @@ is_ancestor (struct type *base, struct type *dclass)
 int
 is_public_ancestor (struct type *base, struct type *dclass)
 {
-  return do_is_ancestor (base, dclass, 1);
+  return distance_to_ancestor (base, dclass, 1) >= 0;
 }
 
 /* A helper function for is_unique_ancestor.  */
@@ -2085,6 +2103,7 @@ sum_ranks (struct rank a, struct rank b)
 {
   struct rank c;
   c.rank = a.rank + b.rank;
+  c.subrank = a.subrank + b.subrank;
   return c;
 }
 
@@ -2097,11 +2116,19 @@ int
 compare_ranks (struct rank a, struct rank b)
 {
   if (a.rank == b.rank)
-    return 0;
+    {
+      if (a.subrank == b.subrank)
+       return 0;
+      if (a.subrank < b.subrank)
+       return 1;
+      if (a.subrank > b.subrank)
+       return -1;
+    }
 
   if (a.rank < b.rank)
     return 1;
 
+  /* a.rank > b.rank  */
   return -1;
 }
 
@@ -2292,6 +2319,7 @@ types_equal (struct type *a, struct type *b)
 struct rank
 rank_one_type (struct type *parm, struct type *arg)
 {
+  struct rank rank = {0,0};
 
   if (types_equal (parm, arg))
     return EXACT_MATCH_BADNESS;
@@ -2332,9 +2360,11 @@ rank_one_type (struct type *parm, struct type *arg)
            return VOID_PTR_CONVERSION_BADNESS;
 
          /* (b) pointer to ancestor-pointer conversion.  */
-         if (is_ancestor (TYPE_TARGET_TYPE (parm),
-                                 TYPE_TARGET_TYPE (arg)))
-           return BASE_PTR_CONVERSION_BADNESS;
+         rank.subrank = distance_to_ancestor (TYPE_TARGET_TYPE (parm),
+                                              TYPE_TARGET_TYPE (arg),
+                                              0);
+         if (rank.subrank >= 0)
+           return sum_ranks (BASE_PTR_CONVERSION_BADNESS, rank);
 
          return INCOMPATIBLE_TYPE_BADNESS;
        case TYPE_CODE_ARRAY:
@@ -2573,8 +2603,9 @@ rank_one_type (struct type *parm, struct type *arg)
        {
        case TYPE_CODE_STRUCT:
          /* Check for derivation */
-         if (is_ancestor (parm, arg))
-           return BASE_CONVERSION_BADNESS;
+         rank.subrank = distance_to_ancestor (parm, arg, 0);
+         if (rank.subrank >= 0)
+           return sum_ranks (BASE_CONVERSION_BADNESS, rank);
          /* else fall through */
        default:
          return INCOMPATIBLE_TYPE_BADNESS;
index 8ce2c82..51eb445 100644 (file)
@@ -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 */
index 914d044..d68e850 100644 (file)
@@ -1,3 +1,9 @@
+2010-11-04  Sami Wagiaalla  <swagiaal@redhat.com>
+
+       * gdb.cp/overload.exp: Added test for inheritance overload.
+       * gdb.cp/overload.cc: Ditto.
+       * gdb.cp/oranking.exp: Removed releveant kfails.
+
 2010-11-04  Jan Kratochvil  <jan.kratochvil@redhat.com>
            Joel Brobecker  <brobecker@adacore.com>
 
index f1efb77..9c4e9dc 100644 (file)
@@ -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"
index dc117fb..bd2f96c 100644 (file)
@@ -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;
 }
 
index 25aeb07..05ca315 100644 (file)
@@ -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.