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