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]

Re: [patch] support argument dependent lookup (ADL)


> 
> Something I don't understand is how this code excludes qualified names,
> or method names, from ADL lookup.
> 

It does not. At first I wanted to solve this problem through the same
mechanism that is used for regular namespace overload resolution, but
regular overload resolution does not have this problem since it can
restrict the search to the scope of the name that has been found already
whether it was found through full qualification or otherwise. ADL cannot
do that since candidates can belong to a namespace outside the current
hierarchy. So I added the no_adl argument.

So if a name is fully qualified and a candidate is found no_adl is used.
If a name is fully qualified and no candidate is found an error is given
by the parser.
If a name is not fully qualified and no candidates are found ADL is
attempted.
And finally if a name is not fully qualified and a candidate if found
ADL proposals are added to the overload set.

for member functions find_oload_champ_namespace is just not called at
all.

I have added tests for all of the above situations.

Sami
commit eb830a135196c2e7829aa9457f0d98a7211022e1
Author: Sami Wagiaalla <swagiaal@redhat.com>
Date:   Mon Mar 22 14:29:42 2010 -0400

    2010-04-09  Sami Wagiaalla  <swagiaal@redhat.com>
    
    	PR C++/7943:
    	* valops.c (find_overload_match): Handle fsym == NULL case.
    	Add int no_adl argument.
    	(find_oload_champ_namespace_loop): Call make_symbol_overload_list_adl
    	when appropriate.
    	Add int no_adl argument.
    	(find_oload_champ_namespace): 	Add int no_adl argument.
    	* parse.c (operator_length_standard): Return length for OP_ADL_FUNC
    	expression.
    	* expprint.c (op_name_standard): Added string for OP_ADL_FUNC case.
    	* eval.c (evaluate_subexp_standard): Added OP_ADL_FUNC case.
    	Evaluate arguments and use them to perform ADL lookup.
    	Pass no_adl argument to find_overload_match.
    	Disable adl lookup when evaluating a fully qualified OP_FUNCALL.
    	* cp-support.h: Added prototype for
    	make_symbol_overload_list_namespace.
    	* cp-support.c (make_symbol_overload_list_namespace): New function.
    	(make_symbol_overload_list_adl_namespace): New function.
    	(make_symbol_overload_list_adl): New function.
    	(make_symbol_overload_list_using): Moved code to add function to
    	overload set to make_symbol_overload_list_namespace.
    	* c-exp.y: create UNKNOWN_CPP_NAME token.
    	Add parse rule for ADL functions.
    	(classify_name): Recognize an UNKNOWN_CPP_NAME.
    
    2010-04-09  Sami Wagiaalla  <swagiaal@redhat.com>
    
    	* gdb.cp/koenig.exp: New test.
    	* gdb.cp/koenig.cc: New test program.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d49b5c0..35d2138 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2010-04-09  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* valops.c (find_overload_match): Add int no_adl argument.
+	(find_oload_champ_namespace): Ditto.
+	(find_oload_champ_namespace_loop): Ditto.
+	Prevent adl lookup if no_adl.
+	* eval.c (evaluate_subexp_standard): Pass no_adl argument to
+	find_overload_match.
+	Disable adl lookup when evaluating a fully qualified OP_FUNCALL.
+
 2010-03-12  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* amd64-tdep.c (amd64_word_names): Replace "sp" with "".
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 1af76c9..0834987 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -186,6 +186,7 @@ static struct stoken operator_stoken (const char *);
 %token <tsval> STRING
 %token <tsval> CHAR
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_CPP_NAME
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name
@@ -391,6 +392,29 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
+exp	:	UNKNOWN_CPP_NAME '('
+			{
+			  /* This could potentially be a an argument defined
+			     lookup function (Koenig).  */
+			  write_exp_elt_opcode (OP_ADL_FUNC);
+			  write_exp_elt_block (expression_context_block);
+			  write_exp_elt_sym (NULL); /* Place holder */
+			  write_exp_string ($1.stoken);
+			  write_exp_elt_opcode (OP_ADL_FUNC);
+
+			/* This is to save the value of arglist_len
+			   being accumulated by an outer function call.  */
+
+			  start_arglist ();
+			}
+		arglist ')'	%prec ARROW
+			{
+			  write_exp_elt_opcode (OP_FUNCALL);
+			  write_exp_elt_longcst ((LONGEST) end_arglist ());
+			  write_exp_elt_opcode (OP_FUNCALL);
+			}
+	;
+
 lcurly	:	'{'
 			{ start_arglist (); }
 	;
@@ -1224,6 +1248,7 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_CPP_NAME  { $$ = $1.stoken; }
 	|	operator { $$ = $1; }
 	;
 
@@ -1236,6 +1261,7 @@ name_not_typename :	NAME
    context where only a name could occur, this might be useful.
   	|	NAME_OR_INT
  */
+	|	UNKNOWN_CPP_NAME
 	;
 
 %%
@@ -2379,6 +2405,12 @@ classify_name (struct block *block)
   /* Any other kind of symbol */
   yylval.ssym.sym = sym;
   yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+
+  if (sym == NULL
+      && parse_language->la_language == language_cplus
+      && !lookup_minimal_symbol (copy, NULL, NULL))
+    return UNKNOWN_CPP_NAME;
+
   return NAME;
 }
 
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index d43d25f..93d9e42 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -52,7 +52,7 @@ static void demangled_name_complaint (const char *name);
 
 /* Functions/variables related to overload resolution.  */
 
-static int sym_return_val_size;
+static int sym_return_val_size = -1;
 static int sym_return_val_index;
 static struct symbol **sym_return_val;
 
@@ -712,6 +712,81 @@ make_symbol_overload_list (const char *func_name,
   return sym_return_val;
 }
 
+/* Adds the function FUNC_NAME from NAMESPACE to the overload set.  */
+
+static void
+make_symbol_overload_list_namespace (const char *func_name,
+                                     const char *namespace)
+{
+
+  if (namespace[0] == '\0')
+    make_symbol_overload_list_qualified (func_name);
+  else
+    {
+      char *concatenated_name
+	= alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+      strcpy (concatenated_name, namespace);
+      strcat (concatenated_name, "::");
+      strcat (concatenated_name, func_name);
+      make_symbol_overload_list_qualified (concatenated_name);
+    }
+}
+
+/* Search the namespace of the given type and namespace of and public base
+ types.  */
+
+static void
+make_symbol_overload_list_adl_namespace (struct type *type,
+                                         const char *func_name)
+{
+  char *namespace;
+  char *type_name;
+  int i, prefix_len;
+
+  while (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF
+         || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    type = TYPE_TARGET_TYPE (type);
+
+  type_name = TYPE_NAME (type);
+
+  prefix_len = cp_entire_prefix_len (type_name);
+
+  if (prefix_len != 0)
+    {
+      namespace = alloca (prefix_len + 1);
+      strncpy (namespace, type_name, prefix_len);
+      namespace[prefix_len] = '\0';
+
+      make_symbol_overload_list_namespace (func_name, namespace);
+    }
+
+  /* Check public base type */
+  if (TYPE_CODE (type) == TYPE_CODE_CLASS)
+    for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+      {
+	if (BASETYPE_VIA_PUBLIC (type, i))
+	  make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i),
+						   func_name);
+      }
+}
+
+/* Adds the the overload list overload candidates for FUNC_NAME found through
+   argument dependent lookup.  */
+
+struct symbol **
+make_symbol_overload_list_adl (struct type **arg_types, int nargs,
+                               const char *func_name)
+{
+  int i;
+
+  gdb_assert (sym_return_val_size != -1);
+
+  for (i = 1; i <= nargs; i++)
+    make_symbol_overload_list_adl_namespace (arg_types[i - 1], func_name);
+
+  return sym_return_val;
+}
+
 /* This applies the using directives to add namespaces to search in,
    and then searches for overloads in all of those namespaces.  It
    adds the symbols found to sym_return_val.  Arguments are as in
@@ -739,20 +814,7 @@ make_symbol_overload_list_using (const char *func_name,
     }
 
   /* Now, add names for this namespace.  */
-  
-  if (namespace[0] == '\0')
-    {
-      make_symbol_overload_list_qualified (func_name);
-    }
-  else
-    {
-      char *concatenated_name
-	= alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
-      strcpy (concatenated_name, namespace);
-      strcat (concatenated_name, "::");
-      strcat (concatenated_name, func_name);
-      make_symbol_overload_list_qualified (concatenated_name);
-    }
+  make_symbol_overload_list_namespace (func_name, namespace);
 }
 
 /* This does the bulk of the work of finding overloaded symbols.
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index e10f5a9..f92ca67 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -79,6 +79,10 @@ extern char *cp_remove_params (const char *demangled_name);
 extern struct symbol **make_symbol_overload_list (const char *,
 						  const char *);
 
+extern struct symbol **make_symbol_overload_list_adl (struct type **arg_types,
+                                                      int nargs,
+                                                      const char *func_name);
+
 extern struct type *cp_lookup_rtti_type (const char *name,
 					 struct block *block);
 
diff --git a/gdb/eval.c b/gdb/eval.c
index 3bcd417..80f1443 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -731,6 +731,7 @@ evaluate_subexp_standard (struct type *expect_type,
       return value_from_decfloat (exp->elts[pc + 1].type,
 				  exp->elts[pc + 2].decfloatconst);
 
+    case OP_ADL_FUNC:
     case OP_VAR_VALUE:
       (*pos) += 3;
       if (noside == EVAL_SKIP)
@@ -1453,6 +1454,17 @@ evaluate_subexp_standard (struct type *expect_type,
 	      tem = 2;
 	    }
 	}
+      else if (op == OP_ADL_FUNC)
+        {
+          /* Save the function position and move pos so that the arguments
+             can be evaluated.  */
+          int func_name_len;
+          save_pos1 = *pos;
+          tem = 1;
+
+          func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst);
+          (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1);
+        }
       else
 	{
 	  /* Non-method function call */
@@ -1483,6 +1495,32 @@ evaluate_subexp_standard (struct type *expect_type,
 
       /* signal end of arglist */
       argvec[tem] = 0;
+      if (op == OP_ADL_FUNC)
+        {
+          struct symbol *symp;
+          char *func_name;
+          int  name_len;
+          int string_pc = save_pos1 + 3;
+
+          /* Extract the function name.  */
+          name_len = longest_to_int (exp->elts[string_pc].longconst);
+          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,
+                               0 /* not method */ , 0 /* strict match */ ,
+                               NULL, NULL /* pass NULL symbol since symbol is unknown */ ,
+                               NULL, &symp, NULL, 0);
+
+          /* 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 == STRUCTOP_STRUCT || op == STRUCTOP_PTR
 	  || (op == OP_SCOPE && function_name != NULL))
@@ -1514,7 +1552,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      (void) find_overload_match (arg_types, nargs, tstr,
 				     1 /* method */ , 0 /* strict match */ ,
 					  &arg2 /* the object */ , NULL,
-					  &valp, NULL, &static_memfuncp);
+					  &valp, NULL, &static_memfuncp, 0);
 
 	      if (op == OP_SCOPE && !static_memfuncp)
 		{
@@ -1566,6 +1604,11 @@ evaluate_subexp_standard (struct type *expect_type,
 	    {
 	      /* Language is C++, do some overload resolution before evaluation */
 	      struct symbol *symp;
+	      int no_adl = 0;
+
+	      /* If a scope has been specified disable ADL.  */
+	      if (op == OP_SCOPE)
+		no_adl = 1;
 
 	      if (op == OP_VAR_VALUE)
 		function = exp->elts[save_pos1+2].symbol;
@@ -1578,7 +1621,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      (void) find_overload_match (arg_types, nargs, NULL /* no need for name */ ,
 				 0 /* not method */ , 0 /* strict match */ ,
 		      NULL, function /* the function */ ,
-					  NULL, &symp, NULL);
+					  NULL, &symp, NULL, no_adl);
 
 	      if (op == OP_VAR_VALUE)
 		{
diff --git a/gdb/expprint.c b/gdb/expprint.c
index e378831..45deffe 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -816,6 +816,8 @@ op_name_standard (enum exp_opcode opcode)
       return "OP_TYPE";
     case OP_LABELED:
       return "OP_LABELED";
+    case OP_ADL_FUNC:
+      return "OP_ADL_FUNC";
     }
 }
 
diff --git a/gdb/expression.h b/gdb/expression.h
index ca216cf..29ebde4 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -347,6 +347,10 @@ enum exp_opcode
        Then comes another OP_DECFLOAT.  */
     OP_DECFLOAT,
 
+    /* OP_ADL_FUNC specifies that the function is to be looked up in an
+       Argument Dependent manner (Koenig lookup).  */
+    OP_ADL_FUNC,
+
      /* First extension operator.  Individual language modules define
 	extra operators in *.inc include files below always starting with
 	numbering at OP_EXTENDED0:
diff --git a/gdb/parse.c b/gdb/parse.c
index aabc461..b607c71 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -889,6 +889,13 @@ operator_length_standard (struct expression *expr, int endpos,
       args = 1;
       break;
 
+    case OP_ADL_FUNC:
+      oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+      oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+      oplen++;
+      oplen++;
+      break;
+
     case OP_LABELED:
     case STRUCTOP_STRUCT:
     case STRUCTOP_PTR:
diff --git a/gdb/testsuite/gdb.cp/koenig.cc b/gdb/testsuite/gdb.cp/koenig.cc
new file mode 100644
index 0000000..d8d4ab3
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/koenig.cc
@@ -0,0 +1,228 @@
+namespace A
+{
+  class C
+  {
+  public:
+    static const int x = 11;
+  };
+
+  int
+  first (C c)
+  {
+    return 11;
+  }
+
+  int
+  first (int a, C c)
+  {
+    return 22;
+  }
+
+  int
+  second (int a, int b, C cc, int c, int d)
+  {
+    return 33;
+  }
+
+}
+
+struct B
+{
+  A::C c;
+};
+
+//------------
+
+namespace E
+{
+  class O{};
+  int foo (O o){return 1; }
+  int foo (O o, O o2){return 2; }
+  int foo (O o, O o2, int i){return 3; }
+}
+
+namespace F
+{
+  class O{};
+  int foo (       O fo, ::E::O eo){ return 4;}
+  int foo (int i, O fo, ::E::O eo){ return 5;}
+}
+
+namespace G
+{
+  class O{};
+  int foo (O go, ::F::O fo, ::E::O eo){ return 6; }
+}
+
+//------------
+
+namespace H
+{
+  class O{};
+  int foo (O){ return 7;}
+}
+
+namespace I
+{
+  class O: public H::O {};
+  class X: H::O{};
+}
+
+//------------
+
+namespace J
+{
+  union U{};
+  struct S{};
+  enum E{};
+
+  class A{
+  public:
+    class B{};
+  };
+
+  class C{};
+
+  int foo (U){ return 8;}
+  int foo (S){ return 9;}
+  int foo (E){ return 10;}
+  int foo (A::B){ return 11;}
+  int foo (A*){ return 12;}
+  int foo (A**){ return 13;}
+  int foo (C[]){ return 14;}
+
+}
+//------------
+
+namespace K{
+  class O{};
+
+  int foo(O, int){
+    return 15;
+  }
+
+  int bar(O, int){
+    return 15;
+  }
+}
+
+int foo(K::O, float){
+  return 16;
+}
+
+int bar(K::O, int){
+  return 16;
+}
+//------------
+
+namespace L {
+  namespace A{
+    namespace B{
+    class O {};
+
+    int foo (O){
+      return 17;
+    }
+
+    }
+  }
+}
+
+//------------
+
+namespace M {
+  class A{
+  public:
+    int foo(char) {
+      return 18;
+    }
+  };
+
+  int foo(A,char){
+      return 19;
+    }
+
+  int foo(A *,char){
+    return 23;
+  }
+
+  int bar(char){
+    return 21;
+  }
+
+  namespace N {
+    int foo(::M::A,int){
+      return 20;
+    }
+
+    int bar(int){
+      return 22;
+    }
+  }
+}
+//------------
+int
+main ()
+{
+  A::C c;
+  B b;
+
+  A::first (c);
+  first (0, c);
+  second (0, 0, c, 0, 0);
+  A::first (b.c);
+
+  E::O eo;
+  F::O fo;
+  G::O go;
+
+  foo (eo);
+  foo (eo, eo);
+  foo (eo, eo, 1);
+  foo (fo, eo);
+  foo (1  ,fo, eo);
+  foo (go, fo, eo);
+
+  I::O io;
+  I::X ix;
+
+  foo (io);
+//foo (ix);
+
+  J::U ju;
+  J::S js;
+  J::E je;
+  J::A::B jab;
+  J::A *jap;
+  J::A **japp;
+  J::C jca[3];
+
+  foo (ju);
+  foo (js);
+  foo (je);
+  foo (jab);
+  foo (jap);
+  foo (japp);
+  foo (jca);
+
+  K::O ko;
+  foo (ko, 1);
+  foo (ko, 1.0f);
+  //bar(ko,1);
+
+  L::A::B::O labo;
+  foo (labo);
+  
+  M::A ma;
+  foo(ma,'a');
+  ma.foo('a');
+  M::N::foo(ma,'a');
+
+  M::bar('a');
+  M::N::bar('a');
+
+  return first (0, c) + foo (eo) +
+         foo (eo, eo) + foo (eo, eo, 1)  +
+         foo (fo, eo) + foo (1  ,fo, eo) +
+         foo (go, fo, eo);
+}
diff --git a/gdb/testsuite/gdb.cp/koenig.exp b/gdb/testsuite/gdb.cp/koenig.exp
new file mode 100644
index 0000000..3424c9f
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/koenig.exp
@@ -0,0 +1,106 @@
+# 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/>.
+
+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"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+# Test that koenig lookup finds correct function
+gdb_test "p first(c)" "= 11"
+
+# Change the number of parameters and position of
+# the qualifying parameter
+gdb_test "p second(0,0,c,0,0)" "= 33"
+
+# Test that koenig lookup finds correct function
+# even if it is overloaded
+gdb_test "p first(0,c)" "= 22"
+
+# Test that koenig lookup finds correct function
+# when the argument is an expression
+gdb_test "p first(b.c)" "= 11"
+
+# test that resolutions can be made across namespaces
+gdb_test "p foo(eo)"         "= 1"
+gdb_test "p foo(eo, eo)"     "= 2"
+gdb_test "p foo(eo, eo, 1)"  "= 3"
+gdb_test "p foo(fo, eo)"     "= 4"
+gdb_test "p foo(1 ,fo, eo)"  "= 5"
+gdb_test "p foo(go, fo, eo)" "= 6"
+
+#test that gdb fails gracefully
+gdb_test "p fake(eo)" "No symbol \"fake\" in current context."
+
+#test that namespaces of base classes are searched
+gdb_test "p foo(io)" "= 7"
+gdb_test "p foo(ix)" "Cannot resolve function foo to any overloaded instance"
+
+#test for other types
+gdb_test "p foo(ju)" "= 8"
+gdb_test "p foo(js)" "= 9"
+gdb_test "p foo(je)" "= 10"
+
+#test for class members
+setup_xfail "*-*-*"
+gdb_test "p foo(jab)" "= 11"
+
+gdb_test "p foo(jap)" "= 12"
+gdb_test "p foo(japp)" "= 13"
+gdb_test "p foo(jca)" "= 14"
+
+#test overload resolution
+gdb_test "p foo(ko,1)" "= 15"
+gdb_test "p foo(ko,1.0f)" "= 16"
+setup_xfail "*-*-*"
+gdb_test "p bar(ko,1)" "= -1"
+
+#test lookup of objects belonging to nested namespaces
+gdb_test "p foo(labo)" "= 17"
+
+#test koenig found function do not compete with qualified
+#names
+gdb_test "p ma.foo('a')" "= 18"
+gdb_test "p foo(ma,'a')" "= 19"
+gdb_test "p M::N::foo(ma,'a')" "= 20"
+gdb_test "p M::FAKE::foo(ma,'a')" "No type \"FAKE\" within class or namespace \"M\"."
+gdb_test "p M::N::fake(ma,'a')" "No symbol \"fake\" in namespace \"M::N\"."
+
+gdb_test "p M::bar('a')" "= 21"
+gdb_test "p M::N::bar('a')" "= 22"
diff --git a/gdb/valops.c b/gdb/valops.c
index 4a7a334..38fc93e 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -63,13 +63,15 @@ static struct value *search_struct_method (const char *, struct value **,
 static int find_oload_champ_namespace (struct type **, int,
 				       const char *, const char *,
 				       struct symbol ***,
-				       struct badness_vector **);
+				       struct badness_vector **,
+				       const int no_adl);
 
 static
 int find_oload_champ_namespace_loop (struct type **, int,
 				     const char *, const char *,
 				     int, struct symbol ***,
-				     struct badness_vector **, int *);
+				     struct badness_vector **, int *,
+				     const int no_adl);
 
 static int find_oload_champ (struct type **, int, int, int,
 			     struct fn_field *, struct symbol **,
@@ -2308,6 +2310,10 @@ value_find_oload_method_list (struct value **argp, const char *method,
    If a method is being searched for, and it is a static method,
    then STATICP will point to a non-zero value.
 
+   If NO_ADL argument dependent lookup is disabled.  This is used to prevent
+   ADL overload candidates when performing overload resolution for a fully
+   qualified name.
+
    Note: This function does *not* check the value of
    overload_resolution.  Caller must check it to see whether overload
    resolution is permitted.
@@ -2318,7 +2324,7 @@ find_overload_match (struct type **arg_types, int nargs,
 		     const char *name, int method, int lax, 
 		     struct value **objp, struct symbol *fsym,
 		     struct value **valp, struct symbol **symp, 
-		     int *staticp)
+		     int *staticp, const int no_adl)
 {
   struct value *obj = (objp ? *objp : NULL);
   /* Index of best overloaded function.  */
@@ -2336,10 +2342,10 @@ find_overload_match (struct type **arg_types, int nargs,
   int boffset;
   int ix;
   int static_offset;
-  struct cleanup *old_cleanups = NULL;
+  struct cleanup *all_cleanups = make_cleanup (null_cleanup, NULL);
 
   const char *obj_type_name = NULL;
-  char *func_name = NULL;
+  const char *func_name = NULL;
   enum oload_classification match_quality;
 
   /* Get the list of overloaded methods or functions.  */
@@ -2384,24 +2390,39 @@ find_overload_match (struct type **arg_types, int nargs,
     }
   else
     {
-      const char *qualified_name = SYMBOL_NATURAL_NAME (fsym);
+      const char *qualified_name = NULL;
 
-      /* If we have a function with a C++ name, try to extract just
-	 the function part.  Do not try this for non-functions (e.g.
-	 function pointers).  */
-      if (qualified_name
-	  && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC)
+      if (fsym)
+        {
+          qualified_name = SYMBOL_NATURAL_NAME (fsym);
+
+          /* If we have a function with a C++ name, try to extract just
+	     the function part.  Do not try this for non-functions (e.g.
+	     function pointers).  */
+          if (qualified_name
+              && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC)
+            {
+	      char *temp;
+
+	      temp = cp_func_name (qualified_name);
+
+	      /* If cp_func_name did not remove anything, the name of the
+	         symbol did not include scope or argument types - it was
+	         probably a C-style function.  */
+	      if (temp)
+		{
+		  make_cleanup (xfree, temp);
+		  if (strcmp (temp, qualified_name) == 0)
+		    func_name = NULL;
+		  else
+		    func_name = temp;
+		}
+            }
+        }
+      else
 	{
-	  func_name = cp_func_name (qualified_name);
-
-	  /* If cp_func_name did not remove anything, the name of the
-	     symbol did not include scope or argument types - it was
-	     probably a C-style function.  */
-	  if (func_name && strcmp (func_name, qualified_name) == 0)
-	    {
-	      xfree (func_name);
-	      func_name = NULL;
-	    }
+	  func_name = name;
+	  qualified_name = name;
 	}
 
       /* If there was no C++ name, this must be a C-style function or
@@ -2413,7 +2434,6 @@ find_overload_match (struct type **arg_types, int nargs,
           return 0;
         }
 
-      old_cleanups = make_cleanup (xfree, func_name);
       make_cleanup (xfree, oload_syms);
       make_cleanup (xfree, oload_champ_bv);
 
@@ -2421,11 +2441,15 @@ find_overload_match (struct type **arg_types, int nargs,
 						func_name,
 						qualified_name,
 						&oload_syms,
-						&oload_champ_bv);
+						&oload_champ_bv,
+						no_adl);
     }
 
-  /* Check how bad the best match is.  */
+  /* Did we find a match ?  */
+  if (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,
@@ -2482,8 +2506,8 @@ find_overload_match (struct type **arg_types, int nargs,
 	}
       *objp = temp;
     }
-  if (old_cleanups != NULL)
-    do_cleanups (old_cleanups);
+
+  do_cleanups (all_cleanups);
 
   switch (match_quality)
     {
@@ -2501,14 +2525,16 @@ find_overload_match (struct type **arg_types, int nargs,
    runs out of namespaces.  It stores the overloaded functions in
    *OLOAD_SYMS, and the badness vector in *OLOAD_CHAMP_BV.  The
    calling function is responsible for freeing *OLOAD_SYMS and
-   *OLOAD_CHAMP_BV.  */
+   *OLOAD_CHAMP_BV.  If NO_ADL, argument dependent lookup is not 
+   performned.  */
 
 static int
 find_oload_champ_namespace (struct type **arg_types, int nargs,
 			    const char *func_name,
 			    const char *qualified_name,
 			    struct symbol ***oload_syms,
-			    struct badness_vector **oload_champ_bv)
+			    struct badness_vector **oload_champ_bv,
+			    const int no_adl)
 {
   int oload_champ;
 
@@ -2516,7 +2542,8 @@ find_oload_champ_namespace (struct type **arg_types, int nargs,
 				   func_name,
 				   qualified_name, 0,
 				   oload_syms, oload_champ_bv,
-				   &oload_champ);
+				   &oload_champ,
+				   no_adl);
 
   return oload_champ;
 }
@@ -2524,7 +2551,8 @@ find_oload_champ_namespace (struct type **arg_types, int nargs,
 /* Helper function for find_oload_champ_namespace; NAMESPACE_LEN is
    how deep we've looked for namespaces, and the champ is stored in
    OLOAD_CHAMP.  The return value is 1 if the champ is a good one, 0
-   if it isn't.
+   if it isn't.  Other arguments are the same as in
+   find_oload_champ_namespace
 
    It is the caller's responsibility to free *OLOAD_SYMS and
    *OLOAD_CHAMP_BV.  */
@@ -2536,7 +2564,8 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
 				 int namespace_len,
 				 struct symbol ***oload_syms,
 				 struct badness_vector **oload_champ_bv,
-				 int *oload_champ)
+				 int *oload_champ,
+				 const int no_adl)
 {
   int next_namespace_len = namespace_len;
   int searched_deeper = 0;
@@ -2570,7 +2599,7 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
 					   func_name, qualified_name,
 					   next_namespace_len,
 					   oload_syms, oload_champ_bv,
-					   oload_champ))
+					   oload_champ, no_adl))
 	{
 	  return 1;
 	}
@@ -2591,6 +2620,12 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
   new_namespace[namespace_len] = '\0';
   new_oload_syms = make_symbol_overload_list (func_name,
 					      new_namespace);
+
+  /* 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);
+
   while (new_oload_syms[num_fns])
     ++num_fns;
 
@@ -2623,7 +2658,6 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
     }
   else
     {
-      gdb_assert (new_oload_champ != -1);
       *oload_syms = new_oload_syms;
       *oload_champ = new_oload_champ;
       *oload_champ_bv = new_oload_champ_bv;
diff --git a/gdb/value.h b/gdb/value.h
index 1f2086e..57b4dd7 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -451,7 +451,7 @@ extern int find_overload_match (struct type **arg_types, int nargs,
 				const char *name, int method, int lax,
 				struct value **objp, struct symbol *fsym,
 				struct value **valp, struct symbol **symp,
-				int *staticp);
+				int *staticp, const int no_adl);
 
 extern struct value *value_field (struct value *arg1, int fieldno);
 

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