Fix derived class overload problem.

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.
This commit is contained in:
Sami Wagiaalla 2010-11-04 20:43:25 +00:00
parent 6403aeeaa1
commit a9d5ef47f3
7 changed files with 113 additions and 36 deletions

View File

@ -1,3 +1,15 @@
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.

View File

@ -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] = {
@ -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;

View 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 */

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

View 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"

View 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;
}

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