Fixed void* vs int* overload issue (PR C++/10343).

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

	* gdbtypes.h: Create BASE_PTR_CONVERSION_BADNESS.
	* gdbtypes.c (rank_one_type): Move type comparison code out of here
	to...
	(types_equal): ...here. And changed it as follows:
	Outside of typedefs type must be of the same TYPE_CODE.
	When compairing two pointers or references they are equal if their
	targets are equal.
	Correct pointer conversions.

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

	* gdb.cp/converts.cc: New test program.
	* gdb.cp/converts.exp: New test.
	* gdb.cp/overload.exp: Added test for void* vs int*.
	* gdb.cp/overload.exp: Ditto.
	* gdb.cp/oranking.exp: Removed related kfail.
This commit is contained in:
Sami Wagiaalla 2010-10-14 16:13:43 +00:00
parent 5c3da5ea2e
commit 7062b0a0df
9 changed files with 207 additions and 28 deletions

View File

@ -1,3 +1,14 @@
2010-10-14 Sami Wagiaalla <swagiaal@redhat.com>
* gdbtypes.h: Create BASE_PTR_CONVERSION_BADNESS.
* gdbtypes.c (rank_one_type): Move type comparison code out of here
to...
(types_equal): ...here. And changed it as follows:
Outside of typedefs type must be of the same TYPE_CODE.
When compairing two pointers or references they are equal if their
targets are equal.
Correct pointer conversions.
2010-10-14 Pierre Muller <muller@ics.u-strasbg.fr>
* p-lang.c (is_pascal_string_type): Avoid crashes on structures

View File

@ -2102,6 +2102,56 @@ integer_types_same_name_p (const char *first, const char *second)
return 1;
}
/* Compares type A to type B returns 1 if the represent the same type
0 otherwise. */
static int
types_equal (struct type *a, struct type *b)
{
/* Identical type pointers. */
/* However, this still doesn't catch all cases of same type for b
and a. The reason is that builtin types are different from
the same ones constructed from the object. */
if (a == b)
return 1;
/* Resolve typedefs */
if (TYPE_CODE (a) == TYPE_CODE_TYPEDEF)
a = check_typedef (a);
if (TYPE_CODE (b) == TYPE_CODE_TYPEDEF)
b = check_typedef (b);
/* If after resolving typedefs a and b are not of the same type
code then they are not equal. */
if (TYPE_CODE (a) != TYPE_CODE (b))
return 0;
/* If a and b are both pointers types or both reference types then
they are equal of the same type iff the objects they refer to are
of the same type. */
if (TYPE_CODE (a) == TYPE_CODE_PTR
|| TYPE_CODE (a) == TYPE_CODE_REF)
return types_equal (TYPE_TARGET_TYPE (a),
TYPE_TARGET_TYPE (b));
/*
Well, damnit, if the names are exactly the same, I'll say they
are exactly the same. This happens when we generate method
stubs. The types won't point to the same address, but they
really are the same.
*/
if (TYPE_NAME (a) && TYPE_NAME (b)
&& strcmp (TYPE_NAME (a), TYPE_NAME (b)) == 0)
return 1;
/* Check if identical after resolving typedefs. */
if (a == b)
return 1;
return 0;
}
/* Compare one type (PARM) for compatibility with another (ARG).
* PARM is intended to be the parameter type of a function; and
* ARG is the supplied argument's type. This function tests if
@ -2115,11 +2165,8 @@ integer_types_same_name_p (const char *first, const char *second)
int
rank_one_type (struct type *parm, struct type *arg)
{
/* 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
the same ones constructed from the object. */
if (parm == arg)
if (types_equal (parm, arg))
return 0;
/* Resolve typedefs */
@ -2128,21 +2175,6 @@ rank_one_type (struct type *parm, struct type *arg)
if (TYPE_CODE (arg) == TYPE_CODE_TYPEDEF)
arg = check_typedef (arg);
/*
Well, damnit, if the names are exactly the same, I'll say they
are exactly the same. This happens when we generate method
stubs. The types won't point to the same address, but they
really are the same.
*/
if (TYPE_NAME (parm) && TYPE_NAME (arg)
&& !strcmp (TYPE_NAME (parm), TYPE_NAME (arg)))
return 0;
/* Check if identical after resolving typedefs. */
if (parm == arg)
return 0;
/* See through references, since we can almost make non-references
references. */
if (TYPE_CODE (arg) == TYPE_CODE_REF)
@ -2166,15 +2198,23 @@ rank_one_type (struct type *parm, struct type *arg)
switch (TYPE_CODE (arg))
{
case TYPE_CODE_PTR:
if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID
&& TYPE_CODE (TYPE_TARGET_TYPE (arg)) != TYPE_CODE_VOID)
/* Allowed pointer conversions are:
(a) pointer to void-pointer conversion. */
if (TYPE_CODE (TYPE_TARGET_TYPE (parm)) == TYPE_CODE_VOID)
return VOID_PTR_CONVERSION_BADNESS;
else
return rank_one_type (TYPE_TARGET_TYPE (parm),
TYPE_TARGET_TYPE (arg));
/* (b) pointer to ancestor-pointer conversion. */
if (is_ancestor (TYPE_TARGET_TYPE (parm),
TYPE_TARGET_TYPE (arg)))
return BASE_PTR_CONVERSION_BADNESS;
return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_ARRAY:
return rank_one_type (TYPE_TARGET_TYPE (parm),
TYPE_TARGET_TYPE (arg));
if (types_equal (TYPE_TARGET_TYPE (parm),
TYPE_TARGET_TYPE (arg)))
return 0;
return INCOMPATIBLE_TYPE_BADNESS;
case TYPE_CODE_FUNC:
return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
case TYPE_CODE_INT:

