Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA] c++/13225
@ 2011-10-11 19:16 Keith Seitz
  2011-10-11 19:36 ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Keith Seitz @ 2011-10-11 19:16 UTC (permalink / raw)
  To: gdb-patches@sourceware.org ml

[-- Attachment #1: Type: text/plain, Size: 1631 bytes --]

Hi,

This bug exposes two problems with inferior function calling. First (and 
foremost), the user is attempting to do something like:

(gdb) p my_function
$1 = ... my_function (char *)
(gdb) p my_function(0)
Cannot resolve function my_function to any overloaded instance

This occurs because the parser interprets "0" as an integer, and the 
evaluator does not allow integer to pointer conversion. I cannot really 
think of a reason why gdb shouldn't be more permissive of this, as long 
as the INT will fit into a pointer.

Second, for a function which takes multiple arguments, 
classify_oload_match would not inspect all arguments. Instead it would 
return immediately upon finding any INCOMPATIBLE or NONSTANDARD ranking. 
For incompatible, this is okay -- subsequent arguments' ranks don't 
matter anymore.

However if we find NONSTANDARD, that doesn't mean that subsequent 
arguments' rankings should be dismissed, since one of these could be 
INCOMPATIBLE.

Tested on x86_64 with no regressions.

Keith

ChangeLog
2011-10-11  Keith Seitz  <keiths@redhat.com>

	c++/13225
	* gdbtypes.h (NS_POINTER_CONVERSION_BADNESS): Update comment.
	* gdbtypes.c (rank_one_type): Size permitting, allow int to pointer
	conversion.
	* valops.c (classify_oload_match): Inspect all arguments
	until INCOMPATIBLE is found. Return the worst badness found
	otherwise.

testsuite/ChangeLog:
2011-10-11  Keith Seitz  <keiths@redhat.com>

	c++/13225
	* gdb.cp/converts.cc (foo3_1): New function.
	* gdb.cp/converts.exp: Add test for int to pointer conversion.
	Add test to check if all arguments are checked for incompatible
	conversion BADNESS.


[-- Attachment #2: 13225.patch --]
[-- Type: text/x-patch, Size: 3529 bytes --]

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b1dada5..ca1547a 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2470,6 +2470,11 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_FUNC:
 	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
 	case TYPE_CODE_INT:
+	  /* The parser may return an integer type for a pointer, especially
+	     if that pointer is 0 (aka NULL).  Allow this if it will fit.  */
+	  if (TYPE_LENGTH (parm) >= TYPE_LENGTH (arg))
+	    return NS_POINTER_CONVERSION_BADNESS;
+	  /* fall through  */
 	case TYPE_CODE_ENUM:
 	case TYPE_CODE_FLAGS:
 	case TYPE_CODE_CHAR:
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 9d9785b..fa6b43c 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1557,7 +1557,8 @@ extern const struct rank BASE_CONVERSION_BADNESS;
 extern const struct rank REFERENCE_CONVERSION_BADNESS;
 
 /* Non-standard conversions allowed by the debugger */
-/* Converting a pointer to an int is usually OK.  */
+/* Converting a pointer to an int is usually OK.  Also allow
+   an int to be converted into a pointer.  */
 extern const struct rank NS_POINTER_CONVERSION_BADNESS;
 
 
diff --git a/gdb/valops.c b/gdb/valops.c
index e88e9dc..b15d12f 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -3081,6 +3081,7 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
 		      int static_offset)
 {
   int ix;
+  enum oload_classification worst = STANDARD;
 
   for (ix = 1; ix <= nargs - static_offset; ix++)
     {
@@ -3093,11 +3094,13 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
          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
+	worst = NON_STANDARD;	/* Non-standard type conversions
 				   needed.  */
     }
 
-  return STANDARD;		/* Only standard conversions needed.  */
+  /* If no INCOMPATIBLE classification was found, return the worst one
+     that was found (if any).  */
+  return worst;
 }
 
 /* C++: return 1 is NAME is a legitimate name for the destructor of
diff --git a/gdb/testsuite/gdb.cp/converts.cc b/gdb/testsuite/gdb.cp/converts.cc
index 34b6927..772510a 100644
--- a/gdb/testsuite/gdb.cp/converts.cc
+++ b/gdb/testsuite/gdb.cp/converts.cc
@@ -23,6 +23,8 @@ int foo2_2 (char[][1]) {return 22;}
 int foo2_3 (char *[])  {return 23;}
 int foo2_4 (int  *[])  {return 24;}
 
+int foo3_1 (int a, const char **b) { return 31; }
+
 int main()
 {
 
@@ -53,5 +55,8 @@ int main()
   foo2_2 (ba);       // ..array of arrays
   foo2_3 (b);        // ..array of pointers
   foo2_4 ((int**)b); // ..array of wrong pointers
+
+  foo3_1 (0, 0);     // int to pointer
+
   return 0;          // end of main
 }
diff --git a/gdb/testsuite/gdb.cp/converts.exp b/gdb/testsuite/gdb.cp/converts.exp
index 3f3b3c8..a3d375b 100644
--- a/gdb/testsuite/gdb.cp/converts.exp
+++ b/gdb/testsuite/gdb.cp/converts.exp
@@ -49,3 +49,8 @@ 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"
+
+gdb_test "p foo3_1 ((char *) 0, ta)" "Cannot resolve.*" \
+    "check all parameters for badness"
+
+gdb_test "p foo3_1 (0, 0)" "= 31" "int to pointer conversion"

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-11 19:16 [RFA] c++/13225 Keith Seitz
@ 2011-10-11 19:36 ` Tom Tromey
  2011-10-11 19:44   ` Keith Seitz
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2011-10-11 19:36 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches@sourceware.org ml

>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:

Keith> This occurs because the parser interprets "0" as an integer, and the
Keith> evaluator does not allow integer to pointer conversion. I cannot
Keith> really think of a reason why gdb shouldn't be more permissive of this,
Keith> as long as the INT will fit into a pointer.

Sami updated overloading resolution to more faithfully follow the C++
spec.  So, I think it would be useful to justify this patch in terms of
the standard.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-11 19:36 ` Tom Tromey
@ 2011-10-11 19:44   ` Keith Seitz
  2011-10-12 13:40     ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Keith Seitz @ 2011-10-11 19:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches@sourceware.org ml

On 10/11/2011 12:36 PM, Tom Tromey wrote:
>>>>>> "Keith" == Keith Seitz<keiths@redhat.com>  writes:

> Sami updated overloading resolution to more faithfully follow the C++
> spec.  So, I think it would be useful to justify this patch in terms of
> the standard.

Other than the "0" case (which shouldn't elicit a warning (but will)), I 
cannot justify allowing int -> pointer conversion via the standard. I 
was simply thinking of the (non-stupid) user who wanted (more 
generically) to do:

(gdb) print my_function (0x1234578)

That *would* require a cast, but I cannot convince myself that gdb need 
be so strict. Issue a warning about a non-standard conversion and do it.

"0" is, of course, a special case for pointer conversion. The standard 
explicitly allows that (4.10.1 in n3290 draft).

Let me know what you would like me to do.

Keith


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-11 19:44   ` Keith Seitz
@ 2011-10-12 13:40     ` Tom Tromey
  2011-10-13 16:07       ` Keith Seitz
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2011-10-12 13:40 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches@sourceware.org ml

>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:

Keith> Let me know what you would like me to do.

Please make it follow the spec.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-12 13:40     ` Tom Tromey
@ 2011-10-13 16:07       ` Keith Seitz
  2011-10-14 19:35         ` Tom Tromey
  0 siblings, 1 reply; 7+ messages in thread
From: Keith Seitz @ 2011-10-13 16:07 UTC (permalink / raw)
  To: gdb-patches@sourceware.org ml

[-- Attachment #1: Type: text/plain, Size: 2142 bytes --]

On 10/12/2011 06:39 AM, Tom Tromey wrote:
> Please make it follow the spec.

Here is a new version which does this and adds several new tests. A lot 
of the patch is massaging the rank_one_type/rank_function API to accept 
an array of struct values (vs struct types).

Is this more what you had in mind?

Keith

ChangeLog
2011-10-13  Keith Seitz  <keiths@redhat.com>

	c++/13225
	* eval.c (evaluate_subexp_standard): Do not construct
	an array of types; pass the value array directly to
	find_overload_match.
	* gdbtypes.h (NULL_POINTER_CONVERSION_BADNESS): Declare.
	(rank_function): Take an array of values instead of types.
	(rank_one_type): Add struct value * parameter.
	* gdbtypes.c (NULL_POINTER_CONVERSION_BADNESS): Define.
	(rank_function): For each argument, pass the argument's
	value to rank_one_type.
	(rank_one_type): Add VALUE parameter.
	If the parameter type is a pointer and the argument type
	is an integer, return NULL_POINTER_CONVERSION_BADNESS if
	VALUE is zero.
	Update all calls to rank_one_type, passing NULL for new
	VALUE parameter.
	* valarith.c (value_user_defined_cpp_op): Do not construct
	an array of types; pass the value array directly to
	find_overload_match.
	* valops.c (find_overload_method_list): Take an array of
	values instead of types.
	Save the type of OBJP for later use.
	Update calls to find_oload_champ, and find_oload_champ_namespace.
	(find_oload_champ_namespace): Take an array of values instead
	of types.
	(find_oload_champ_namespace_loop): Likewise.
	(find_oload_champ): Likewise.
	(classify_oload_match): Inspect all arguments
	until INCOMPATIBLE is found. Return the worst badness found
	otherwise.
	(compare_parameters): Update call to rank_one_type.
	* value.h (find_overload_match): Take an array of values instead
	of types.

testsuite/ChangeLog:
2011-10-13  Keith Seitz  <keiths@redhat.com>

	c++/13225
	* gdb.cp/converts.cc (foo3_1): New function.
	(foo3_2): New functions.
	* gdb.cp/converts.exp: Add tests for int to pointer conversion
	and null pointer conversions of integer constant zero.
	Add test to check if all arguments are checked for incompatible
	conversion BADNESS.

[-- Attachment #2: 13225-2.patch --]
[-- Type: text/x-patch, Size: 19758 bytes --]

diff --git a/gdb/eval.c b/gdb/eval.c
index 0956449..5d758d1 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1674,13 +1674,7 @@ evaluate_subexp_standard (struct type *expect_type,
           func_name = (char *) alloca (name_len + 1);
           strcpy (func_name, &exp->elts[string_pc + 1].string);
 
-          /* Prepare list of argument types for overload resolution.  */
-          arg_types = (struct type **)
-	    alloca (nargs * (sizeof (struct type *)));
-          for (ix = 1; ix <= nargs; ix++)
-            arg_types[ix - 1] = value_type (argvec[ix]);
-
-          find_overload_match (arg_types, nargs, func_name,
+          find_overload_match (&argvec[1], nargs, func_name,
                                NON_METHOD, /* not method */
 			       0,          /* strict match */
                                NULL, NULL, /* pass NULL symbol since
@@ -1716,13 +1710,7 @@ evaluate_subexp_standard (struct type *expect_type,
 		 evaluation.  */
 	      struct value *valp = NULL;
 
-	      /* Prepare list of argument types for overload resolution.  */
-	      arg_types = (struct type **)
-		alloca (nargs * (sizeof (struct type *)));
-	      for (ix = 1; ix <= nargs; ix++)
-		arg_types[ix - 1] = value_type (argvec[ix]);
-
-	      (void) find_overload_match (arg_types, nargs, tstr,
+	      (void) find_overload_match (&argvec[1], nargs, tstr,
 	                                  METHOD, /* method */
 					  0,      /* strict match */
 					  &arg2,  /* the object */
@@ -1793,13 +1781,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      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++)
-		arg_types[ix - 1] = value_type (argvec[ix]);
-
-	      (void) find_overload_match (arg_types, nargs,
+	      (void) find_overload_match (&argvec[1], nargs,
 					  NULL,        /* no need for name */
 	                                  NON_METHOD,  /* not method */
 					  0,           /* strict match */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index b1dada5..614b813 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -60,7 +60,7 @@ 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 NULL_POINTER_CONVERSION_BADNESS = {2,0};
 const struct rank NS_POINTER_CONVERSION_BADNESS = {10,0};
 
 /* Floatformat pairs.  */
@@ -2283,7 +2283,7 @@ compare_badness (struct badness_vector *a, struct badness_vector *b)
 
 struct badness_vector *
 rank_function (struct type **parms, int nparms, 
-	       struct type **args, int nargs)
+	       struct value **args, int nargs)
 {
   int i;
   struct badness_vector *bv;
@@ -2306,7 +2306,8 @@ rank_function (struct type **parms, int nparms,
 
   /* Now rank all the parameters of the candidate function.  */
   for (i = 1; i <= min_len; i++)
-    bv->rank[i] = rank_one_type (parms[i-1], args[i-1]);
+    bv->rank[i] = rank_one_type (parms[i - 1], value_type (args[i - 1]),
+				 args[i - 1]);
 
   /* If more arguments than parameters, add dummy entries.  */
   for (i = min_len + 1; i <= nargs; i++)
@@ -2405,6 +2406,7 @@ types_equal (struct type *a, struct type *b)
  * PARM is intended to be the parameter type of a function; and
  * ARG is the supplied argument's type.  This function tests if
  * the latter can be converted to the former.
+ * VALUE is the argument's value or NULL if none (or called recursively)
  *
  * Return 0 if they are identical types;
  * Otherwise, return an integer which corresponds to how compatible
@@ -2412,7 +2414,7 @@ types_equal (struct type *a, struct type *b)
  * Generally the "bad" conversions are all uniformly assigned a 100.  */
 
 struct rank
-rank_one_type (struct type *parm, struct type *arg)
+rank_one_type (struct type *parm, struct type *arg, struct value *value)
 {
   struct rank rank = {0,0};
 
@@ -2428,10 +2430,10 @@ 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 (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg)),
+    return (sum_ranks (rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL),
                        REFERENCE_CONVERSION_BADNESS));
   if (TYPE_CODE (parm) == TYPE_CODE_REF)
-    return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg),
+    return (sum_ranks (rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL),
                        REFERENCE_CONVERSION_BADNESS));
   if (overload_debug)
   /* Debugging only.  */
@@ -2468,8 +2470,16 @@ rank_one_type (struct type *parm, struct type *arg)
 	    return EXACT_MATCH_BADNESS;
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	case TYPE_CODE_FUNC:
-	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg);
+	  return rank_one_type (TYPE_TARGET_TYPE (parm), arg, NULL);
 	case TYPE_CODE_INT:
+	  if (value != NULL && TYPE_CODE (value_type (value)) == TYPE_CODE_INT
+	      && value_as_long (value) == 0)
+	    {
+	      /* Null pointer conversion: allow it to be cast to a pointer.
+		 [4.10.1 of C++ standard draft n3290]  */
+	      return NULL_POINTER_CONVERSION_BADNESS;
+	    }
+	  /* fall through  */
 	case TYPE_CODE_ENUM:
 	case TYPE_CODE_FLAGS:
 	case TYPE_CODE_CHAR:
@@ -2484,7 +2494,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	case TYPE_CODE_PTR:
 	case TYPE_CODE_ARRAY:
 	  return rank_one_type (TYPE_TARGET_TYPE (parm), 
-				TYPE_TARGET_TYPE (arg));
+				TYPE_TARGET_TYPE (arg), NULL);
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
@@ -2492,7 +2502,7 @@ rank_one_type (struct type *parm, struct type *arg)
       switch (TYPE_CODE (arg))
 	{
 	case TYPE_CODE_PTR:	/* funcptr -> func */
-	  return rank_one_type (parm, TYPE_TARGET_TYPE (arg));
+	  return rank_one_type (parm, TYPE_TARGET_TYPE (arg), NULL);
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
@@ -2748,7 +2758,7 @@ rank_one_type (struct type *parm, struct type *arg)
 	  /* Not in C++ */
 	case TYPE_CODE_SET:
 	  return rank_one_type (TYPE_FIELD_TYPE (parm, 0), 
-				TYPE_FIELD_TYPE (arg, 0));
+				TYPE_FIELD_TYPE (arg, 0), NULL);
 	default:
 	  return INCOMPATIBLE_TYPE_BADNESS;
 	}
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 9d9785b..3a69f51 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1555,6 +1555,8 @@ extern const struct rank BOOL_PTR_CONVERSION_BADNESS;
 extern const struct rank BASE_CONVERSION_BADNESS;
 /* Badness of converting from non-reference to reference.  */
 extern const struct rank REFERENCE_CONVERSION_BADNESS;
+/* Baddness of converting integer 0 to NULL pointer.  */
+extern const struct rank NULL_POINTER_CONVERSION;
 
 /* Non-standard conversions allowed by the debugger */
 /* Converting a pointer to an int is usually OK.  */
@@ -1567,9 +1569,9 @@ 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);
+					     struct value **, int);
 
