This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FYI: fix PR c++/8017


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]