View File

@ -1399,6 +1399,9 @@ extern int is_unique_ancestor (struct type *, struct value *);
#define INTEGER_PROMOTION_BADNESS 1
/* Badness of floating promotion */
#define FLOAT_PROMOTION_BADNESS 1
/* Badness of converting a derived class pointer
to a base class pointer. */
#define BASE_PTR_CONVERSION_BADNESS 1
/* Badness of integral conversion */
#define INTEGER_CONVERSION_BADNESS 2
/* Badness of floating conversion */

View File

@ -1,3 +1,11 @@
2010-10-14 Sami Wagiaalla <swagiaal@redhat.com>
* gdb.cp/converts.cc: New test program.
* gdb.cp/converts.exp: New test.
* gdb.cp/overload.exp: Added test for void* vs int*.
* gdb.cp/overload.exp: Ditto.
* gdb.cp/oranking.exp: Removed related kfail.
2010-10-13 Doug Evans <dje@google.com>
* lib/gdb-python.exp (gdb_check_python_config): New function.

View File

@ -0,0 +1,53 @@
class A {};
class B : public A {};
typedef A TA1;
typedef A TA2;
typedef TA2 TA3;
int foo0_1 (TA1) { return 1; }
int foo0_2 (TA3) { return 2; }
int foo0_3 (A***) { return 3; }
int foo1_1 (char *) {return 11;}
int foo1_2 (char[]) {return 12;}
int foo1_3 (int*) {return 13;}
int foo1_4 (A*) {return 14;}
int foo1_5 (void*) {return 15;}
int foo1_6 (void**) {return 15;}
int foo2_1 (char** ) {return 21;}
int foo2_2 (char[][1]) {return 22;}
int foo2_3 (char *[]) {return 23;}
int foo2_4 (int *[]) {return 24;}
int main()
{
TA2 ta; // typedef to..
foo0_1 (ta); // ..another typedef
foo0_2 (ta); // ..typedef of a typedef
B*** bppp; // Pointer-to-pointer-to-pointer-to-derived..
//foo0_3(bppp); // Pointer-to-pointer-to-pointer base.
foo0_3((A***)bppp); // to ensure that the function is emitted.
char *a; // pointer to..
B *bp;
foo1_1 (a); // ..pointer
foo1_2 (a); // ..array
foo1_3 ((int*)a); // ..pointer of wrong type
foo1_3 ((int*)bp); // ..pointer of wrong type
foo1_4 (bp); // ..ancestor pointer
foo1_5 (bp); // ..void pointer
foo1_6 ((void**)bp); // ..void pointer
char **b; // pointer pointer to..
char ba[1][1];
foo1_5 (b); // ..void pointer
foo2_1 (b); // ..pointer pointer
foo2_2 (ba); // ..array of arrays
foo2_3 (b); // ..array of pointers
foo2_4 ((int**)b); // ..array of wrong pointers
return 0; // end of main
}

View File