-extern struct rank rank_one_type (struct type *, struct type *);
+extern struct rank rank_one_type (struct type *, struct type *, struct value *);
 
 extern void recursive_dump_type (struct type *, int);
 
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 68f649f..3250cc7 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -335,15 +335,8 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
 
   struct symbol *symp = NULL;
   struct value *valp = NULL;
-  struct type **arg_types;
-  int i;
 
-  arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
-  /* Prepare list of argument types for overload resolution.  */
-  for (i = 0; i < nargs; i++)
-    arg_types[i] = value_type (args[i]);
-
-  find_overload_match (arg_types, nargs, operator, BOTH /* could be method */,
+  find_overload_match (args, nargs, operator, BOTH /* could be method */,
                        0 /* strict match */, &args[0], /* objp */
                        NULL /* pass NULL symbol since symbol is unknown */,
                        &valp, &symp, static_memfuncp, 0);
diff --git a/gdb/valops.c b/gdb/valops.c
index e88e9dc..4fe1712 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -61,20 +61,20 @@ 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,
+static int find_oload_champ_namespace (struct value **, int,
 				       const char *, const char *,
 				       struct symbol ***,
 				       struct badness_vector **,
 				       const int no_adl);
 
 static
-int find_oload_champ_namespace_loop (struct type **, int,
+int find_oload_champ_namespace_loop (struct value **, int,
 				     const char *, const char *,
 				     int, struct symbol ***,
 				     struct badness_vector **, int *,
 				     const int no_adl);
 
-static int find_oload_champ (struct type **, int, int, int,
+static int find_oload_champ (struct value **, int, int, int,
 			     struct fn_field *, struct symbol **,
 			     struct badness_vector **);
 
@@ -2491,7 +2491,7 @@ value_find_oload_method_list (struct value **argp, const char *method,
 			   basetype, boffset);
 }
 
-/* Given an array of argument types (ARGTYPES) (which includes an
+/* Given an array of arguments (ARGS) (which includes an
    entry for "this" in the case of C++ methods), the number of
    arguments NARGS, the NAME of a function whether it's a method or
    not (METHOD), and the degree of laxness (LAX) in conforming to
@@ -2534,13 +2534,14 @@ value_find_oload_method_list (struct value **argp, const char *method,
    resolution is permitted.  */
 
 int
-find_overload_match (struct type **arg_types, int nargs, 
+find_overload_match (struct value **args, int nargs,
 		     const char *name, enum oload_search_type method,
 		     int lax, struct value **objp, struct symbol *fsym,
 		     struct value **valp, struct symbol **symp, 
 		     int *staticp, const int no_adl)
 {
   struct value *obj = (objp ? *objp : NULL);
+  struct type *obj_type = obj ? value_type (obj) : NULL;
   /* Index of best overloaded function.  */
   int func_oload_champ = -1;
   int method_oload_champ = -1;
@@ -2609,7 +2610,7 @@ find_overload_match (struct type **arg_types, int nargs,
       if (fns_ptr)
 	{
 	  gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
-	  method_oload_champ = find_oload_champ (arg_types, nargs, method,
+	  method_oload_champ = find_oload_champ (args, nargs, method,
 	                                         num_fns, fns_ptr,
 	                                         oload_syms, &method_badness);
 
@@ -2631,7 +2632,8 @@ find_overload_match (struct type **arg_types, int nargs,
          and non member function, the first argument must now be
          dereferenced.  */
       if (method == BOTH)
-	arg_types[0] = TYPE_TARGET_TYPE (arg_types[0]);
+	deprecated_set_value_type (args[0],
+				   TYPE_TARGET_TYPE (value_type (args[0])));
 
       if (fsym)
         {
@@ -2677,7 +2679,7 @@ find_overload_match (struct type **arg_types, int nargs,
           return 0;
         }
 
-      func_oload_champ = find_oload_champ_namespace (arg_types, nargs,
+      func_oload_champ = find_oload_champ_namespace (args, nargs,
                                                      func_name,
                                                      qualified_name,
                                                      &oload_syms,
@@ -2781,11 +2783,11 @@ find_overload_match (struct type **arg_types, int nargs,
   if (objp)
     {
       struct type *temp_type = check_typedef (value_type (temp));
-      struct type *obj_type = check_typedef (value_type (*objp));
+      struct type *objtype = check_typedef (obj_type);
 
       if (TYPE_CODE (temp_type) != TYPE_CODE_PTR
-	  && (TYPE_CODE (obj_type) == TYPE_CODE_PTR
-	      || TYPE_CODE (obj_type) == TYPE_CODE_REF))
+	  && (TYPE_CODE (objtype) == TYPE_CODE_PTR
+	      || TYPE_CODE (objtype) == TYPE_CODE_REF))
 	{
 	  temp = value_addr (temp);
 	}
@@ -2814,7 +2816,7 @@ find_overload_match (struct type **arg_types, int nargs,
    performned.  */
 
 static int
-find_oload_champ_namespace (struct type **arg_types, int nargs,
+find_oload_champ_namespace (struct value **args, int nargs,
 			    const char *func_name,
 			    const char *qualified_name,
 			    struct symbol ***oload_syms,
@@ -2823,7 +2825,7 @@ find_oload_champ_namespace (struct type **arg_types, int nargs,
 {
   int oload_champ;
 
-  find_oload_champ_namespace_loop (arg_types, nargs,
+  find_oload_champ_namespace_loop (args, nargs,
 				   func_name,
 				   qualified_name, 0,
 				   oload_syms, oload_champ_bv,
@@ -2843,7 +2845,7 @@ find_oload_champ_namespace (struct type **arg_types, int nargs,
    *OLOAD_CHAMP_BV.  */
 
 static int
-find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
+find_oload_champ_namespace_loop (struct value **args, int nargs,
 				 const char *func_name,
 				 const char *qualified_name,
 				 int namespace_len,
@@ -2880,7 +2882,7 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
     {
       searched_deeper = 1;
 
-      if (find_oload_champ_namespace_loop (arg_types, nargs,
+      if (find_oload_champ_namespace_loop (args, nargs,
 					   func_name, qualified_name,
 					   next_namespace_len,
 					   oload_syms, oload_champ_bv,
@@ -2909,12 +2911,22 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
   /* If we have reached the deepest level perform argument
      determined lookup.  */
   if (!searched_deeper && !no_adl)
-    make_symbol_overload_list_adl (arg_types, nargs, func_name);
+    {
+      int ix;
+      struct type **arg_types;
+
+      /* Prepare list of argument types for overload resolution.  */
+      arg_types = (struct type **)
+	alloca (nargs * (sizeof (struct type *)));
+      for (ix = 0; ix < nargs; ix++)
+	arg_types[ix] = value_type (args[ix]);
+      make_symbol_overload_list_adl (arg_types, nargs, func_name);
+    }
 
   while (new_oload_syms[num_fns])
     ++num_fns;
 
-  new_oload_champ = find_oload_champ (arg_types, nargs, 0, num_fns,
+  new_oload_champ = find_oload_champ (args, nargs, 0, num_fns,
 				      NULL, new_oload_syms,
 				      &new_oload_champ_bv);
 
@@ -2951,7 +2963,7 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
     }
 }
 
-/* Look for a function to take NARGS args of types ARG_TYPES.  Find
+/* Look for a function to take NARGS args of ARGS.  Find
    the best match from among the overloaded methods or functions
    (depending on METHOD) given by FNS_PTR or OLOAD_SYMS, respectively.
    The number of methods/functions in the list is given by NUM_FNS.
@@ -2961,7 +2973,7 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
    It is the caller's responsibility to free *OLOAD_CHAMP_BV.  */
 
 static int
-find_oload_champ (struct type **arg_types, int nargs, int method,
+find_oload_champ (struct value **args, int nargs, int method,
 		  int num_fns, struct fn_field *fns_ptr,
 		  struct symbol **oload_syms,
 		  struct badness_vector **oload_champ_bv)
@@ -3007,7 +3019,7 @@ find_oload_champ (struct type **arg_types, int nargs, int method,
       /* Compare parameter types to supplied argument types.  Skip
          THIS for static methods.  */
       bv = rank_function (parm_types, nparms, 
-			  arg_types + static_offset,
+			  args + static_offset,
 			  nargs - static_offset);
 
       if (!*oload_champ_bv)
@@ -3081,6 +3093,7 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
 		      int static_offset)
 {
   int ix;
+  enum oload_classification worst = STANDARD;
 
   for (ix = 1; ix <= nargs - static_offset; ix++)
     {
@@ -3093,11 +3106,13 @@ classify_oload_match (struct badness_vector *oload_champ_bv,
          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
+	worst = NON_STANDARD;	/* Non-standard type conversions
 				   needed.  */
     }
 
-  return STANDARD;		/* Only standard conversions needed.  */
+  /* If no INCOMPATIBLE classification was found, return the worst one
+     that was found (if any).  */
+  return worst;
 }
 
 /* C++: return 1 is NAME is a legitimate name for the destructor of
@@ -3231,7 +3246,7 @@ compare_parameters (struct type *t1, struct type *t2, int skip_artificial)
       for (i = 0; i < TYPE_NFIELDS (t2); ++i)
 	{
 	  if (compare_ranks (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
-	                                   TYPE_FIELD_TYPE (t2, i)),
+					    TYPE_FIELD_TYPE (t2, i), NULL),
 	                     EXACT_MATCH_BADNESS) != 0)
 	    return 0;
 	}
diff --git a/gdb/value.h b/gdb/value.h
index dc2ac13..1376f95 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -599,7 +599,7 @@ extern struct fn_field *value_find_oload_method_list (struct value **,
 
 enum oload_search_type { NON_METHOD, METHOD, BOTH };
 
-extern int find_overload_match (struct type **arg_types, int nargs,
+extern int find_overload_match (struct value **args, int nargs,
 				const char *name,
 				enum oload_search_type method, int lax,
 				struct value **objp, struct symbol *fsym,
diff --git a/gdb/testsuite/gdb.cp/converts.cc b/gdb/testsuite/gdb.cp/converts.cc
index 34b6927..26a45f5 100644
--- a/gdb/testsuite/gdb.cp/converts.cc
+++ b/gdb/testsuite/gdb.cp/converts.cc
@@ -23,6 +23,10 @@ int foo2_2 (char[][1]) {return 22;}
 int foo2_3 (char *[])  {return 23;}
 int foo2_4 (int  *[])  {return 24;}
 
+int foo3_1 (int a, const char **b) { return 31; }
+int foo3_2 (int a, int b) { return 32; }
+int foo3_2 (int a, const char **b) { return 320; }
+
 int main()
 {
 
@@ -53,5 +57,10 @@ int main()
   foo2_2 (ba);       // ..array of arrays
   foo2_3 (b);        // ..array of pointers
   foo2_4 ((int**)b); // ..array of wrong pointers
+
+  foo3_1 (0, 0);
+  foo3_2 (0, static_cast<char const**> (0));
+  foo3_2 (0, 0);
+
   return 0;          // end of main
 }
diff --git a/gdb/testsuite/gdb.cp/converts.exp b/gdb/testsuite/gdb.cp/converts.exp
index 3f3b3c8..b6a2ad3 100644
--- a/gdb/testsuite/gdb.cp/converts.exp
+++ b/gdb/testsuite/gdb.cp/converts.exp
@@ -49,3 +49,30 @@ 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"
+
+gdb_test "p foo3_1 ((char *) 0, ta)" "Cannot resolve.*" \
+    "check all parameters for badness"
+
+# Tests for null pointer conversion
+global gdb_prompt
+set nl {[\r\n]+}
+set t "null pointer conversion"
+gdb_test_multiple "p foo3_1 (0, 0)" $t {
+  -re "warning: Using non-standard conversion.*$nl$gdb_prompt $" {
+    fail "$t (warning issued)"
+  }
+
+  -re "Cannot resolve function foo3_1 to any overloaded instance$nl$gdb_prompt $" {
+    fail "$t (conversion failed)"
+  }
+
+  -re "\\$\[0-9\]+ = 31$nl$gdb_prompt $" {
+    pass $t
+  }
+}
+gdb_test "p foo3_1 (0, 1)" \
+    "Cannot resolve function foo3_1 to any overloaded instance"
+gdb_test "p foo3_1 (0, (const char**) 1)" " = 31"
+gdb_test "p foo3_2 (0, 0)" "= 32"
+gdb_test "p foo3_2 (0, (char const**) 0)" " = 320"
+

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-13 16:07       ` Keith Seitz
@ 2011-10-14 19:35         ` Tom Tromey
  2011-10-14 20:26           ` Keith Seitz
  0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2011-10-14 19:35 UTC (permalink / raw)
  To: Keith Seitz; +Cc: gdb-patches@sourceware.org ml

>>>>> "Keith" == Keith Seitz <keiths@redhat.com> writes:

Keith> Here is a new version which does this and adds several new tests. A
Keith> lot of the patch is massaging the rank_one_type/rank_function API to
Keith> accept an array of struct values (vs struct types).

Keith> Is this more what you had in mind?

Yes, thanks.

2 tiny nits.

Keith> +/* Baddness of converting integer 0 to NULL pointer.  */

Typo, "badness".

Keith> +extern struct rank rank_one_type (struct type *, struct type *, struct value *);

This line is too long.

Ok with these fixed.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFA] c++/13225
  2011-10-14 19:35         ` Tom Tromey
@ 2011-10-14 20:26           ` Keith Seitz
  0 siblings, 0 replies; 7+ messages in thread
From: Keith Seitz @ 2011-10-14 20:26 UTC (permalink / raw)
  To: gdb-patches@sourceware.org ml

On 10/14/2011 12:35 PM, Tom Tromey wrote:
>>>>>> "Keith" == Keith Seitz<keiths@redhat.com>  writes:
> 2 tiny nits.

Both fixed and patch committed. [(joking) Nit of your nit: That long 
line actually ends on column 79. But that's close enough, so I wrapped 
it anyway. :-)]

Thank you for reviewing this.

Keith


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-10-14 20:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-11 19:16 [RFA] c++/13225 Keith Seitz
2011-10-11 19:36 ` Tom Tromey
2011-10-11 19:44   ` Keith Seitz
2011-10-12 13:40     ` Tom Tromey
2011-10-13 16:07       ` Keith Seitz
2011-10-14 19:35         ` Tom Tromey
2011-10-14 20:26           ` Keith Seitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox