This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
FYI: fix PR c++/8017
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 08 Feb 2010 13:47:54 -0700
- Subject: FYI: fix PR c++/8017
- Reply-to: Tom Tromey <tromey at redhat dot com>
I'm checking this in.
This fixes two related overloading bugs.
The problem is that a qualified call to an overloaded static method or
function in a namespace doesn't work (something like "print A::func()").
The bug is that the OP_FUNC case does not special-case OP_SCOPE; and the
OP_SCOPE fails.
This patch fixes the problem by adding some special code to the OP_FUNC
case for OP_SCOPE. This code is pretty ugly, and now even a bit more
so; I am considering cleaning it up.
A big chunk of this patch is const-correctifying some functions so that
I could verify that one change I made in the OP_FUNC code was safe.
Built and regtested on x86-64 (compile farm).
New test case included.
There is still one related case I know of that fails, where a qualified
name is used to do a non-virtual call to a method in a superclass. I
think this will require more work in the overloading code. I added an
error to try to catch this case -- but it appears that some other
problem prevents us from reaching it. I'm going to at least file a PR
about this.
Tom
2010-02-08 Tom Tromey <tromey@redhat.com>
PR c++/8017:
* value.h: Update.
* valops.c (search_struct_field): Make 'name' const.
(search_struct_method): Likewise.
(find_method_list): Make 'method' const.
(value_struct_elt): Make 'name' and 'err' const.
(value_find_oload_method_list): Make 'method' const.
(find_overload_match): Make 'name' const.
* eval.c (evaluate_subexp_standard): New locals function,
function_name.
<OP_FUNCALL>: Handle OP_SCOPE specially.
2010-02-08 Tom Tromey <tromey@redhat.com>
PR c++/8017:
* gdb.cp/overload.exp: Add tests.
* gdb.cp/overload.cc (struct K): New.
(namespace N): New.
(main): Call new functions.
(K::staticoverload): Define.
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.126
diff -u -r1.126 eval.c
--- eval.c 26 Jan 2010 16:53:43 -0000 1.126
+++ eval.c 8 Feb 2010 20:18:02 -0000
@@ -696,6 +696,8 @@
long mem_offset;
struct type **arg_types;
int save_pos1;
+ struct symbol *function = NULL;
+ char *function_name = NULL;
pc = (*pos)++;
op = exp->elts[pc].opcode;
@@ -1410,6 +1412,47 @@
/* Now, say which argument to start evaluating from */
tem = 2;
}
+ else if (op == OP_SCOPE
+ && overload_resolution
+ && (exp->language_defn->la_language == language_cplus))
+ {
+ /* Unpack it locally so we can properly handle overload
+ resolution. */
+ struct type *qual_type;
+ char *name;
+ int local_tem;
+
+ pc2 = (*pos)++;
+ local_tem = longest_to_int (exp->elts[pc2 + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (local_tem + 1);
+ type = exp->elts[pc2 + 1].type;
+ name = &exp->elts[pc2 + 3].string;
+
+ function = NULL;
+ function_name = NULL;
+ if (TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+ {
+ function = cp_lookup_symbol_namespace (TYPE_TAG_NAME (type),
+ name, NULL,
+ get_selected_block (0),
+ VAR_DOMAIN, 1);
+ if (function == NULL)
+ error (_("No symbol \"%s\" in namespace \"%s\"."),
+ name, TYPE_TAG_NAME (type));
+
+ tem = 1;
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION);
+ function_name = name;
+
+ arg2 = value_zero (type, lval_memory);
+ ++nargs;
+ tem = 2;
+ }
+ }
else
{
/* Non-method function call */
@@ -1441,15 +1484,22 @@
/* signal end of arglist */
argvec[tem] = 0;
- if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR
+ || (op == OP_SCOPE && function_name != NULL))
{
int static_memfuncp;
- char tstr[256];
+ char *tstr;
/* Method invocation : stuff "this" as first parameter */
argvec[1] = arg2;
- /* Name of method from expression */
- strcpy (tstr, &exp->elts[pc2 + 2].string);
+
+ if (op != OP_SCOPE)
+ {
+ /* Name of method from expression */
+ tstr = &exp->elts[pc2 + 2].string;
+ }
+ else
+ tstr = function_name;
if (overload_resolution && (exp->language_defn->la_language == language_cplus))
{
@@ -1466,7 +1516,13 @@
&arg2 /* the object */ , NULL,
&valp, NULL, &static_memfuncp);
-
+ if (op == OP_SCOPE && !static_memfuncp)
+ {
+ /* For the time being, we don't handle this. */
+ error (_("Call to overloaded function %s requires "
+ "`this' pointer"),
+ function_name);
+ }
argvec[1] = arg2; /* the ``this'' pointer */
argvec[0] = valp; /* use the method found after overload resolution */
}
@@ -1499,7 +1555,7 @@
argvec[1] = arg2;
argvec[0] = arg1;
}
- else if (op == OP_VAR_VALUE)
+ else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL))
{
/* Non-member function being called */
/* fn: This can only be done for C++ functions. A C-style function
@@ -1511,6 +1567,9 @@
/* Language is C++, do some overload resolution before evaluation */
struct symbol *symp;
+ if (op == OP_VAR_VALUE)
+ function = exp->elts[save_pos1+2].symbol;
+
/* Prepare list of argument types for overload resolution */
arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
for (ix = 1; ix <= nargs; ix++)
@@ -1518,12 +1577,18 @@
(void) find_overload_match (arg_types, nargs, NULL /* no need for name */ ,
0 /* not method */ , 0 /* strict match */ ,
- NULL, exp->elts[save_pos1+2].symbol /* the function */ ,
+ NULL, function /* the function */ ,
NULL, &symp, NULL);
- /* Now fix the expression being evaluated */
- exp->elts[save_pos1+2].symbol = symp;
- argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
+ if (op == OP_VAR_VALUE)
+ {
+ /* Now fix the expression being evaluated */
+ exp->elts[save_pos1+2].symbol = symp;
+ argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1,
+ noside);
+ }
+ else
+ argvec[0] = value_of_variable (symp, get_selected_block (0));
}
else
{
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.236
diff -u -r1.236 valops.c
--- valops.c 4 Feb 2010 21:04:30 -0000 1.236
+++ valops.c 8 Feb 2010 20:18:03 -0000
@@ -53,12 +53,12 @@
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static struct value *search_struct_field (char *, struct value *,
+static struct value *search_struct_field (const char *, struct value *,
int, struct type *, int);
-static struct value *search_struct_method (char *, struct value **,
- struct value **,
- int, int *, struct type *);
+static struct value *search_struct_method (const char *, struct value **,
+ struct value **,
+ int, int *, struct type *);
static int find_oload_champ_namespace (struct type **, int,
const char *, const char *,
@@ -100,7 +100,7 @@
static struct value *cast_into_complex (struct type *, struct value *);
-static struct fn_field *find_method_list (struct value **, char *,
+static struct fn_field *find_method_list (struct value **, const char *,
int, struct type *, int *,
struct type **, int *);
@@ -1806,7 +1806,7 @@
fields, look for a baseclass named NAME. */
static struct value *
-search_struct_field (char *name, struct value *arg1, int offset,
+search_struct_field (const char *name, struct value *arg1, int offset,
struct type *type, int looking_for_baseclass)
{
int i;
@@ -1963,7 +1963,7 @@
(value) -1, else return NULL. */
static struct value *
-search_struct_method (char *name, struct value **arg1p,
+search_struct_method (const char *name, struct value **arg1p,
struct value **args, int offset,
int *static_memfuncp, struct type *type)
{
@@ -2093,7 +2093,7 @@
struct value *
value_struct_elt (struct value **argp, struct value **args,
- char *name, int *static_memfuncp, char *err)
+ const char *name, int *static_memfuncp, const char *err)
{
struct type *t;
struct value *v;
@@ -2188,7 +2188,7 @@
*/
static struct fn_field *
-find_method_list (struct value **argp, char *method,
+find_method_list (struct value **argp, const char *method,
int offset, struct type *type, int *num_fns,
struct type **basetype, int *boffset)
{
@@ -2258,7 +2258,7 @@
*/
struct fn_field *
-value_find_oload_method_list (struct value **argp, char *method,
+value_find_oload_method_list (struct value **argp, const char *method,
int offset, int *num_fns,
struct type **basetype, int *boffset)
{
@@ -2315,7 +2315,7 @@
int
find_overload_match (struct type **arg_types, int nargs,
- char *name, int method, int lax,
+ const char *name, int method, int lax,
struct value **objp, struct symbol *fsym,
struct value **valp, struct symbol **symp,
int *staticp)
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.153
diff -u -r1.153 value.h
--- value.h 18 Jan 2010 20:54:34 -0000 1.153
+++ value.h 8 Feb 2010 20:18:03 -0000
@@ -431,8 +431,8 @@
extern struct value *value_struct_elt (struct value **argp,
struct value **args,
- char *name, int *static_memfuncp,
- char *err);
+ const char *name, int *static_memfuncp,
+ const char *err);
extern struct value *value_aggregate_elt (struct type *curtype,
char *name,
@@ -442,12 +442,13 @@
extern struct value *value_static_field (struct type *type, int fieldno);
-extern struct fn_field *value_find_oload_method_list (struct value **, char *,
+extern struct fn_field *value_find_oload_method_list (struct value **,
+ const char *,
int, int *,
struct type **, int *);
extern int find_overload_match (struct type **arg_types, int nargs,
- char *name, int method, int lax,
+ const char *name, int method, int lax,
struct value **objp, struct symbol *fsym,
struct value **valp, struct symbol **symp,
int *staticp);
Index: testsuite/gdb.cp/overload.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/overload.cc,v
retrieving revision 1.3
diff -u -r1.3 overload.cc
--- testsuite/gdb.cp/overload.cc 28 Dec 2009 21:45:24 -0000 1.3
+++ testsuite/gdb.cp/overload.cc 8 Feb 2010 20:18:04 -0000
@@ -42,7 +42,18 @@
int overloadargs (int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9, int a10, int a11);
+};
+
+struct K {
+ static int staticoverload ();
+ static int staticoverload (int);
+ static int staticoverload (int, int);
+};
+namespace N {
+ int nsoverload () { return 1; }
+ int nsoverload (int x) { return x; }
+ int nsoverload (int x, int y) { return x + y; }
};
int intToChar (char c)
@@ -97,6 +108,14 @@
foo foo_instance2(222, str);
foo foo_instance3(foo_instance2);
+ // Some calls to ensure all the functions are emitted.
+ K::staticoverload();
+ K::staticoverload(2);
+ K::staticoverload(2, 3);
+ N::nsoverload();
+ N::nsoverload(2);
+ N::nsoverload(2, 3);
+
#ifdef usestubs
set_debug_traps();
breakpoint();
@@ -196,3 +215,6 @@
+int K::staticoverload () { return 1; }
+int K::staticoverload (int x) { return x; }
+int K::staticoverload (int x, int y) { return x + y; }
Index: testsuite/gdb.cp/overload.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/overload.exp,v
retrieving revision 1.13
diff -u -r1.13 overload.exp
--- testsuite/gdb.cp/overload.exp 1 Jan 2010 07:32:01 -0000 1.13
+++ testsuite/gdb.cp/overload.exp 8 Feb 2010 20:18:04 -0000
@@ -299,6 +299,16 @@
gdb_test "print overloadNamespace('a')" ".\[0-9\]* = 1"
gdb_test "print overloadNamespace(dummyInstance)" ".\[0-9\]* = 2"
+# Static methods.
+gdb_test "print K::staticoverload ()" " = 1"
+gdb_test "print K::staticoverload (2)" " = 2"
+gdb_test "print K::staticoverload (2, 3)" " = 5"
+
+# Namespace-qualified functions.
+gdb_test "print N::nsoverload ()" " = 1"
+gdb_test "print N::nsoverload (2)" " = 2"
+gdb_test "print N::nsoverload (2, 3)" " = 5"
+
if ![runto 'XXX::marker2'] then {
perror "couldn't run to XXX::marker2"
continue