@ -0,0 +1,48 @@
# Copyright 2008 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
set testfile converts
set srcfile ${testfile}.cc
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } {
return -1
}
############################################
if ![runto_main] then {
perror "couldn't run to breakpoint main"
continue
}
gdb_breakpoint [gdb_get_line_number "end of main"]
gdb_continue_to_breakpoint "end of main"
gdb_test "p foo0_1 (ta)" "= 1" "typedef to another typedef"
gdb_test "p foo0_2 (ta)" "= 2" "typedef to typedef of a typedef"
gdb_test "p foo0_3 (bppp)" "Cannot resolve.*" \
"Pointer-to-pointer-to-pointer derived to Pointer-to-pointer-to-pointer base."
gdb_test "p foo1_1 (a)" "= 11" "pointer to pointer"
gdb_test "p foo1_2 (a)" "= 12" "pointer to array"
gdb_test "p foo1_3 (a)" "Cannot resolve.*" "pointer to pointer of wrong type"
gdb_test "p foo1_3 (bp)" "Cannot resolve.*" "pointer to pointer of wrong type"
gdb_test "p foo1_4 (bp)" "= 14" "pointer to ancestor pointer"
gdb_test "p foo1_5 (bp)" "= 15" "pointer to void pointer"
gdb_test "p foo1_5 (b)" "= 15" "pointer pointer to void pointer"
gdb_test "p foo2_1 (b)" "= 21" "pointer pointer to pointer pointer"
gdb_test "p foo2_2 (b)" "Cannot resolve.*" "pointer pointer to array of arrays"
gdb_test "p foo2_3 (b)" "= 23" "pointer pointer to array of pointers"
gdb_test "p foo2_4 (b)" "Cannot resolve.*" "pointer pointer to array of wrong pointers"

View File

@ -56,7 +56,6 @@ setup_kfail "gdb/12098" *-*-*
gdb_test "p foo5(c)" "26"
gdb_test "p test6()" "28"
setup_kfail "gdb/10343" *-*-*
gdb_test "p foo6(bp)" "28"
gdb_test "p test7()" "210"

View File

@ -24,6 +24,9 @@ int overload1arg (unsigned long);
int overload1arg (float);
int overload1arg (double);
int overload1arg (int*);
int overload1arg (void*);
int overloadfnarg (void);
int overloadfnarg (int);
int overloadfnarg (int, int (*) (int));
@ -99,6 +102,8 @@ int main ()
unsigned long arg10 =10;
float arg11 =100.0;
double arg12 = 200.0;
int arg13 = 200.0;
char arg14 = 'a';
char *str = (char *) "A";
foo foo_instance1(111);
@ -150,6 +155,8 @@ int foo::overload1arg (long arg) { arg = 0; return 9;}
int foo::overload1arg (unsigned long arg) { arg = 0; return 10;}
int foo::overload1arg (float arg) { arg = 0; return 11;}
int foo::overload1arg (double arg) { arg = 0; return 12;}
int foo::overload1arg (int* arg) { arg = 0; return 13;}
int foo::overload1arg (void* arg) { arg = 0; return 14;}
/* Test to see that we can explicitly request overloaded functions
with function pointers in the prototype. */

View File

@ -80,6 +80,8 @@ set re_methods "${re_methods}${ws}int overload1arg\\(long( int)?\\);"
set re_methods "${re_methods}${ws}int overload1arg\\((unsigned long|long unsigned)( int)?\\);"
set re_methods "${re_methods}${ws}int overload1arg\\(float\\);"
set re_methods "${re_methods}${ws}int overload1arg\\(double\\);"
set re_methods "${re_methods}${ws}int overload1arg\\(int \\*\\);"
set re_methods "${re_methods}${ws}int overload1arg\\(void \\*\\);"
set re_methods "${re_methods}${ws}int overloadfnarg\\((void|)\\);"
set re_methods "${re_methods}${ws}int overloadfnarg\\(int\\);"
set re_methods "${re_methods}${ws}int overloadfnarg\\(int, int ?\\(\\*\\) ?\\(int\\)\\);"
@ -256,6 +258,14 @@ gdb_test "print foo_instance1.overload1arg((double)arg12)" \
"\\$\[0-9\]+ = 12" \
"print call overloaded func double arg"
gdb_test "print foo_instance1.overload1arg(&arg13)" \
"\\$\[0-9\]+ = 13" \
"print call overloaded func int\\* arg"
gdb_test "print foo_instance1.overload1arg(&arg14)" \
"\\$\[0-9\]+ = 14" \
"print call overloaded func char\\* arg"
# ---
# List overloaded functions.