Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: sami wagiaalla <swagiaal@redhat.com>
To: tromey@redhat.com
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH 1/2] Test and support all cpp operator types
Date: Tue, 18 May 2010 20:49:00 -0000	[thread overview]
Message-ID: <4BF2F4F6.8080303@redhat.com> (raw)
In-Reply-To: <m3ljbozrqb.fsf@fleche.redhat.com>

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


> Sami>  @@ -800,21 +800,27 @@ make_symbol_overload_list_using (const char *func_name,
> Sami>   				const char *namespace)
> [...]
> Sami>  -  for (current = block_using (get_selected_block (0));
> Sami>  -       current != NULL;
> Sami>  -       current = current->next)
> Sami>  -    {
> Sami>  -      if (strcmp (namespace, current->import_dest) == 0)
> Sami>  -	{
> Sami>  -	  make_symbol_overload_list_using (func_name,
> Sami>  -					   current->import_src);
> Sami>  -	}
> Sami>  -    }
> Sami>  +  for (block = get_selected_block (0);
> Sami>  +       block != NULL;
> Sami>  +       block = BLOCK_SUPERBLOCK(block))
> Sami>  +    for (current = block_using (block);
> Sami>  +	current != NULL;
> Sami>  +	current = current->next)
> Sami>  +      {
> [...]
>
> This part seems a little weird to me.
> make_symbol_overload_list_using calls make_symbol_overload_list_namespace,
> which calls make_symbol_overload_list_qualified, which itself
> starts with get_selected_block and iterates over the superblocks.
>
> It seems to me that only one such iteration should be needed.
> I don't have a test case but it seems like this could cause incorrect
> results in some corner case.
>

It is weird but it is due to the nature of the symbol tables. The first 
iteration, by make_symbol_overload_list_using, is iteration over the 
blocks' import statements. The Second iteration is actually searching 
for the symbol.

If we assume that names belonging to namespaces can only be in the 
static scope -since namespace symbols are flattened to the nearest 
parent- then we can separate the qualified and unqualified searches
and eliminate the nesting of the iterations.

Please see patch 2/2.

> Sami>  +# some unary operators for good measure
> Sami>  +# Cannot resolve function operator++ to any overloaded instance
> Sami>  +gdb_test "p ++q" "= 30"
>
> It would be interesting to know if "q++" would call an overloaded
> postfix operator++.  These have a hack in the C++ spec to differentiate
> them from prefix ++.
>

It does work. This is tested in userdef.exp.

> I'm also curious to know if "ADL avoidance" works properly when a
> qualified reference to "operator<whatever>" is used.  I didn't see a
> test for that in this patch.  (If there is already one in the test
> suite, then of course we don't need a new one...)
>

Yes it does. I have added a test case.

[-- Attachment #2: operators.patch --]
[-- Type: text/plain, Size: 24525 bytes --]

commit 493c3d32944b9b355158a46b300050ff2fdbfb59
Author: Sami Wagiaalla <swagiaal@redhat.com>
Date:   Tue May 11 15:39:00 2010 -0400

    test and support all cpp operator types
    
    2010-05-18  Sami Wagiaalla  <swagiaal@redhat.com>
    
    	* value.h: Created oload_search_type enum.
    	(find_overload_match): Use oload_search_type enum.
    	* valops.c (find_overload_match): Support combined member and
    	non-member search.
    	* eval.c (evaluate_subexp_standard): Calls to
    	find_overload_match now use oload_search_type enum.
    	(oload_method_static): Verify index is a proper value.
    	* valarith.c (value_user_defined_cpp_op): Search for and handle
    	both member and non-member operators.
    	(value_user_defined_cpp_op): New function.
    	(value_user_defined_op): New function.
    	(value_x_unop): Use value_user_defined_op.
    	(value_x_binop): Ditto.
    	* cp-support.c (make_symbol_overload_list_using): Added block
    	iteration.
    	Add check for namespace aliases and imported declarations.
    
    2010-05-18  Sami Wagiaalla  <swagiaal@redhat.com>
    
    	* gdb.cp/koenig.exp: Test for ADL operators.
    	* gdb.cp/koenig.cc: Added ADL operators.
    	* gdb.cp/operator.exp: New test.
    	* gdb.cp/operator.cc: New test.

diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 8f447ca..0a0f777 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -800,21 +800,26 @@ make_symbol_overload_list_using (const char *func_name,
 				 const char *namespace)
 {
   const struct using_direct *current;
+  const struct block *block;
 
   /* First, go through the using directives.  If any of them apply,
      look in the appropriate namespaces for new functions to match
      on.  */
 
-  for (current = block_using (get_selected_block (0));
-       current != NULL;
-       current = current->next)
-    {
-      if (strcmp (namespace, current->import_dest) == 0)
-	{
-	  make_symbol_overload_list_using (func_name,
-					   current->import_src);
-	}
-    }
+  for (block = get_selected_block (0);
+       block != NULL;
+       block = BLOCK_SUPERBLOCK (block))
+    for (current = block_using (block);
+	current != NULL;
+	current = current->next)
+      {
+        /* If this is a namespace alias or imported declaration ignore it.  */
+        if (current->alias != NULL || current->declaration != NULL)
+          continue;
+
+        if (strcmp (namespace, current->import_dest) == 0)
+          make_symbol_overload_list_using (func_name, current->import_src);
+      }
 
   /* Now, add names for this namespace.  */
   make_symbol_overload_list_namespace (func_name, namespace);
diff --git a/gdb/eval.c b/gdb/eval.c
index 985e653..4beb1bd 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1512,7 +1512,7 @@ evaluate_subexp_standard (struct type *expect_type,
             arg_types[ix - 1] = value_type (argvec[ix]);
 
           find_overload_match (arg_types, nargs, func_name,
-                               0 /* not method */ , 0 /* strict match */ ,
+                               NON_METHOD /* not method */ , 0 /* strict match */ ,
                                NULL, NULL /* pass NULL symbol since symbol is unknown */ ,
                                NULL, &symp, NULL, 0);
 
@@ -1549,7 +1549,7 @@ evaluate_subexp_standard (struct type *expect_type,
 		arg_types[ix - 1] = value_type (argvec[ix]);
 
 	      (void) find_overload_match (arg_types, nargs, tstr,
-				     1 /* method */ , 0 /* strict match */ ,
+	                                  METHOD /* method */ , 0 /* strict match */ ,
 					  &arg2 /* the object */ , NULL,
 					  &valp, NULL, &static_memfuncp, 0);
 
@@ -1618,8 +1618,8 @@ evaluate_subexp_standard (struct type *expect_type,
 		arg_types[ix - 1] = value_type (argvec[ix]);
 
 	      (void) find_overload_match (arg_types, nargs, NULL /* no need for name */ ,
-				 0 /* not method */ , 0 /* strict match */ ,
-		      NULL, function /* the function */ ,
+	                                  NON_METHOD /* not method */ , 0 /* strict match */ ,
+	                                  NULL, function /* the function */ ,
 					  NULL, &symp, NULL, no_adl);
 
 	      if (op == OP_VAR_VALUE)
diff --git a/gdb/testsuite/gdb.cp/koenig.cc b/gdb/testsuite/gdb.cp/koenig.cc
index 6cfa3f5..24b3ae7 100644
--- a/gdb/testsuite/gdb.cp/koenig.cc
+++ b/gdb/testsuite/gdb.cp/koenig.cc
@@ -175,6 +175,49 @@ typedef O::A TOA;
 typedef TOA  TTOA;
 
 //------------
+
+namespace P {
+  class Q{
+  public:
+    int operator== (int)
+      {
+        return 24;
+      }
+
+    int operator== (float)
+      {
+        return 25;
+      }
+
+    int operator+ (float)
+      {
+        return 26;
+      }
+
+  };
+
+  int operator!= (Q, int)
+    {
+      return 27;
+    }
+
+  int operator!= (Q, double)
+    {
+      return 28;
+    }
+
+  int operator+ (Q, int)
+    {
+      return 29;
+    }
+
+  int operator++ (Q)
+    {
+      return 30;
+    }
+}
+
+//------------
 int
 main ()
 {
@@ -238,6 +281,16 @@ main ()
   TTOA ttoa;
   foo (ttoa, 'a');
 
+  P::Q q;
+  q == 5;
+  q == 5.0f;
+  q != 5;
+  q != 5.0f;
+  q + 5;
+  q + 5.0f;
+
+  ++q;
+
   return first (0, c) + foo (eo) +
          foo (eo, eo) + foo (eo, eo, 1)  +
          foo (fo, eo) + foo (1  ,fo, eo) +
diff --git a/gdb/testsuite/gdb.cp/koenig.exp b/gdb/testsuite/gdb.cp/koenig.exp
index b13ffbc..12b4ddf 100644
--- a/gdb/testsuite/gdb.cp/koenig.exp
+++ b/gdb/testsuite/gdb.cp/koenig.exp
@@ -13,28 +13,12 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-if $tracelevel then {
-    strace $tracelevel
-}
-
-set prms_id 0
-set bug_id 0
-
 set testfile koenig
 set srcfile ${testfile}.cc
-set binfile ${objdir}/${subdir}/${testfile}
-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
-    untested "Couldn't compile test program"
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } {
     return -1
 }
 
-# Get things started.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
 ############################################
 
 if ![runto_main] then {
@@ -107,3 +91,22 @@ gdb_test "p M::N::bar('a')" "= 22"
 
 #test that lookup supports typedef
 gdb_test "p foo(ttoa, 'a')" "= 23"
+
+# test lookup of namespace user-defined operators
+# and overload resolution:
+
+# within class
+gdb_test "p q == 5" "= 24"
+gdb_test "p q == 5.0f" "= 25"
+
+# within namespace
+gdb_test "p q != 5" "= 27"
+gdb_test "p q != 5.0f" "= 28"
+
+# across namespace and class
+gdb_test "p q + 5.0f" "= 26"
+gdb_test "p q + 5" "= 29"
+
+# some unary operators for good measure
+# Cannot resolve function operator++ to any overloaded instance
+gdb_test "p ++q" "= 30"
diff --git a/gdb/testsuite/gdb.cp/operator.cc b/gdb/testsuite/gdb.cp/operator.cc
new file mode 100644
index 0000000..cc925a0
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/operator.cc
@@ -0,0 +1,195 @@
+class A
+{
+};
+
+int operator== (A, int)
+{
+  return 11;
+}
+
+int operator== (A, char)
+{
+  return 12;
+}
+
+//------------------
+
+namespace B
+{
+  class C
+  {
+  };
+
+  int operator== (C, int)
+  {
+    return 22;
+  }
+
+  int operator== (C, char)
+  {
+    return 23;
+  }
+
+  namespace BD
+  {
+    int operator== (C, int)
+    {
+      return 24;
+    }
+  }
+}
+
+//------------------
+
+class D
+{
+};
+namespace
+{
+  int operator== (D, int)
+  {
+    return 33;
+  }
+
+  int operator== (D, char)
+  {
+    return 34;
+  }
+}
+
+int operator== (D, float)
+{
+  return 35;
+}
+
+//------------------
+
+class E
+{
+};
+namespace F
+{
+  int operator== (E, int)
+  {
+    return 44;
+  }
+
+  int operator== (E, char)
+  {
+    return 45;
+  }
+}
+
+int operator== (E, float)
+{
+  return 46;
+}
+
+using namespace F;
+
+//-----------------
+
+class G
+{
+public:
+  int operator== (int)
+  {
+    return 55;
+  }
+};
+
+int operator== (G, char)
+{
+  return 56;
+}
+
+//------------------
+
+class H
+{
+};
+namespace I
+{
+  int operator== (H, int)
+  {
+    return 66;
+  }
+}
+
+namespace ALIAS = I;
+
+//------------------
+
+class J
+{
+};
+
+namespace K
+{
+  int i;
+  int operator== (J, int)
+  {
+    return 77;
+  }
+}
+
+using K::i;
+
+//------------------
+
+class L
+{
+};
+namespace M
+{
+  int operator== (L, int)
+  {
+    return 88;
+  }
+}
+
+namespace N
+{
+  using namespace M;
+}
+
+using namespace N;
+
+//------------------
+
+int main ()
+{
+  A a;
+  a == 1;
+  a == 'a';
+
+  B::C bc;
+  bc == 1;
+  bc == 'a';
+  B::BD::operator== (bc,'a');
+
+  D d;
+  d == 1;
+  d == 'a';
+  d == 1.0f;
+
+  E e;
+  e == 1;
+  e == 'a';
+  e == 1.0f;
+
+  G g;
+  g == 1;
+  g == 'a';
+
+  H h;
+  I::operator== (h, 1);
+
+  J j;
+  K::operator== (j, 1);
+
+  L l;
+  l == 1;
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.cp/operator.exp b/gdb/testsuite/gdb.cp/operator.exp
new file mode 100644
index 0000000..ac89d2b
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/operator.exp
@@ -0,0 +1,58 @@
+# 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 operator
+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
+}
+
+# Test global operator
+gdb_test "p a == 1" "= 11" "global operator"
+gdb_test "p a == 'a'" "= 12" "global operator overload"
+
+# Test ADL operator
+gdb_test "p bc == 1" "= 22" "ADL operator"
+gdb_test "p bc == 'a'" "= 23" "ADL operator overload"
+gdb_test "p B::BD::operator== (bc,'a')" "= 24" "Fully qualified explicit operator call"
+
+# Test operator imported from anonymous namespace
+gdb_test "p d == 1" "= 33" "anonymous namespace operator"
+gdb_test "p d == 'a'" "= 34" "anonymous namespace operator overload"
+gdb_test "p d == 1.0f" "= 35" "anonymous namespace operator overload float"
+
+# Test operator imported by using directive
+gdb_test "p e == 1" "= 44" "imported operator"
+gdb_test "p e == 'a'" "= 45" "imported operator overload"
+gdb_test "p e == 1.0f" "= 46" "imported operator overload float"
+
+# Test member operator
+gdb_test "p g == 1" "= 55" "member operator"
+gdb_test "p g == 'a'" "= 56" "member operator overload"
+
+# Test that operators are not wrongly imported
+# by import declarations and namespace aliases
+gdb_test "p h == 1" "Cannot resolve function operator== to any overloaded instance" "namespace alias"
+gdb_test "p j == 1" "Cannot resolve function operator== to any overloaded instance" "imported declaration"
+
+# Test that indirectly imported operators work
+gdb_test "p l == 1" "= 88"
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 4efe936..fe6cae6 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -31,6 +31,7 @@
 #include "dfp.h"
 #include <math.h>
 #include "infcall.h"
+#include "exceptions.h"
 
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C). */
@@ -318,6 +319,67 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
     }
 }
 
+/* Try to find an operator named OPERATOR which takes NARGS arguments
+   specified in ARGS.  If the operator found is a static member operator
+   *STATIC_MEMFUNP will be set to 1, and otherwise 0.
+   The search if performed through find_overload_match which will handle
+   member operators, non member operators, operators imported implicitly or
+   explicitly, and perform correct overload resolution in all of the above
+   situations or combinations thereof.  */
+
+static struct value *
+value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
+                           int *static_memfuncp)
+{
+
+  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 */,
+                       0 /* strict match */, &args[0], /* objp */
+                       NULL /* pass NULL symbol since symbol is unknown */,
+                       &valp, &symp, static_memfuncp, 0);
+
+  if (valp)
+    return valp;
+
+  if (symp)
+    {
+      /* This is a non member function and does not
+         expect a reference as its first argument
+         rather the explicit structure.  */
+      args[0] = value_ind (args[0]);
+      return value_of_variable (symp, 0);
+    }
+
+  error (_("Could not find %s."), operator);
+}
+
+/* Lookup user defined operator NAME.  Return a value representing the
+   function, otherwise return NULL.  */
+
+static struct value *
+value_user_defined_op (struct value **argp, struct value **args, char *name,
+                       int *static_memfuncp, int nargs)
+{
+  struct value *result = NULL;
+
+  if (current_language->la_language == language_cplus)
+    result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp);
+  else
+    result = value_struct_elt (argp, args, name, static_memfuncp,
+                               "structure");
+
+  return result;
+}
+
 /* We know either arg1 or arg2 is a structure, so try to find the right
    user defined function.  Create an argument vector that calls 
    arg1.operator @ (arg1,arg2) and return that value (where '@' is any
@@ -458,7 +520,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
       error (_("Invalid binary operation specified."));
     }
 
-  argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+                                     &static_memfuncp, 2);
 
   if (argvec[0])
     {
@@ -555,7 +618,8 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
       error (_("Invalid unary operation specified."));
     }
 
-  argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+                                     &static_memfuncp, nargs);
 
   if (argvec[0])
     {
diff --git a/gdb/valops.c b/gdb/valops.c
index 6f5f684..6648bdb 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2293,6 +2293,16 @@ value_find_oload_method_list (struct value **argp, const char *method,
    matches on the argument types according to the overload resolution
    rules.
 
+   METHOD can be one of three values:
+     NON_METHOD for non-member functions.
+     METHOD: for member functions.
+     BOTH: used for overload resolution of operators where the
+       candidates are expected to be either member or non member
+       functions. In this case the first argument ARGTYPES
+       (representing 'this') is expected to be a reference to the
+       target object, and will be dereferenced when attempting the
+       non-member search.
+
    In the case of class methods, the parameter OBJ is an object value
    in which to search for overloaded methods.
 
@@ -2320,16 +2330,20 @@ value_find_oload_method_list (struct value **argp, const char *method,
 
 int
 find_overload_match (struct type **arg_types, int nargs, 
-		     const char *name, int method, int lax, 
-		     struct value **objp, struct symbol *fsym,
+		     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);
   /* Index of best overloaded function.  */
-  int oload_champ;
+  int func_oload_champ = -1;
+  int method_oload_champ = -1;
+
   /* The measure for the current best match.  */
-  struct badness_vector *oload_champ_bv = NULL;
+  struct badness_vector *method_badness = NULL;
+  struct badness_vector *func_badness = NULL;
+
   struct value *temp = obj;
   /* For methods, the list of overloaded methods.  */
   struct fn_field *fns_ptr = NULL;
@@ -2345,9 +2359,11 @@ find_overload_match (struct type **arg_types, int nargs,
   const char *obj_type_name = NULL;
   const char *func_name = NULL;
   enum oload_classification match_quality;
+  enum oload_classification method_match_quality = INCOMPATIBLE;
+  enum oload_classification func_match_quality = INCOMPATIBLE;
 
   /* Get the list of overloaded methods or functions.  */
-  if (method)
+  if (method == METHOD || method == BOTH)
     {
       gdb_assert (obj);
 
@@ -2370,10 +2386,13 @@ find_overload_match (struct type **arg_types, int nargs,
 	    }
 	}
 
+      /* Retrieve the list of methods with the name NAME.  */
       fns_ptr = value_find_oload_method_list (&temp, name, 
 					      0, &num_fns, 
 					      &basetype, &boffset);
-      if (!fns_ptr || !num_fns)
+      /* If this is a method only search, and no methods were found
+         the search has faild.  */
+      if (method == METHOD && (!fns_ptr || !num_fns))
 	error (_("Couldn't find method %s%s%s"),
 	       obj_type_name,
 	       (obj_type_name && *obj_type_name) ? "::" : "",
@@ -2381,15 +2400,33 @@ find_overload_match (struct type **arg_types, int nargs,
       /* If we are dealing with stub method types, they should have
 	 been resolved by find_method_list via
 	 value_find_oload_method_list above.  */
-      gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
-      oload_champ = find_oload_champ (arg_types, nargs, method, 
-				      num_fns, fns_ptr, 
-				      oload_syms, &oload_champ_bv);
+      if (fns_ptr)
+	{
+	  gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
+	  method_oload_champ = find_oload_champ (arg_types, nargs, method,
+	                                         num_fns, fns_ptr,
+	                                         oload_syms, &method_badness);
+
+	  method_match_quality =
+	      classify_oload_match (method_badness, nargs,
+	                            oload_method_static (method, fns_ptr,
+	                                                 method_oload_champ));
+
+	  make_cleanup (xfree, method_badness);
+	}
+
     }
-  else
+
+  if (method == NON_METHOD || method == BOTH)
     {
       const char *qualified_name = NULL;
 
+      /* If the the overload match is being search for both
+         as a method and non member function, the first argument
+         must now be dereferenced.  */
+      if (method == BOTH)
+	arg_types[0] = TYPE_TARGET_TYPE (arg_types[0]);
+
       if (fsym)
         {
           qualified_name = SYMBOL_NATURAL_NAME (fsym);
@@ -2432,30 +2469,67 @@ find_overload_match (struct type **arg_types, int nargs,
           return 0;
         }
 
-      make_cleanup (xfree, oload_syms);
-      make_cleanup (xfree, oload_champ_bv);
+      func_oload_champ = find_oload_champ_namespace (arg_types, nargs,
+                                                     func_name,
+                                                     qualified_name,
+                                                     &oload_syms,
+                                                     &func_badness,
+                                                     no_adl);
 
-      oload_champ = find_oload_champ_namespace (arg_types, nargs,
-						func_name,
-						qualified_name,
-						&oload_syms,
-						&oload_champ_bv,
-						no_adl);
+      if (func_oload_champ >= 0)
+	func_match_quality = classify_oload_match (func_badness, nargs, 0);
+
+      make_cleanup (xfree, oload_syms);
+      make_cleanup (xfree, func_badness);
     }
 
   /* Did we find a match ?  */
-  if (oload_champ == -1)
+  if (method_oload_champ == -1 && func_oload_champ == -1)
     error (_("No symbol \"%s\" in current context."), name);
 
-  /* Check how bad the best match is.  */
-  match_quality =
-    classify_oload_match (oload_champ_bv, nargs,
-			  oload_method_static (method, fns_ptr,
-					       oload_champ));
+  /* If we have found both a method match and a function
+     match, find out which one is better, and calculate match
+     quality.  */
+  if (method_oload_champ >= 0 && func_oload_champ >= 0)
+    {
+      switch (compare_badness (func_badness, method_badness))
+        {
+	  case 0: /* Top two contenders are equally good.  */
+	    /* FIXME: GDB does not support the general ambiguous
+	     case.  All candidates should be collected and presented
+	     the the user.  */
+	    error (_("Ambiguous overload resolution"));
+	    break;
+	  case 1: /* Incomparable top contenders.  */
+	    /* This is an error incompatible candidates
+	       should not have been proposed.  */
+	    error (_("Internal error: incompatible overload candidates proposed"));
+	    break;
+	  case 2: /* Function champion.  */
+	    method_oload_champ = -1;
+	    match_quality = func_match_quality;
+	    break;
+	  case 3: /* Method champion.  */
+	    func_oload_champ = -1;
+	    match_quality = method_match_quality;
+	    break;
+	  default:
+	    error (_("Internal error: unexpected overload comparison result"));
+	    break;
+        }
+    }
+  else
+    {
+      /* We have either a method match or a function match.  */
+      if (method_oload_champ >= 0)
+	match_quality = method_match_quality;
+      else
+	match_quality = func_match_quality;
+    }
 
   if (match_quality == INCOMPATIBLE)
     {
-      if (method)
+      if (method == METHOD)
 	error (_("Cannot resolve method %s%s%s to any overloaded instance"),
 	       obj_type_name,
 	       (obj_type_name && *obj_type_name) ? "::" : "",
@@ -2466,7 +2540,7 @@ find_overload_match (struct type **arg_types, int nargs,
     }
   else if (match_quality == NON_STANDARD)
     {
-      if (method)
+      if (method == METHOD)
 	warning (_("Using non-standard conversion to match method %s%s%s to supplied arguments"),
 		 obj_type_name,
 		 (obj_type_name && *obj_type_name) ? "::" : "",
@@ -2476,21 +2550,20 @@ find_overload_match (struct type **arg_types, int nargs,
 		 func_name);
     }
 
-  if (method)
+  if (staticp != NULL)
+    *staticp = oload_method_static (method, fns_ptr, method_oload_champ);
+
+  if (method_oload_champ >= 0)
     {
-      if (staticp != NULL)
-	*staticp = oload_method_static (method, fns_ptr, oload_champ);
-      if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
-	*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, 
+      if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
+	*valp = value_virtual_fn_field (&temp, fns_ptr, method_oload_champ,
 					basetype, boffset);
       else
-	*valp = value_fn_field (&temp, fns_ptr, oload_champ, 
+	*valp = value_fn_field (&temp, fns_ptr, method_oload_champ,
 				basetype, boffset);
     }
   else
-    {
-      *symp = oload_syms[oload_champ];
-    }
+    *symp = oload_syms[func_oload_champ];
 
   if (objp)
     {
@@ -2778,7 +2851,8 @@ find_oload_champ (struct type **arg_types, int nargs, int method,
 static int
 oload_method_static (int method, struct fn_field *fns_ptr, int index)
 {
-  if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, index))
+  if (method && fns_ptr && index >= 0
+      && TYPE_FN_FIELD_STATIC_P (fns_ptr, index))
     return 1;
   else
     return 0;
diff --git a/gdb/value.h b/gdb/value.h
index 57b4dd7..7f71dc4 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -447,8 +447,11 @@ extern struct fn_field *value_find_oload_method_list (struct value **,
 						      int, int *,
 						      struct type **, int *);
 
+enum oload_search_type { NON_METHOD, METHOD, BOTH };
+
 extern int find_overload_match (struct type **arg_types, int nargs,
-				const char *name, int method, int lax,
+				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);

  reply	other threads:[~2010-05-18 20:23 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-11 20:38 [PATCH] " sami wagiaalla
2010-05-13  0:00 ` Tom Tromey
2010-05-18 20:49   ` sami wagiaalla [this message]
2010-06-04 20:55     ` [PATCH 1/2] " Tom Tromey
2010-05-18 22:31   ` [PATCH 2/2] " sami wagiaalla
2010-06-04 20:59     ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4BF2F4F6.8080303@redhat.com \
    --to=swagiaal@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox