Add ADL support
authorSami Wagiaalla <swagiaal@redhat.com>
Fri, 7 May 2010 14:46:28 +0000 (14:46 +0000)
committerSami Wagiaalla <swagiaal@redhat.com>
Fri, 7 May 2010 14:46:28 +0000 (14:46 +0000)
2010-05-07  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-05-07  Sami Wagiaalla  <swagiaal@redhat.com>

* gdb.cp/koenig.exp: New test.
* gdb.cp/koenig.cc: New test program.

13 files changed:
gdb/ChangeLog
gdb/c-exp.y
gdb/cp-support.c
gdb/cp-support.h
gdb/eval.c
gdb/expprint.c
gdb/expression.h
gdb/parse.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/koenig.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/koenig.exp [new file with mode: 0644]
gdb/valops.c
gdb/value.h

index 8a4703e732ec99cada5930e327eaae4f3d42395c..d5a9fb61d3ed0547d517c88640de1af7568f5c5c 100644 (file)
@@ -1,3 +1,30 @@
+2010-05-07  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-05-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * fbsd-nat.c (fbsd_make_corefile_notes): Add cast to NULL used as
index 44fa6905446380c8676c514f33266f7fbb4c9535..4db41033db41200bd7e49bffeee78cee04d68d7d 100644 (file)
@@ -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); /* Placeholder.  */
+                         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; }
        ;
 
@@ -1244,6 +1269,7 @@ name_not_typename :       NAME
                                                  VAR_DOMAIN,
                                                  &$$.is_a_field_of_this);
                        }
+       |       UNKNOWN_CPP_NAME
        ;
 
 %%
@@ -2387,6 +2413,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;
 }
 
index b5db6e0c74780e96a3d5780945404ec775a28177..8f447caa2269fa88c1f24400d258d00864d07916 100644 (file)
@@ -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;
 
@@ -709,6 +709,87 @@ 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_CODE (type) == TYPE_CODE_TYPEDEF)
+    {
+      if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+       type = check_typedef(type);
+      else
+       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
@@ -736,20 +817,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.
index dd4df842df1a30118440e115d781b08d51c0ff41..ddc4c9377c5f0168fa2f69c70040ca147abf9201 100644 (file)
@@ -110,6 +110,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);
 
index b5c2012c9af7fd4fef7a3860280cea5d53833ef4..985e653ddf68fb0994112c928ded6e51308dcf0c 100644 (file)
@@ -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)
@@ -1452,6 +1453,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 */
@@ -1482,6 +1494,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))
@@ -1513,7 +1551,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)
                {
@@ -1565,6 +1603,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;
@@ -1577,7 +1620,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)
                {
index e378831b84a39ddb9b64d0b2c95b1be1bc1f3076..45deffe4ab52592a5d0723477b4d2b8f1c7386cf 100644 (file)
@@ -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";
     }
 }
 
index ca216cf13e0bf62130acd0b787c69557dd46a48d..29ebde46b0e2f9b9aa8e16cefc847c717191285e 100644 (file)
@@ -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:
index 5319555072c44bf22059c8ffb4e1a8f444072e02..7db6e926bf0278e8e592c43cc0f6ec5509a8163e 100644 (file)
@@ -890,6 +890,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:
index 457a6282c35bf51ecd2851013cafabcc6c9774c3..013f5eb8e9867faee324931b31e0c7f6352d152e 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-07  Sami Wagiaalla  <swagiaal@redhat.com>
+
+       * gdb.cp/koenig.exp: New test.
+       * gdb.cp/koenig.cc: New test program.
+
 2010-05-05  Joel Brobecker  <brobecker@adacore.com>
 
        Remove the use of prms_id and bug_id throughout the testsuite.
diff --git a/gdb/testsuite/gdb.cp/koenig.cc b/gdb/testsuite/gdb.cp/koenig.cc
new file mode 100644 (file)
index 0000000..6cfa3f5
--- /dev/null
@@ -0,0 +1,245 @@
+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;
+    }
+  }
+}
+//------------
+
+namespace O {
+  class A{};
+
+  int foo(A,int){
+    return 23;
+  }
+
+}
+
+typedef O::A TOA;
+typedef TOA  TTOA;
+
+//------------
+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');
+
+  TTOA ttoa;
+  foo (ttoa, '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 (file)
index 0000000..b13ffbc
--- /dev/null
@@ -0,0 +1,109 @@
+# 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"
+
+#test that lookup supports typedef
+gdb_test "p foo(ttoa, 'a')" "= 23"
index 65706c5ff2e2bd1517a6e56bff36811befcae5ec..7979db91c004147cde52c5036d9abce0ee7b61ff 100644 (file)
@@ -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 **,
@@ -2306,6 +2308,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.
@@ -2316,7 +2322,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.  */
@@ -2332,10 +2338,11 @@ find_overload_match (struct type **arg_types, int nargs,
   int num_fns = 0;
   struct type *basetype = NULL;
   int boffset;
-  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.  */
@@ -2380,24 +2387,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
@@ -2409,7 +2431,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);
 
@@ -2417,11 +2438,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,
@@ -2478,8 +2503,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)
     {
@@ -2497,14 +2522,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;
 
@@ -2512,7 +2539,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;
 }
@@ -2520,7 +2548,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.  */
@@ -2532,7 +2561,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;
@@ -2566,7 +2596,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;
        }
@@ -2587,6 +2617,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;
 
@@ -2619,7 +2655,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;
index 1f2086e93177ba0048b5fb461de212a411b540fb..57b4dd726f2fbd47753aa21624d09bb45d54b69b 100644 (file)
@@ -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);