public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* [RFC] Koenig lookup patch
@ 2009-03-13 19:58 Sami Wagiaalla
  2009-03-13 22:10 ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-03-13 19:58 UTC (permalink / raw)
  To: Project Archer

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

Hi,

I have attached the patch for koenig lookup. I would like to hear your 
thoughts on the approach.

During lexing the if a name token cannot be looked up, the lexer returns 
an UNKNOWN_NAME token with the name of the potential symbol.

If the parser sees an UNKNOWN_NAME token it creates a shell expression 
that looks like the one that would be created for a variable except it 
has a NULL where the symbol would normally be added, and the operator is 
OP_ADL_FUNCTION instead OP_VAR_VALUE. If UNKNOWN_NAME is followed by '(' 
0 or more arguments and ')' a function call is created using the shell 
expression for symbol that was created.

During evaluation when an OP_ADL_FUNCTION operator is encountered then 
expressions for the arguments are evaluated the prefixes of their types 
are collected then used to lookup the unknown name. The newly found 
symbol replaces the place holding NULL and the expression is evaluated 
as if it was a normal OP_VAR_VALUE. Overloads are resolved, and finally 
the result is used to perform the inferior function call.

Here is a copy and paste demo:

namespace A {
   class C {
   };

   int foo(C arg)
   {
     return 11;
   }
}

struct X{
   A::C theC;
};

int main()
{
   A::C theC;
   X x;
   foo(theC);
   foo(x.theC);
}

(gdb) break main
Breakpoint 1 at 0x40056f: file koenig.c, line 20.
(gdb) run

Breakpoint 1, main () at koenig.c:20
20	  foo(theC);
Current language:  auto; currently c++
(gdb) list
15	
16	int main()
17	{
18	  A::C theC;
19	  X x;
20	  foo(theC);
21	  foo(x.theC);
22	}
(gdb) print foo(theC)
$1 = 11
(gdb) print foo(x.theC)
$2 = 11
(gdb)



Thanks,
   Sami

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

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..7b0b299 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME 
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
+exp	:	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); 	      
+			}
+	;
+
+adl_func	:	UNKNOWN_NAME
+			{/* This could potentially be a an argument dependet 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);
+			}
+			;
+		
+
 lcurly	:	'{'
 			{ start_arglist (); }
 	;
@@ -796,6 +821,7 @@ variable:	name_not_typename
 	;
 
 space_identifier : '@' NAME
+		|  '@' UNKNOWN_NAME
 		{ push_type_address_space (copy_name ($2.stoken));
 		  push_type (tp_space_identifier);
 		}
@@ -1091,10 +1117,12 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
 	;
 
 name_not_typename :	NAME
 	|	BLOCKNAME
+	|	UNKNOWN_NAME
 /* These would be useful if name_not_typename was useful, but it is just
    a fake for "variable", so these cause reduce/reduce conflicts because
    the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2044,11 @@ yylex ()
     if (in_parse_field && *lexptr == '\0')
       saw_name_at_eof = 1;
         
+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)
+      {
+        return UNKNOWN_NAME;
+      }
+    
     return NAME;
   }
 }
diff --git a/gdb/eval.c b/gdb/eval.c
index 0262b35..3775321 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -672,6 +672,9 @@ evaluate_subexp_standard (struct type *expect_type,
   struct type **arg_types;
   int save_pos1;
 
+  static char** prefix_array = NULL;
+  static int    prefix_array_size = 0;
+
   pc = (*pos)++;
   op = exp->elts[pc].opcode;
 
@@ -704,6 +707,57 @@ 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:
+      {
+        char *func_name;
+        char *prefix;
+        char *concatenated_name;
+        struct symbol *sym = NULL;
+        int string_length;
+        int i = 0;
+        int string_pc = pc + 3;
+
+        string_length = longest_to_int (exp->elts[string_pc].longconst);
+
+        func_name = (char*) alloca(string_length+1);
+        strcpy (func_name, &exp->elts[string_pc + 1].string);
+        sym = exp->elts[pc + 2].symbol;
+        if (sym == NULL)
+          { /* Symbol has not been resolved yet. */
+            for (i = 0; sym == NULL && i < prefix_array_size; i++)
+              {
+                prefix = prefix_array[i];
+                concatenated_name = alloca (strlen (prefix) + 1 + strlen (func_name) + 1);
+                strcpy(concatenated_name, prefix);
+                strcat(concatenated_name, "::");
+                strcat(concatenated_name, func_name);
+
+                sym = lookup_symbol(concatenated_name,
+                    exp->elts[pc + 1].block, VAR_DOMAIN, (int *) NULL);
+
+                if (sym)
+                  {
+                    exp->elts[pc + 2].symbol = sym;
+                    break;
+                  }
+              }
+
+            /* free prefix_array */
+            for (i = 0; i < prefix_array_size; ++i)
+              {
+                xfree(prefix_array[i]);
+              }
+            xfree(prefix_array);
+            prefix_array = NULL;
+            prefix_array_size = 0;
+          }
+
+        if (sym == NULL)
+          {
+            error("No function \"%s\" in specified context.", func_name);
+          }
+      }
+      /* Now fall through for normal symbol evaluation  */
     case OP_VAR_VALUE:
       (*pos) += 3;
       if (noside == EVAL_SKIP)
@@ -1276,6 +1330,10 @@ evaluate_subexp_standard (struct type *expect_type,
       break;
 
     case OP_FUNCALL:
+      {
+        int adl_func_pos = 0;
+        int adl_func = 0;
+
       (*pos) += 2;
       op = exp->elts[*pos].opcode;
       nargs = longest_to_int (exp->elts[pc + 1].longconst);
@@ -1362,8 +1420,21 @@ evaluate_subexp_standard (struct type *expect_type,
 	  /* Now, say which argument to start evaluating from */
 	  tem = 2;
 	}
-      else
+      else if ( op == OP_ADL_FUNC )
 	{
+          int temp;
+          adl_func_pos = *pos;
+          tem = 1;
+          adl_func = 1;
+
+          prefix_array = xzalloc (sizeof(char*) * nargs);
+          temp = longest_to_int (exp->elts[adl_func_pos + 3].longconst);
+          (*pos)++; // block
+          (*pos)++; // symbol
+          (*pos)++; // strlng
+          (*pos) += 3 + BYTES_TO_EXP_ELEM (temp + 1); // string + a null terminator
+        }
+      else{
 	  /* Non-method function call */
 	  save_pos1 = *pos;
 	  argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -1386,8 +1457,39 @@ evaluate_subexp_standard (struct type *expect_type,
       /* Evaluate arguments */
       for (; tem <= nargs; tem++)
 	{
+
 	  /* Ensure that array expressions are coerced into pointer objects. */
 	  argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+
+	  if(adl_func)
+	    {
+	    /* save prefixes */
+	    char* cindex;
+	    char* name;
+
+	    name = TYPE_NAME (value_type (argvec[tem]));
+	    cindex = rindex(name, ':');
+	    if(cindex != NULL){
+	      prefix_array[prefix_array_size] = savestring(name, (int)(cindex - name) - 1);
+	      prefix_array_size++;
+	    }
+	  }
+
+	}
+
+      if(adl_func){
+        struct symbol *symp;
+        save_pos1 = adl_func_pos;
+        argvec[0] = evaluate_subexp_with_coercion (exp, &adl_func_pos, noside);
+
+        (void) find_overload_match (argvec, nargs, NULL /* no need for name */ ,
+            0 /* not method */ , 0 /* strict match */ ,
+            NULL, exp->elts[save_pos1+2].symbol /* the function */ ,
+            NULL, &symp, NULL);
+
+        /* Now fix the expression being evaluated */
+        exp->elts[save_pos1+2].symbol = symp;
+        argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
 	}
 
       /* signal end of arglist */
@@ -1502,9 +1604,10 @@ evaluate_subexp_standard (struct type *expect_type,
 	  else
 	    error (_("Expression of type other than \"Function returning ...\" used as function"));
 	}
+
       return call_function_by_hand (argvec[0], nargs, argvec + 1);
       /* pai: FIXME save value from call_function_by_hand, then adjust pc by adjust_fn_pc if +ve  */
-
+      }
     case OP_F77_UNDETERMINED_ARGLIST:
 
       /* Remember that in F77, functions, substring ops and 
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
        Then comes another OP_DECFLOAT.  */
     OP_DECFLOAT,
 
+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
      /* First extension operator.  Individual language modules define
         extra operators they need as constants with values 
         OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate 
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..c6f1c9a 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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++; // block
+      oplen++; // symbol
+      break;
+
     case OP_LABELED:
     case STRUCTOP_STRUCT:
     case STRUCTOP_PTR:

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

* Re: [RFC] Koenig lookup patch
  2009-03-13 19:58 [RFC] Koenig lookup patch Sami Wagiaalla
@ 2009-03-13 22:10 ` Tom Tromey
  2009-03-17 18:39   ` Sami Wagiaalla
  2009-04-29 15:51   ` [RFC] Koenig lookup patch 2 Sami Wagiaalla
  0 siblings, 2 replies; 15+ messages in thread
From: Tom Tromey @ 2009-03-13 22:10 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Sami> I have attached the patch for koenig lookup. I would like to hear your
Sami> thoughts on the approach.

Here's a few things I noticed.  I stuck to the important stuff.  I'll
send another note describing the various formatting nits and similar
trivia.

Sami>  space_identifier : '@' NAME
Sami> +		|  '@' UNKNOWN_NAME
Sami>  		{ push_type_address_space (copy_name ($2.stoken));
Sami>  		  push_type (tp_space_identifier);

You have to duplicate the actions here.

Sami> +    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)

lookup_minimal_symbol definitely won't follow the normal C++ lookup rules.
So, this is not really implementing the C++ spec.

I am not sure this can really be done in the lexer.

I suppose you could look for a class member, based on the parser
context, and return NAME in that case.  I don't know whether that
would always be correct.

Another possible approach would be to have a C-specific evaluate
function (other languages have examples of this, and the charset
branch does it for C) that changes the function call code to do
C++-specific stuff.

Sami> +  static char** prefix_array = NULL;
Sami> +  static int    prefix_array_size = 0;

Statics are usually bad.  I guess this is to avoid adding extra
arguments all up and down the evaluate_* call chain...

Another approach would be to factor some of the code out into a helper
function, then call it.  Then things like that can simply be
arguments.

If you want to stick with the statics, you will have to add cleanups,
as right now they can be leaked.  Also I think you will have to change
how they are allocated, because the value can be overwritten by a
recursive call to evaluate_subexp_standard.

Sami> +                sym = lookup_symbol(concatenated_name,
Sami> +                    exp->elts[pc + 1].block, VAR_DOMAIN, (int *) NULL);
Sami> +
Sami> +                if (sym)
Sami> +                  {
Sami> +                    exp->elts[pc + 2].symbol = sym;
Sami> +                    break;
Sami> +                  }
Sami> +              }

I suspect this kind of thing belongs elsewhere.

My understanding is that ADL can add some symbols to the overload set.
But, this seems to stop when it finds any matching symbol.

Instead I would expect to find this in the code that computes the
overload set.  I see later there is a call to find_overload_match, but
given that I don't understand the need to do a lookup_symbol here.

Rewriting the expression in-place seems a bit weird.
It may always work, but I am not certain ... I'm not sure whether a
parsed expression can validly be re-evaluated in a context other than
the one in which it was created.


One thing I would like to see is a reasonably comprehensive set of
tests, in particular including tests of whatever odd cases there are,
and of some error cases.

Tom

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

* Re: [RFC] Koenig lookup patch
  2009-03-13 22:10 ` Tom Tromey
@ 2009-03-17 18:39   ` Sami Wagiaalla
  2009-03-17 21:25     ` Tom Tromey
  2009-04-29 15:51   ` [RFC] Koenig lookup patch 2 Sami Wagiaalla
  1 sibling, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-03-17 18:39 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer


> Sami>  space_identifier : '@' NAME
> Sami> +		|  '@' UNKNOWN_NAME
> Sami>  		{ push_type_address_space (copy_name ($2.stoken));
> Sami>  		  push_type (tp_space_identifier);
> 
> You have to duplicate the actions here.
> 

Hmm it looks like NAME is no longer nessesary here

> Sami> +    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)
> 
> lookup_minimal_symbol definitely won't follow the normal C++ lookup rules.
> So, this is not really implementing the C++ spec.
> 
> I am not sure this can really be done in the lexer.
> 
> I suppose you could look for a class member, based on the parser
> context, and return NAME in that case.  I don't know whether that
> would always be correct.
> 
> Another possible approach would be to have a C-specific evaluate
> function (other languages have examples of this, and the charset
> branch does it for C) that changes the function call code to do
> C++-specific stuff.
> 

This is done to distinguish an adl_func from names which are meant to be 
  found through lookup_minimal_symbol. Without this check tests for 
checkpoint try to call 'lseek', this gets wrongly reduced to an 
adl_function and the later ADL lookup fails.

> Sami> +  static char** prefix_array = NULL;
> Sami> +  static int    prefix_array_size = 0;
> 
> Statics are usually bad.  I guess this is to avoid adding extra
> arguments all up and down the evaluate_* call chain...
> 
> Another approach would be to factor some of the code out into a helper
> function, then call it.  Then things like that can simply be
> arguments.
> 
> If you want to stick with the statics, you will have to add cleanups,
> as right now they can be leaked.  Also I think you will have to change
> how they are allocated, because the value can be overwritten by a
> recursive call to evaluate_subexp_standard.
> 
> Sami> +                sym = lookup_symbol(concatenated_name,
> Sami> +                    exp->elts[pc + 1].block, VAR_DOMAIN, (int *) NULL);
> Sami> +
> Sami> +                if (sym)
> Sami> +                  {
> Sami> +                    exp->elts[pc + 2].symbol = sym;
> Sami> +                    break;
> Sami> +                  }
> Sami> +              }
> 
> I suspect this kind of thing belongs elsewhere.
> 
> My understanding is that ADL can add some symbols to the overload set.
> But, this seems to stop when it finds any matching symbol.
> 
> Instead I would expect to find this in the code that computes the
> overload set.  I see later there is a call to find_overload_match, but
> given that I don't understand the need to do a lookup_symbol here.
> 

Yeah, the above code can actually be moved into find_overload_match I 
never really thought of it that way. This will get rid of the statics, 
and allocation problems.

> Rewriting the expression in-place seems a bit weird.

It makes sense to me. You see the parameters of this expression actually 
depend on the result of the evaluation of the parameters particularly of 
the parameters are expressed in complex expressions and not plain 
variable names.

> It may always work, but I am not certain ... I'm not sure whether a
> parsed expression can validly be re-evaluated in a context other than
> the one in which it was created.
> 

If by context you mean scope, that is preserved and passed in as part of 
the "pre-expression" here exp->elts[pc + 1].block. I cant think of 
anything else but we can adapt this when we run into such cases.
> 
> One thing I would like to see is a reasonably comprehensive set of
> tests, in particular including tests of whatever odd cases there are,
> and of some error cases.

Looks like I forgot to git add my tests. Please see:
  git show fbf9dc5c8c817b100ad7ce5c680c4bf346e326df

Thanks for the review. I'll post an update version soon.

Sami

> 
> Tom

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

* Re: [RFC] Koenig lookup patch
  2009-03-17 18:39   ` Sami Wagiaalla
@ 2009-03-17 21:25     ` Tom Tromey
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2009-03-17 21:25 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Tom> Rewriting the expression in-place seems a bit weird.

Sami> It makes sense to me. You see the parameters of this expression
Sami> actually depend on the result of the evaluation of the parameters
Sami> particularly of the parameters are expressed in complex expressions
Sami> and not plain variable names.

Oh, that reminds me... using the types of the actual arguments can
yield incorrect results.  Instead the formal types must be used.
The difference matters because a subclass might be in a different
namespace from its superclass.

Tom

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

* Re: [RFC] Koenig lookup patch 2
  2009-03-13 22:10 ` Tom Tromey
  2009-03-17 18:39   ` Sami Wagiaalla
@ 2009-04-29 15:51   ` Sami Wagiaalla
  2009-04-30  0:19     ` Tom Tromey
  1 sibling, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-04-29 15:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

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

commit 7d1e49d1b6be54d563280f13fd69672faa98ef6f
Author: Sami Wagiaalla <swagiaal@redhat.com>
Date:   Wed Apr 29 11:28:57 2009 -0400

     Recommit: Added support for ADL function lookup. Patch 2.

     2009-04-28  Sami Wagiaalla  <swagiaal@redhat.com>

        * valops.c (find_overload_match): Added adl argument.
        Perform argument defined lookup when requested.
        * parse.c (operator_length_standard): Added length information for
        OP_ADL_FUNC.
        * expression.h: Added OP_ADL_FUNC.
        * c-exp.y: Created token UNKOWN_NAME.
        Created grammer rules for UNKOWN_NAME, and adl_function.
        * eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..7e12e0c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);

  %token <sval> STRING
  %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME
  %token <voidval> COMPLETE
  %token <tsym> TYPENAME
  %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
  			  write_exp_elt_opcode (OP_FUNCALL); }
  	;

+exp	:	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); 	
+			}
+	;
+
+adl_func	:	UNKNOWN_NAME
+			{/* This could potentially be a an argument dependet 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);
+			}
+			;
+		
+
  lcurly	:	'{'
  			{ start_arglist (); }
  	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
  			}
  	;

-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
  		{ push_type_address_space (copy_name ($2.stoken));
  		  push_type (tp_space_identifier);
  		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
  	|	BLOCKNAME { $$ = $1.stoken; }
  	|	TYPENAME { $$ = $1.stoken; }
  	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
  	;

  name_not_typename :	NAME
  	|	BLOCKNAME
+	|	UNKNOWN_NAME
  /* These would be useful if name_not_typename was useful, but it is just
     a fake for "variable", so these cause reduce/reduce conflicts because
     the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2043,11 @@ yylex ()
      if (in_parse_field && *lexptr == '\0')
        saw_name_at_eof = 1;

+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)
+      {
+        return UNKNOWN_NAME;
+      }
+
      return NAME;
    }
  }
diff --git a/gdb/eval.c b/gdb/eval.c
index 0262b35..0fa10c7 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
  	  /* Now, say which argument to start evaluating from */
  	  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 */
@@ -1393,6 +1405,26 @@ 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;
+
+          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);
+          find_overload_match (argvec, nargs, func_name,
+                               0 /* not method */ , 0 /* strict match */ ,
+                               NULL, NULL /* pass NULL symbol to signal ADL lookup */ ,
+                               NULL, &symp, NULL, 1);
+
+          /* 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)
  	{
  	  int static_memfuncp;
@@ -1411,7 +1443,7 @@ evaluate_subexp_standard (struct type *expect_type,
  	      (void) find_overload_match (argvec, nargs, tstr,
  				     1 /* method */ , 0 /* strict match */ ,
  					  &arg2 /* the object */ , NULL,
-					  &valp, NULL, &static_memfuncp);
+					  &valp, NULL, &static_memfuncp, 0);


  	      argvec[1] = arg2;	/* the ``this'' pointer */
@@ -1461,7 +1493,7 @@ evaluate_subexp_standard (struct type *expect_type,
  	      (void) find_overload_match (argvec, nargs, NULL /* no need for name */ ,
  				 0 /* not method */ , 0 /* strict match */ ,
  		      NULL, exp->elts[save_pos1+2].symbol /* the function */ ,
-					  NULL, &symp, NULL);
+					  NULL, &symp, NULL, 0);

  	      /* Now fix the expression being evaluated */
  	      exp->elts[save_pos1+2].symbol = symp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
         Then comes another OP_DECFLOAT.  */
      OP_DECFLOAT,

+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
       /* First extension operator.  Individual language modules define
          extra operators they need as constants with values
          OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/valops.c b/gdb/valops.c
index 400a4d1..0345645 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2048,6 +2048,9 @@ value_find_oload_method_list (struct value **argp, char *method,
     Note: This function does *not* check the value of
     overload_resolution.  Caller must check it to see whether overload
     resolution is permitted.
+
+   If adl is a non zero value, this function attempts to perform an
+   argument defined lookup.
  */

  int
@@ -2055,7 +2058,7 @@ find_overload_match (struct value **argvec, int nargs,
  		     char *name, int method, int lax,
  		     struct value **objp, struct symbol *fsym,
  		     struct value **valp, struct symbol **symp,
-		     int *staticp)
+		     int *staticp, int adl)
  {
    struct value *obj = (objp ? *objp : NULL);
    /* Index of best overloaded function.  */
@@ -2083,9 +2086,37 @@ find_overload_match (struct value **argvec, int nargs,

    /* Prepare list of argument types for overload resolution */
    arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
-  for (ix = 1; ix <= nargs; ix++)
+  for (ix = 1; ix <= nargs; ix++){
      arg_types[ix - 1] = value_type (argvec[ix]);

+    /* If this is an ADL lookup */
+    if ( adl && fsym == NULL )
+      {
+        char *type_name;
+        char *cindex;
+        char *prefix;
+        int prefix_len;
+        char *concatenated_name;
+
+        type_name = TYPE_NAME (arg_types[ix - 1]);
+        cindex = rindex(type_name, ':');
+        if(cindex != NULL){
+          prefix_len = (int)(cindex - type_name) - 1;
+          prefix = alloca(prefix_len+1);
+          strncpy(prefix, type_name, prefix_len);
+          prefix[prefix_len] = '\0';
+
+          concatenated_name = alloca (strlen (prefix) + 1 + strlen (name) + 1);
+          strcpy(concatenated_name, prefix);
+          strcat(concatenated_name, "::");
+          strcat(concatenated_name, name);
+
+          fsym = lookup_symbol(concatenated_name,NULL, VAR_DOMAIN, (int *) NULL);
+        }
+      }
+
+  }
+
    /* Get the list of overloaded methods or functions.  */
    if (method)
      {
diff --git a/gdb/value.h b/gdb/value.h
index 0ad1d12..6ff8f79 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -448,7 +448,7 @@ extern int find_overload_match (struct value **argvec , int nargs,
  				char *name, int method, int lax,
  				struct value **objp, struct symbol *fsym,
  				struct value **valp, struct symbol **symp,
-				int *staticp);
+				int *staticp, int adl);

  extern struct value *value_field (struct value *arg1, int fieldno);


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

commit 7d1e49d1b6be54d563280f13fd69672faa98ef6f
Author: Sami Wagiaalla <swagiaal@redhat.com>
Date:   Wed Apr 29 11:28:57 2009 -0400

    Recommit: Added support for ADL function lookup. Patch 2.
    
    2009-04-28  Sami Wagiaalla  <swagiaal@redhat.com>
    
       * valops.c (find_overload_match): Added adl argument.
       Perform argument defined lookup when requested.
       * parse.c (operator_length_standard): Added length information for
       OP_ADL_FUNC.
       * expression.h: Added OP_ADL_FUNC.
       * c-exp.y: Created token UNKOWN_NAME.
       Created grammer rules for UNKOWN_NAME, and adl_function.
       * eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..7e12e0c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME 
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
+exp	:	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); 	      
+			}
+	;
+
+adl_func	:	UNKNOWN_NAME
+			{/* This could potentially be a an argument dependet 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);
+			}
+			;
+		
+
 lcurly	:	'{'
 			{ start_arglist (); }
 	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
 			}
 	;
 
-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
 		{ push_type_address_space (copy_name ($2.stoken));
 		  push_type (tp_space_identifier);
 		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
 	;
 
 name_not_typename :	NAME
 	|	BLOCKNAME
+	|	UNKNOWN_NAME
 /* These would be useful if name_not_typename was useful, but it is just
    a fake for "variable", so these cause reduce/reduce conflicts because
    the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2043,11 @@ yylex ()
     if (in_parse_field && *lexptr == '\0')
       saw_name_at_eof = 1;
         
+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)
+      {
+        return UNKNOWN_NAME;
+      }
+    
     return NAME;
   }
 }
diff --git a/gdb/eval.c b/gdb/eval.c
index 0262b35..0fa10c7 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
 	  /* Now, say which argument to start evaluating from */
 	  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 */
@@ -1393,6 +1405,26 @@ 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;
+
+          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);
+          find_overload_match (argvec, nargs, func_name,
+                               0 /* not method */ , 0 /* strict match */ ,
+                               NULL, NULL /* pass NULL symbol to signal ADL lookup */ ,
+                               NULL, &symp, NULL, 1);
+
+          /* 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)
 	{
 	  int static_memfuncp;
@@ -1411,7 +1443,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      (void) find_overload_match (argvec, nargs, tstr,
 				     1 /* method */ , 0 /* strict match */ ,
 					  &arg2 /* the object */ , NULL,
-					  &valp, NULL, &static_memfuncp);
+					  &valp, NULL, &static_memfuncp, 0);
 
 
 	      argvec[1] = arg2;	/* the ``this'' pointer */
@@ -1461,7 +1493,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      (void) find_overload_match (argvec, nargs, NULL /* no need for name */ ,
 				 0 /* not method */ , 0 /* strict match */ ,
 		      NULL, exp->elts[save_pos1+2].symbol /* the function */ ,
-					  NULL, &symp, NULL);
+					  NULL, &symp, NULL, 0);
 
 	      /* Now fix the expression being evaluated */
 	      exp->elts[save_pos1+2].symbol = symp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
        Then comes another OP_DECFLOAT.  */
     OP_DECFLOAT,
 
+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
      /* First extension operator.  Individual language modules define
         extra operators they need as constants with values 
         OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate 
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/valops.c b/gdb/valops.c
index 400a4d1..0345645 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2048,6 +2048,9 @@ value_find_oload_method_list (struct value **argp, char *method,
    Note: This function does *not* check the value of
    overload_resolution.  Caller must check it to see whether overload
    resolution is permitted.
+
+   If adl is a non zero value, this function attempts to perform an
+   argument defined lookup.
 */
 
 int
@@ -2055,7 +2058,7 @@ find_overload_match (struct value **argvec, int nargs,
 		     char *name, int method, int lax, 
 		     struct value **objp, struct symbol *fsym,
 		     struct value **valp, struct symbol **symp, 
-		     int *staticp)
+		     int *staticp, int adl)
 {
   struct value *obj = (objp ? *objp : NULL);
   /* Index of best overloaded function.  */
@@ -2083,9 +2086,37 @@ find_overload_match (struct value **argvec, int nargs,
 
   /* Prepare list of argument types for overload resolution */
   arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
-  for (ix = 1; ix <= nargs; ix++)
+  for (ix = 1; ix <= nargs; ix++){
     arg_types[ix - 1] = value_type (argvec[ix]);
 
+    /* If this is an ADL lookup */
+    if ( adl && fsym == NULL )
+      {
+        char *type_name;
+        char *cindex;
+        char *prefix;
+        int prefix_len;
+        char *concatenated_name;
+
+        type_name = TYPE_NAME (arg_types[ix - 1]);
+        cindex = rindex(type_name, ':');
+        if(cindex != NULL){
+          prefix_len = (int)(cindex - type_name) - 1;
+          prefix = alloca(prefix_len+1);
+          strncpy(prefix, type_name, prefix_len);
+          prefix[prefix_len] = '\0';
+
+          concatenated_name = alloca (strlen (prefix) + 1 + strlen (name) + 1);
+          strcpy(concatenated_name, prefix);
+          strcat(concatenated_name, "::");
+          strcat(concatenated_name, name);
+
+          fsym = lookup_symbol(concatenated_name,NULL, VAR_DOMAIN, (int *) NULL);
+        }
+      }
+
+  }
+
   /* Get the list of overloaded methods or functions.  */
   if (method)
     {
diff --git a/gdb/value.h b/gdb/value.h
index 0ad1d12..6ff8f79 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -448,7 +448,7 @@ extern int find_overload_match (struct value **argvec , int nargs,
 				char *name, int method, int lax,
 				struct value **objp, struct symbol *fsym,
 				struct value **valp, struct symbol **symp,
-				int *staticp);
+				int *staticp, int adl);
 
 extern struct value *value_field (struct value *arg1, int fieldno);
 

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

* Re: [RFC] Koenig lookup patch 2
  2009-04-29 15:51   ` [RFC] Koenig lookup patch 2 Sami Wagiaalla
@ 2009-04-30  0:19     ` Tom Tromey
  2009-08-27 14:35       ` Sami Wagiaalla
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-04-30  0:19 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Sami>     Recommit: Added support for ADL function lookup. Patch 2.

Thanks.

Sami>        * c-exp.y: Created token UNKOWN_NAME.

FYI, a typo in the ChangeLog -- missing an "N".

A couple quick notes.  I don't have time to pick nits... there were
some formatting issues and whatnot -- these have to be fixed but are
not very important overall.

Sami> @@ -2083,9 +2086,37 @@ find_overload_match (struct value **argvec, int nargs,

With the current code is there a need to have the values here?
Or could this be reverted to the trunk's approach?

Sami> +  for (ix = 1; ix <= nargs; ix++){
Sami>      arg_types[ix - 1] = value_type (argvec[ix]);

BTW, my earlier note about needing the formal types was in error.
I think GDB really only deals in formal types, unless it does special
work to find the dynamic type.

Sami> +        if(cindex != NULL){
Sami> +          prefix_len = (int)(cindex - type_name) - 1;
Sami> +          prefix = alloca(prefix_len+1);
Sami> +          strncpy(prefix, type_name, prefix_len);
Sami> +          prefix[prefix_len] = '\0';
Sami> +
Sami> +          concatenated_name = alloca (strlen (prefix) + 1 + strlen (name) + 1);
Sami> +          strcpy(concatenated_name, prefix);
Sami> +          strcat(concatenated_name, "::");
Sami> +          strcat(concatenated_name, name);

This could be reduced to a single allocation.

Sami> +          fsym = lookup_symbol(concatenated_name,NULL, VAR_DOMAIN, (int *) NULL);

Does this really do the right thing in the case where the call has
multiple arguments, each of which has a type from a different
namespace?  I don't understand how those would get added to the
overload set.

Tom

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

* Re: [RFC] Koenig lookup patch 2
  2009-04-30  0:19     ` Tom Tromey
@ 2009-08-27 14:35       ` Sami Wagiaalla
  2009-08-27 21:49         ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-08-27 14:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

Tom Tromey wrote:
>>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:
> 
> Sami>     Recommit: Added support for ADL function lookup. Patch 2.
> 
> Thanks.
> 
> Sami>        * c-exp.y: Created token UNKOWN_NAME.
> 
> FYI, a typo in the ChangeLog -- missing an "N".
> 
> A couple quick notes.  I don't have time to pick nits... there were
> some formatting issues and whatnot -- these have to be fixed but are
> not very important overall.
> 
> Sami> @@ -2083,9 +2086,37 @@ find_overload_match (struct value **argvec, int nargs,
> 
> With the current code is there a need to have the values here?
> Or could this be reverted to the trunk's approach?
> 

This was my attempt of making the code a little more compact. It makes
sense that you should be able to perform an overload resolution with
types not values. It is just that this code:

/* 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]);

...is repeated before every call to the function.

I had also rolled the Koenig lookup into this loop in this function
but that is a cheat since Koenig is not really an overload.

> Sami> +  for (ix = 1; ix <= nargs; ix++){
> Sami>      arg_types[ix - 1] = value_type (argvec[ix]);
> 
> BTW, my earlier note about needing the formal types was in error.
> I think GDB really only deals in formal types, unless it does special
> work to find the dynamic type.
> 

Cool.

> Sami> +        if(cindex != NULL){
> Sami> +          prefix_len = (int)(cindex - type_name) - 1;
> Sami> +          prefix = alloca(prefix_len+1);
> Sami> +          strncpy(prefix, type_name, prefix_len);
> Sami> +          prefix[prefix_len] = '\0';
> Sami> +
> Sami> +          concatenated_name = alloca (strlen (prefix) + 1 + strlen (name) + 1);
> Sami> +          strcpy(concatenated_name, prefix);
> Sami> +          strcat(concatenated_name, "::");
> Sami> +          strcat(concatenated_name, name);
> 
> This could be reduced to a single allocation.
> 

I have eliminated the unneeded allocation and also found a
better way to figure out the prefix. Please see patch below.

> Sami> +          fsym = lookup_symbol(concatenated_name,NULL, VAR_DOMAIN, (int *) NULL);
> 
> Does this really do the right thing in the case where the call has
> multiple arguments, each of which has a type from a different
> namespace?  I don't understand how those would get added to the
> overload set.

The overload resolution is performed by the remainder of the function
(find_overloaded_match) this is just to give a starting point. However,
as you suspected, find_overload_match assumes that all the overload
choices are within the same namespace. This is corrected in this patch.

     Added support for ADL function lookup. Patch 3.

     2009-08-26  Sami Wagiaalla  <swagiaal@redhat.com>

     	* valops.c (find_adl_match): New function
     	* parse.c (operator_length_standard): Added length information for
     	OP_ADL_FUNC.
     	* expression.h: Added OP_ADL_FUNC.
     	* c-exp.y: Created token UNKOWN_NAME.
     	Created grammer rules for UNKOWN_NAME, and adl_function.
     	* eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.


diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..24b8481 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);

  %token <sval> STRING
  %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME
  %token <voidval> COMPLETE
  %token <tsym> TYPENAME
  %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
  			  write_exp_elt_opcode (OP_FUNCALL); }
  	;

+exp	:	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);
+			}
+	;
+
+adl_func	:	UNKNOWN_NAME
+			{
+			  /* This could potentially be a an argument dependet
+			     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);
+			}
+		;
+
  lcurly	:	'{'
  			{ start_arglist (); }
  	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
  			}
  	;

-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
  		{ push_type_address_space (copy_name ($2.stoken));
  		  push_type (tp_space_identifier);
  		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
  	|	BLOCKNAME { $$ = $1.stoken; }
  	|	TYPENAME { $$ = $1.stoken; }
  	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
  	;

  name_not_typename :	NAME
  	|	BLOCKNAME
+	|	UNKNOWN_NAME
  /* These would be useful if name_not_typename was useful, but it is just
     a fake for "variable", so these cause reduce/reduce conflicts because
     the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2043,11 @@ yylex ()
      if (in_parse_field && *lexptr == '\0')
        saw_name_at_eof = 1;

+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)
+      {
+        return UNKNOWN_NAME;
+      }
+
      return NAME;
    }
  }
diff --git a/gdb/eval.c b/gdb/eval.c
index 1d35571..8125594 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
  	  /* Now, say which argument to start evaluating from */
  	  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 */
@@ -1393,6 +1405,29 @@ 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;
+
+          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_adl_match (arg_types, nargs, func_name, &symp);
+
+          /* 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)
  	{
  	  int static_memfuncp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
         Then comes another OP_DECFLOAT.  */
      OP_DECFLOAT,

+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
       /* First extension operator.  Individual language modules define
          extra operators they need as constants with values
          OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc
index fad833e..8f3bd98 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.cc
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc
@@ -31,6 +31,27 @@ 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; }
+}
+
+//------------
  int
  main()
  {
@@ -42,5 +63,19 @@ main()
    second(0, 0, c, 0, 0);
    A::first(b.c);

-  return first(0, 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);
+
+  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/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp
index 060c8a5..69df315 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.exp
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp
@@ -57,11 +57,10 @@ gdb_test "p first(0,c)" "= 22"
  # 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"
diff --git a/gdb/valops.c b/gdb/valops.c
index 202dcce..8a804b5 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2021,6 +2021,42 @@ value_find_oload_method_list (struct value **argp, char *method,
  			   basetype, boffset);
  }

+/* Performs an argument defined (Koenig) lookup. */
+void
+find_adl_match (struct type **arg_types, int nargs,char *name,
+               struct symbol **symp)
+{
+  char *type_name;
+  int cindex;
+  int prefix_len;
+  char *concatenated_name;
+  int i;
+  struct symbol *fsym;
+
+  for (i = 1; i <= nargs; i++){
+    type_name = TYPE_NAME (arg_types[i - 1]);
+
+    prefix_len = cp_entire_prefix_len(type_name);
+
+    if( prefix_len != 0){
+
+      concatenated_name = alloca (prefix_len + 2 + strlen (name) + 1);
+      strncpy(concatenated_name, type_name, prefix_len);
+      concatenated_name[prefix_len] = '\0';
+      strcat(concatenated_name, "::");
+      strcat(concatenated_name, name);
+
+      fsym = lookup_symbol(concatenated_name,NULL, VAR_DOMAIN, (int *) NULL);
+
+      if ( fsym &&
+           find_overload_match(arg_types, nargs, name, 0,
+                              0, NULL, fsym,NULL, symp,NULL) == 0)
+        return;
+
+    }
+  }
+}
+
  /* Given an array of argument types (ARGTYPES) (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
diff --git a/gdb/value.h b/gdb/value.h
index aa43365..c37eb4d 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -444,6 +444,9 @@ extern struct fn_field *value_find_oload_method_list (struct value **, char *,
  						      int, int *,
  						      struct type **, int *);

+extern void find_adl_match (struct type **arg_types, int nargs, char *name,
+                           struct symbol **symp);
+
  extern int find_overload_match (struct type **arg_types, int nargs,
  				char *name, int method, int lax,
  				struct value **objp, struct symbol *fsym,


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

* Re: [RFC] Koenig lookup patch 2
  2009-08-27 14:35       ` Sami Wagiaalla
@ 2009-08-27 21:49         ` Tom Tromey
  2009-10-14 20:29           ` [RFC] Koenig lookup patch 3 Sami Wagiaalla
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-08-27 21:49 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Tom> there were
Tom> some formatting issues and whatnot -- these have to be fixed but are
Tom> not very important overall.

This comment still applies.  Please fix the formatting problems.
I can list them if you want.

Tom> With the current code is there a need to have the values here?
Tom> Or could this be reverted to the trunk's approach?

Sami> This was my attempt of making the code a little more compact.

Ah, I see.. thanks.

Tom> Does this really do the right thing in the case where the call has
Tom> multiple arguments, each of which has a type from a different
Tom> namespace?  I don't understand how those would get added to the
Tom> overload set.

Sami> The overload resolution is performed by the remainder of the function
Sami> (find_overloaded_match) this is just to give a starting point. However,
Sami> as you suspected, find_overload_match assumes that all the overload
Sami> choices are within the same namespace. This is corrected in this patch.

I am still not convinced this is correct.

First, I think Koenig lookup looks in the namespaces of all the
"associated" classes of each arguments.  So, if you have an argument of
type one::A which inherits from two::B, I think Koenig lookup should
search both one:: and two::.  I don't see that in this patch.  (I didn't
look this up in the standard, so if I'm wrong about it, feel free to say
so :-)

Sami> +			  /* This could potentially be a an argument dependet

Typo, "dependent".

Sami> +			     lookup function (koenig).  */

Should capitalize Koenig.

Sami> +    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && !is_a_field_of_this)

I think checking is_a_field_of_this is unneeded here.

Sami> +void
Sami> +find_adl_match (struct type **arg_types, int nargs,char *name,
Sami> +               struct symbol **symp)
Sami> +{
[...]
Sami> +  for (i = 1; i <= nargs; i++){
[...]
Sami> +      if ( fsym &&
Sami> +           find_overload_match(arg_types, nargs, name, 0,
Sami> +                              0, NULL, fsym,NULL, symp,NULL) == 0)

I am not sure this is correct either.

My understanding is that in Koenig lookup, all the functions found this
way are put into an overload set which is then subject to overload
resolution rules.  ("Top-level" functions found by ordinary lookup are
also put into this set.)

In this code, I think you are just searching each namespace separately
for the best overload.  This seems like it could yield the wrong answer
in some cases (or at least, yield an answer when in fact the request is
ambiguous).

Tom

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

* Re: [RFC] Koenig lookup patch 3
  2009-08-27 21:49         ` Tom Tromey
@ 2009-10-14 20:29           ` Sami Wagiaalla
  2009-10-14 21:01             ` Sami Wagiaalla
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-10-14 20:29 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer


> Tom> there were
> Tom> some formatting issues and whatnot -- these have to be fixed but are
> Tom> not very important overall.
> 
> This comment still applies.  Please fix the formatting problems.
> I can list them if you want.
> 

Please do. I fixed what I could find, I hope there aren't any any more.

As for comments regarding correctness of the lookup, I have change the 
code to just insert
the extra functions found through ADL into the overload set during the 
search of
the deepest namespace.

This patch does not implement all searches needed to perform complete 
ADL. Here is an
excerpt from the spec with supported functionality marked. I have 
supported the low hanging fruit, and will work on the medium hanging
fruit.

— If T is a fundamental type, its associated sets of namespaces and
   classes are both empty [supported :)].

— If T is a class type (including unions), its associated classes are:
   the class itself [supported]; the class of which it is a member[not
   supported], if any; and its direct and indirect base classes
   [supported]. Its associated namespaces are the namespaces in which its
   associated classes are defined.

— If T is an enumeration type, its associated namespace is the namespace
   in which it is defined [supported]. If it is class member , its
   associated class is the memberÂ’s class [supported]; else it has no
   associated class.

— If T is a pointer to U or an array of U, its associated namespaces and
   classes are those associated with U [supported].

— If T is a function type, its associated namespaces and classes are
   those associated with the function parameter types and those
   associated with the return type [not supported].

— If T is a pointer to a member function of a class X, its associated
   namespaces and classes are those associated with the function
   parameter types and return type, together with those associated with
   X [not supported].

— If T is a pointer to a data member of class X, its associated
   namespaces and classes are those associated with the member type
   together with those associated with X [not supported].

— If T is a class template specialization its associated namespaces and
   classes are the namespace in which the template is defined; for member
   templates, the member templateÂ’s class; the namespaces and classes
   associated with the types of the template arguments provided for
   template type parameters (excluding template template parameters); the
   namespaces in which any template template arguments are defined; and
   the classes in which any member templates used as template template
   arguments are defined. [ Note: non-type template arguments do not
   contribute to the set of associated namespaces. — end note ]
   [not supported :D]




Here is the patch:







2009-10-08  Sami Wagiaalla  <swagiaal@redhat.com>

	* cp-support.c (make_symbol_overload_list_namespace): New function.
	(make_symbol_overload_list_using): Moved namespace checking code to
	make_symbol_overload_list_namespace.
	(make_symbol_overload_list_adl): New function.
	* parse.c (operator_length_standard): Added length information for
	OP_ADL_FUNC.
	* expression.h: Added OP_ADL_FUNC.
	* c-exp.y: Created token UNKOWN_NAME.
	Created grammer rules for UNKOWN_NAME, and adl_function.
	* eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.



diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..d215a9c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);

  %token <sval> STRING
  %token <ssym> NAME /* BLOCKNAME defined below to give it higher 
precedence. */
+%token <ssym> UNKNOWN_NAME
  %token <voidval> COMPLETE
  %token <tsym> TYPENAME
  %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
  			  write_exp_elt_opcode (OP_FUNCALL); }
  	;

+exp	:	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);
+			}
+	;
+
+adl_func	:	UNKNOWN_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);
+			}
+		;
+
  lcurly	:	'{'
  			{ start_arglist (); }
  	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
  			}
  	;

-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
  		{ push_type_address_space (copy_name ($2.stoken));
  		  push_type (tp_space_identifier);
  		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
  	|	BLOCKNAME { $$ = $1.stoken; }
  	|	TYPENAME { $$ = $1.stoken; }
  	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
  	;

  name_not_typename :	NAME
  	|	BLOCKNAME
+	|	UNKNOWN_NAME
  /* These would be useful if name_not_typename was useful, but it is just
     a fake for "variable", so these cause reduce/reduce conflicts because
     the parser can't tell whether NAME_OR_INT is a name_not_typename 
(=variable,
@@ -2016,6 +2043,9 @@ yylex ()
      if (in_parse_field && *lexptr == '\0')
        saw_name_at_eof = 1;

+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL))
+      return UNKNOWN_NAME;
+
      return NAME;
    }
  }
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index bf42636..f69bcd9 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -47,7 +47,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;

@@ -57,6 +57,12 @@ static void overload_list_add_symbol (struct symbol *sym,
  static void make_symbol_overload_list_using (const char *func_name,
  					     const char *namespace);

+static void make_symbol_overload_list_namespace (const char *func_name,
+                                                 const char *namespace);
+
+static void make_symbol_overload_list_adl_namespace (struct type *type,
+                                                     const char 
*func_name);
+
  static void make_symbol_overload_list_qualified (const char *func_name);

  static void read_in_psymtabs (const char *oload_name);
@@ -697,6 +703,59 @@ make_symbol_overload_list (const char *func_name,
    return sym_return_val;
  }

+/* 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;
+}
+
+/* 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;
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR
+      || TYPE_CODE (type) == TYPE_CODE_REF)
+    return make_symbol_overload_list_adl_namespace(TYPE_TARGET_TYPE 
(type), func_name);
+
+  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 );
+      }
+
+}
+
  /* 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
@@ -704,7 +763,7 @@ make_symbol_overload_list (const char *func_name,

  static void
  make_symbol_overload_list_using (const char *func_name,
-				 const char *namespace)
+                                 const char *namespace)
  {
    const struct using_direct *current;

@@ -724,7 +783,16 @@ make_symbol_overload_list_using (const char *func_name,
      }

    /* Now, add names for this namespace.  */
-
+  make_symbol_overload_list_namespace (func_name, namespace);
+}
+
+/* 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);
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 4ce85b5..0e4a378 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -84,6 +84,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 1d35571..bb07c03 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
  	  /* Now, say which argument to start evaluating from */
  	  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 */
@@ -1393,6 +1405,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;
+
+          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 to signal 
ADL lookup */ ,
+                              NULL, &symp, NULL);
+
+          /* Now fix the expression being evaluated */
+          exp->elts[save_pos1+2].symbol = symp;
+          argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, 
noside);
+        }
+
        if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
  	{
  	  int static_memfuncp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
         Then comes another OP_DECFLOAT.  */
      OP_DECFLOAT,

+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
       /* First extension operator.  Individual language modules define
          extra operators they need as constants with values
          OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/namespace-koenig.cc 
b/gdb/testsuite/gdb.cp/namespace-koenig.cc
index fad833e..0c5140a 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.cc
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc
@@ -7,19 +7,19 @@ namespace A
    };

    int
-  first(C c)
+  first (C c)
    {
      return 11;
    }

    int
-  first(int a, C c)
+  first (int a, C c)
    {
      return 22;
    }

    int
-  second(int a, int b, C cc, int c, int d)
+  second (int a, int b, C cc, int c, int d)
    {
      return 33;
    }
@@ -31,16 +31,115 @@ 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;}
+
+}
+//------------
+
  int
-main()
+main ()
  {
    A::C c;
    B b;

-  A::first(c);
-  first(0, c);
-  second(0, 0, c, 0, 0);
-  A::first(b.c);
+  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);

-  return first(0, c);
+  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/namespace-koenig.exp 
b/gdb/testsuite/gdb.cp/namespace-koenig.exp
index 060c8a5..caf432f 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.exp
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp
@@ -57,11 +57,31 @@ gdb_test "p first(0,c)" "= 22"
  # 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)" "No symbol \"foo\" in current context."
+
+#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"

diff --git a/gdb/valops.c b/gdb/valops.c
index 202dcce..ace3fa7 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2108,12 +2108,25 @@ find_overload_match (struct type **arg_types, 
int nargs,
      }
    else
      {
-      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      const char *qualified_name = NULL;

-      /* If we have a C++ name, try to extract just the function
-	 part.  */
-      if (qualified_name)
-	func_name = cp_func_name (qualified_name);
+      if (fsym)
+        {
+          qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+
+          /* If we have a C++ name, try to extract just the function
+             part.  */
+          if (qualified_name)
+            {
+              func_name = cp_func_name (qualified_name);
+              old_cleanups = make_cleanup (xfree, func_name);
+            }
+        }
+      else
+        {
+          func_name = name;
+          qualified_name = name;
+        }

        /* If there was no C++ name, this must be a C-style function.
  	 Just return the same symbol.  Do the same if cp_func_name
@@ -2124,7 +2137,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);

@@ -2135,8 +2147,11 @@ find_overload_match (struct type **arg_types, int 
nargs,
  						&oload_champ_bv);
      }

-  /* 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,
@@ -2302,6 +2317,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 deepesst level perform argument
+     determined lookup.  */
+  if (!searched_deeper)
+      make_symbol_overload_list_adl(arg_types, nargs, func_name);
+
    while (new_oload_syms[num_fns])
      ++num_fns;

@@ -2334,7 +2355,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;

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

* Re: [RFC] Koenig lookup patch 3
  2009-10-14 20:29           ` [RFC] Koenig lookup patch 3 Sami Wagiaalla
@ 2009-10-14 21:01             ` Sami Wagiaalla
  2009-10-15 20:48               ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-10-14 21:01 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

My previous patch was wrapped by my mail agent. Here is a correct one:


2009-10-08  Sami Wagiaalla  <swagiaal@redhat.com>

	* cp-support.c (make_symbol_overload_list_namespace): New function.
	(make_symbol_overload_list_using): Moved namespace checking code to
	make_symbol_overload_list_namespace.
	(make_symbol_overload_list_adl): New function.
	* parse.c (operator_length_standard): Added length information for
	OP_ADL_FUNC.
	* expression.h: Added OP_ADL_FUNC.
	* c-exp.y: Created token UNKOWN_NAME.
	Created grammer rules for UNKOWN_NAME, and adl_function.
	* eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.







diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..d215a9c 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);

  %token <sval> STRING
  %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME
  %token <voidval> COMPLETE
  %token <tsym> TYPENAME
  %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
  			  write_exp_elt_opcode (OP_FUNCALL); }
  	;

+exp	:	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);
+			}
+	;
+
+adl_func	:	UNKNOWN_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);
+			}
+		;
+
  lcurly	:	'{'
  			{ start_arglist (); }
  	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
  			}
  	;

-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
  		{ push_type_address_space (copy_name ($2.stoken));
  		  push_type (tp_space_identifier);
  		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
  	|	BLOCKNAME { $$ = $1.stoken; }
  	|	TYPENAME { $$ = $1.stoken; }
  	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
  	;

  name_not_typename :	NAME
  	|	BLOCKNAME
+	|	UNKNOWN_NAME
  /* These would be useful if name_not_typename was useful, but it is just
     a fake for "variable", so these cause reduce/reduce conflicts because
     the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2043,9 @@ yylex ()
      if (in_parse_field && *lexptr == '\0')
        saw_name_at_eof = 1;

+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL))
+      return UNKNOWN_NAME;
+
      return NAME;
    }
  }
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index bf42636..14af415 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -47,7 +47,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;

@@ -57,6 +57,12 @@ static void overload_list_add_symbol (struct symbol *sym,
  static void make_symbol_overload_list_using (const char *func_name,
  					     const char *namespace);

+static void make_symbol_overload_list_namespace (const char *func_name,
+                                                 const char *namespace);
+
+static void make_symbol_overload_list_adl_namespace (struct type *type,
+                                                     const char *func_name);
+
  static void make_symbol_overload_list_qualified (const char *func_name);

  static void read_in_psymtabs (const char *oload_name);
@@ -697,6 +703,59 @@ make_symbol_overload_list (const char *func_name,
    return sym_return_val;
  }

+/* 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;
+}
+
+/* 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;
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR
+      || TYPE_CODE (type) == TYPE_CODE_REF)
+    return make_symbol_overload_list_adl_namespace(TYPE_TARGET_TYPE (type), func_name);
+
+  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 );
+      }
+
+}
+
  /* 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
@@ -724,7 +783,16 @@ make_symbol_overload_list_using (const char *func_name,
      }

    /* Now, add names for this namespace.  */
-
+  make_symbol_overload_list_namespace (func_name, namespace);
+}
+
+/* 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);
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 4ce85b5..0e4a378 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -84,6 +84,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 1d35571..bb07c03 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
  	  /* Now, say which argument to start evaluating from */
  	  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 */
@@ -1393,6 +1405,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;
+
+          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 to signal ADL lookup */ ,
+                              NULL, &symp, NULL);
+
+          /* Now fix the expression being evaluated */
+          exp->elts[save_pos1+2].symbol = symp;
+          argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
+        }
+
        if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
  	{
  	  int static_memfuncp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..ec8df4d 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
         Then comes another OP_DECFLOAT.  */
      OP_DECFLOAT,

+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (keonig lookup) */
+    OP_ADL_FUNC,
+
       /* First extension operator.  Individual language modules define
          extra operators they need as constants with values
          OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc
index fad833e..0c5140a 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.cc
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc
@@ -7,19 +7,19 @@ namespace A
    };

    int
-  first(C c)
+  first (C c)
    {
      return 11;
    }

    int
-  first(int a, C c)
+  first (int a, C c)
    {
      return 22;
    }

    int
-  second(int a, int b, C cc, int c, int d)
+  second (int a, int b, C cc, int c, int d)
    {
      return 33;
    }
@@ -31,16 +31,115 @@ 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;}
+
+}
+//------------
+
  int
-main()
+main ()
  {
    A::C c;
    B b;

-  A::first(c);
-  first(0, c);
-  second(0, 0, c, 0, 0);
-  A::first(b.c);
+  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);

-  return first(0, c);
+  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/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp
index 060c8a5..caf432f 100644
--- a/gdb/testsuite/gdb.cp/namespace-koenig.exp
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp
@@ -57,11 +57,31 @@ gdb_test "p first(0,c)" "= 22"
  # 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)" "No symbol \"foo\" in current context."
+
+#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"

diff --git a/gdb/valops.c b/gdb/valops.c
index 202dcce..ace3fa7 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2108,12 +2108,25 @@ find_overload_match (struct type **arg_types, int nargs,
      }
    else
      {
-      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      const char *qualified_name = NULL;

-      /* If we have a C++ name, try to extract just the function
-	 part.  */
-      if (qualified_name)
-	func_name = cp_func_name (qualified_name);
+      if (fsym)
+        {
+          qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+
+          /* If we have a C++ name, try to extract just the function
+             part.  */
+          if (qualified_name)
+            {
+              func_name = cp_func_name (qualified_name);
+              old_cleanups = make_cleanup (xfree, func_name);
+            }
+        }
+      else
+        {
+          func_name = name;
+          qualified_name = name;
+        }

        /* If there was no C++ name, this must be a C-style function.
  	 Just return the same symbol.  Do the same if cp_func_name
@@ -2124,7 +2137,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);

@@ -2135,8 +2147,11 @@ find_overload_match (struct type **arg_types, int nargs,
  						&oload_champ_bv);
      }

-  /* 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,
@@ -2302,6 +2317,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 deepesst level perform argument
+     determined lookup.  */
+  if (!searched_deeper)
+      make_symbol_overload_list_adl(arg_types, nargs, func_name);
+
    while (new_oload_syms[num_fns])
      ++num_fns;

@@ -2334,7 +2355,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;

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

* Re: [RFC] Koenig lookup patch 3
  2009-10-14 21:01             ` Sami Wagiaalla
@ 2009-10-15 20:48               ` Tom Tromey
  2009-11-02 19:11                 ` Sami Wagiaalla
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-10-15 20:48 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Sami> My previous patch was wrapped by my mail agent. Here is a correct one:
Sami> 2009-10-08  Sami Wagiaalla  <swagiaal@redhat.com>

Looking much nicer!

Sami> +exp	:	adl_func '('
Sami> +adl_func	:	UNKNOWN_NAME

It seems like these additions would introduce a parser ambiguity,
because UNKNOWN_NAME could be parsed as adl_func or as name_not_typename
(and hence variable).

Is bison silent about this?

Sami> +static void make_symbol_overload_list_namespace (const char *func_name,
Sami> +                                                 const char *namespace);
Sami> +
Sami> +static void make_symbol_overload_list_adl_namespace (struct type *type,
Sami> +                                                     const char *func_name);

GDB does this all over, but in new code we're now preferring that
functions be ordered so that prototypes aren't necessary for static
functions.  This is a bit simpler to maintain.

Sami> +make_symbol_overload_list_adl_namespace (struct type *type, const char *func_name )

Line wraps.  Space before close paren.

Sami> +  char* namespace;
Sami> +  char* type_name;

"char *".

Sami> +    return make_symbol_overload_list_adl_namespace(TYPE_TARGET_TYPE (type), func_name);

Line wraps (?).  Also, space before open paren.  There are several of
these.

Sami> +    case OP_ADL_FUNC:
Sami>      case OP_VAR_VALUE:

I don't understand the placement of the new case here.
How do we ever end up in the new code here, which seems to be in the
OP_FUNCALL case?

Sami> +  /* Check public base type */
Sami> +  if (TYPE_CODE(type) == TYPE_CODE_CLASS)
Sami> +    for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
Sami> +      {
Sami> +        if(BASETYPE_VIA_PUBLIC (type, i))

Why the check for public?

Sami> +          func_name = (char*) alloca (name_len+1);

Spaces around "+".  I think I saw this in more than one place.


Sami> +          find_overload_match (arg_types, nargs, func_name,
Sami> +                              0 /* not method */ , 0 /* strict match */ ,
Sami> +                              NULL, NULL /* pass NULL symbol to signal ADL lookup */ ,

If this is a new convention for the find_overload_match argument, then
it ought to be documented in that function's introductory comment.

Sami> +    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
Sami> +       Argument Dependent manner (keonig lookup) */

Typo, and capitalize "Koenig".

Sami> @@ -2108,12 +2108,25 @@ find_overload_match (struct type **arg_types, int nargs,
Sami> +              old_cleanups = make_cleanup (xfree, func_name);
Sami> -      old_cleanups = make_cleanup (xfree, func_name);
Sami>        make_cleanup (xfree, oload_syms);
Sami>        make_cleanup (xfree, oload_champ_bv);

I think the cleanup logic here is wrong now.
It seems like the code can make a cleanup but still have old_cleanups==NULL.
This will leave dangling cleanups; the usual rule (for functions not
return a cleanup or making one as a side effect) is that local cleanups
must always be run before function exit.

One way to do this would be to initialize old_cleanups as a null cleanup
early on.  Then, never set it elsewhere in the function, and change the
do_cleanups call at the end to be unconditional.  This is a typical
idiom elsewhere in gdb.

Sami> +  if (!searched_deeper)
Sami> +      make_symbol_overload_list_adl(arg_types, nargs, func_name);

Indentation.

I like the new test cases.  I did not go over them extensively, but I
have two points to make.  One is, I think there should probably be some
tests for nested namespaces.  The other is that it would be nice to be
assured that each supported case has a corresponding test; including
tests for things like overload resolution picking the best match both
when the best match is found via ADL and when it is not.

Tom

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

* Re: [RFC] Koenig lookup patch 3
  2009-10-15 20:48               ` Tom Tromey
@ 2009-11-02 19:11                 ` Sami Wagiaalla
  2009-11-09 19:29                   ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-11-02 19:11 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer


> Sami> +exp	:	adl_func '('
> Sami> +adl_func	:	UNKNOWN_NAME
> 
> It seems like these additions would introduce a parser ambiguity,
> because UNKNOWN_NAME could be parsed as adl_func or as name_not_typename
> (and hence variable).
> 
> Is bison silent about this?
> 

Good point. Same goes for everything that is common between name and 
name_no_typename. Anyways I have changed this to:

exp	:	UNKOWN_NAME '('

> Sami> +static void make_symbol_overload_list_namespace (const char *func_name,
> Sami> +                                                 const char *namespace);
> Sami> +
> Sami> +static void make_symbol_overload_list_adl_namespace (struct type *type,
> Sami> +                                                     const char *func_name);
> 
> GDB does this all over, but in new code we're now preferring that
> functions be ordered so that prototypes aren't necessary for static
> functions.  This is a bit simpler to maintain.
> 

Done.

> Sami> +    case OP_ADL_FUNC:
> Sami>      case OP_VAR_VALUE:
> 
> I don't understand the placement of the new case here.
> How do we ever end up in the new code here, which seems to be in the
> OP_FUNCALL case?
> 

After we have used find_overload_match to find a symbol for the 
function. we call evaluate_subexp_with_coercion here:

/* Now fix the expression being evaluated */
exp->elts[save_pos1+2].symbol = symp;
argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);

> Sami> +  /* Check public base type */
> Sami> +  if (TYPE_CODE(type) == TYPE_CODE_CLASS)
> Sami> +    for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
> Sami> +      {
> Sami> +        if(BASETYPE_VIA_PUBLIC (type, i))
> 
> Why the check for public?
> 

I have not seen anything in the spec to require this. But it seems to be 
the case in gcc that the inheritance must be public for the parent 
class(s) to be added to the associated classes set.

> Sami> +          func_name = (char*) alloca (name_len+1);
> 
> Spaces around "+".  I think I saw this in more than one place.
> 
> 
> Sami> +          find_overload_match (arg_types, nargs, func_name,
> Sami> +                              0 /* not method */ , 0 /* strict match */ ,
> Sami> +                              NULL, NULL /* pass NULL symbol to signal ADL lookup */ ,
> 
> If this is a new convention for the find_overload_match argument, then
> it ought to be documented in that function's introductory comment.
> 

That is an outdated comment. In the current code functions found through 
adl are just added overload set whether symbol is null or otherwise.

> Sami> @@ -2108,12 +2108,25 @@ find_overload_match (struct type **arg_types, int nargs,
> Sami> +              old_cleanups = make_cleanup (xfree, func_name);
> Sami> -      old_cleanups = make_cleanup (xfree, func_name);
> Sami>        make_cleanup (xfree, oload_syms);
> Sami>        make_cleanup (xfree, oload_champ_bv);
> 
> I think the cleanup logic here is wrong now.
> It seems like the code can make a cleanup but still have old_cleanups==NULL.
> This will leave dangling cleanups; the usual rule (for functions not
> return a cleanup or making one as a side effect) is that local cleanups
> must always be run before function exit.
> 
> One way to do this would be to initialize old_cleanups as a null cleanup
> early on.  Then, never set it elsewhere in the function, and change the
> do_cleanups call at the end to be unconditional.  This is a typical
> idiom elsewhere in gdb.
> 

Gotcha! Done.

> ... I think there should probably be some
> tests for nested namespaces.

Is this what you mean ?

+namespace L {
+  namespace A{
+    namespace B{
+    class O {};
+
+    int foo (O){
+      return 17;
+    }
+
+    }
+  }
+}
+
...
+#test lookup of objects belonging to nested namespaces
+gdb_test "p foo(labo)" "= 17"

> The other is that it would be nice to be
> assured that each supported case has a corresponding test; 

That's the intention, but if I have missed cases let me know as you have
done last time :)

> tests for things like overload resolution picking the best match both
> when the best match is found via ADL and when it is not.
> 

How is this:

+namespace K{
+  class O{};
+
+  int foo(O, int){
+    return 15;
+  }
+}
+
+int foo(K::O, float){
+  return 16;
+}

...

+#test overload resolution
+gdb_test "p foo(ko,1)" "= 15"
+gdb_test "p foo(ko,1.0f)" "= 16"

The ambiguous case fails but I think that is the case even outside of 
Koenig.


Here is the latest patch:

2009-11-02  Sami Wagiaalla  <swagiaal@redhat.com>

	* cp-support.c (make_symbol_overload_list_namespace): New function.
	(make_symbol_overload_list_using): Moved namespace checking code to
	make_symbol_overload_list_namespace.
	(make_symbol_overload_list_adl): New function.
	* parse.c (operator_length_standard): Added length information for
	OP_ADL_FUNC.
	* expression.h: Added OP_ADL_FUNC.
	* c-exp.y: Created token UNKOWN_NAME.
	Created grammar rules for UNKOWN_NAME.
	* eval.c (evaluate_subexp_standard): Added handling for for OP_ADL_FUNC.

2009-11-02  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdb.cp/namespace-koenig.exp: New test.
	* gdb.cp/namespace-koenig.cc: New test file.

diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 5123042..80e09d4 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,6 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_NAME
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name string_exp
@@ -384,6 +385,30 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
+exp	:	UNKNOWN_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 (); }
 	;
@@ -795,7 +820,7 @@ variable:	name_not_typename
 			}
 	;
 
-space_identifier : '@' NAME
+space_identifier : '@' UNKNOWN_NAME
 		{ push_type_address_space (copy_name ($2.stoken));
 		  push_type (tp_space_identifier);
 		}
@@ -1091,10 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_NAME  { $$ = $1.stoken; }
 	;
 
 name_not_typename :	NAME
 	|	BLOCKNAME
+	|	UNKNOWN_NAME
 /* These would be useful if name_not_typename was useful, but it is just
    a fake for "variable", so these cause reduce/reduce conflicts because
    the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2016,6 +2043,9 @@ yylex ()
     if (in_parse_field && *lexptr == '\0')
       saw_name_at_eof = 1;
         
+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL))
+      return UNKNOWN_NAME;
+
     return NAME;
   }
 }
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index bf42636..b95a450 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -47,7 +47,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;
 
@@ -696,6 +696,82 @@ 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;
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    return make_symbol_overload_list_adl_namespace (TYPE_TARGET_TYPE (type),
+                                                    func_name);
+
+  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
@@ -724,20 +800,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 4ce85b5..0e4a378 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -84,6 +84,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 1d35571..8566414 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -704,6 +704,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)
@@ -1362,6 +1363,17 @@ evaluate_subexp_standard (struct type *expect_type,
 	  /* Now, say which argument to start evaluating from */
 	  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 */
@@ -1393,6 +1405,33 @@ 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);
+
+          /* 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)
 	{
 	  int static_memfuncp;
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 89bae03..fd2e1ce 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -799,6 +799,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 12163e3..4cd8848 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -334,6 +334,10 @@ enum exp_opcode
        Then comes another OP_DECFLOAT.  */
     OP_DECFLOAT,
 
+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (Koenig lookup) */
+    OP_ADL_FUNC,
+
      /* First extension operator.  Individual language modules define
         extra operators they need as constants with values 
         OP_LANGUAGE_SPECIFIC0 + k, for k >= 0, using a separate 
diff --git a/gdb/parse.c b/gdb/parse.c
index eee1f8e..afa6a43 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -811,6 +811,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/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc
new file mode 100644
index 0000000..6c2c01d
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc
@@ -0,0 +1,188 @@
+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;
+    }
+
+    }
+  }
+}
+
+//------------
+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);
+  
+  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/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp
new file mode 100644
index 0000000..616b816
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp
@@ -0,0 +1,95 @@
+# 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 namespace-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"
diff --git a/gdb/valops.c b/gdb/valops.c
index 202dcce..4a1b231 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -2073,7 +2073,7 @@ find_overload_match (struct type **arg_types, int nargs,
   int boffset;
   int ix;
   int static_offset;
-  struct cleanup *old_cleanups = NULL;
+  struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
   const char *obj_type_name = NULL;
   char *func_name = NULL;
@@ -2108,12 +2108,25 @@ find_overload_match (struct type **arg_types, int nargs,
     }
   else
     {
-      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      const char *qualified_name = NULL;
 
-      /* If we have a C++ name, try to extract just the function
-	 part.  */
-      if (qualified_name)
-	func_name = cp_func_name (qualified_name);
+      if (fsym)
+        {
+          qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+
+          /* If we have a C++ name, try to extract just the function
+             part.  */
+          if (qualified_name)
+            {
+              func_name = cp_func_name (qualified_name);
+              make_cleanup (xfree, func_name);
+            }
+        }
+      else
+        {
+          func_name = name;
+          qualified_name = name;
+        }
 
       /* If there was no C++ name, this must be a C-style function.
 	 Just return the same symbol.  Do the same if cp_func_name
@@ -2124,7 +2137,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);
 
@@ -2135,8 +2147,11 @@ find_overload_match (struct type **arg_types, int nargs,
 						&oload_champ_bv);
     }
 
-  /* 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,
@@ -2193,8 +2208,8 @@ find_overload_match (struct type **arg_types, int nargs,
 	}
       *objp = temp;
     }
-  if (old_cleanups != NULL)
-    do_cleanups (old_cleanups);
+
+  do_cleanups (old_cleanups);
 
   switch (match_quality)
     {
@@ -2302,6 +2317,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 deepesst level perform argument
+     determined lookup.  */
+  if (!searched_deeper)
+    make_symbol_overload_list_adl (arg_types, nargs, func_name);
+
   while (new_oload_syms[num_fns])
     ++num_fns;
 
@@ -2334,7 +2355,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;

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

* Re: [RFC] Koenig lookup patch 3
  2009-11-02 19:11                 ` Sami Wagiaalla
@ 2009-11-09 19:29                   ` Tom Tromey
  2009-11-17 16:04                     ` Sami Wagiaalla
  0 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2009-11-09 19:29 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Tom> It seems like these additions would introduce a parser ambiguity,
Tom> because UNKNOWN_NAME could be parsed as adl_func or as name_not_typename
Tom> (and hence variable).

Tom> Is bison silent about this?

Sami> Good point. Same goes for everything that is common between name and
Sami> name_no_typename. Anyways I have changed this to:

It still seems like the new productions are ambiguous, because
UNKNOWN_NAME alone is an `exp'.  If bison doesn't give more warnings
after the patch, though, then I wouldn't worry about it.

Sami> 	* c-exp.y: Created token UNKOWN_NAME.
Sami> 	Created grammar rules for UNKOWN_NAME.

Typo: should be `UNKNOWN'.


Other than that this looks good to me.

I was curious to know what happens when the current language is C, not
C++.  Do we still attempt ADL?

Tom

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

* Re: [RFC] Koenig lookup patch 3
  2009-11-09 19:29                   ` Tom Tromey
@ 2009-11-17 16:04                     ` Sami Wagiaalla
  2009-11-17 20:51                       ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Sami Wagiaalla @ 2009-11-17 16:04 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer


> I was curious to know what happens when the current language is C, not
> C++.  Do we still attempt ADL?
> 

With the previous patch an ADL search would have been attempted and 
failed. What do you think of this solution (applied to the previous patch):


diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 80e09d4..a45133f 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -184,7 +184,7 @@ static int parse_number (char *, int, int, YYSTYPE *);
 
 %token <sval> STRING
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
-%token <ssym> UNKNOWN_NAME
+%token <ssym> UNKNOWN_CPP_NAME
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name string_exp
@@ -385,7 +385,7 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
-exp	:	UNKNOWN_NAME '('
+exp	:	UNKNOWN_CPP_NAME '('
 			{
 
 			 /* This could potentially be a an argument defined
@@ -820,7 +820,7 @@ variable:	name_not_typename
 			}
 	;
 
-space_identifier : '@' UNKNOWN_NAME
+space_identifier : '@' UNKNOWN_CPP_NAME
 		{ push_type_address_space (copy_name ($2.stoken));
 		  push_type (tp_space_identifier);
 		}
@@ -1116,12 +1116,12 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
-	|	UNKNOWN_NAME  { $$ = $1.stoken; }
+	|	UNKNOWN_CPP_NAME  { $$ = $1.stoken; }
 	;
 
 name_not_typename :	NAME
 	|	BLOCKNAME
-	|	UNKNOWN_NAME
+	|	UNKNOWN_CPP_NAME
 /* These would be useful if name_not_typename was useful, but it is just
    a fake for "variable", so these cause reduce/reduce conflicts because
    the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
@@ -2043,8 +2043,8 @@ yylex ()
     if (in_parse_field && *lexptr == '\0')
       saw_name_at_eof = 1;
         
-    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL))
-      return UNKNOWN_NAME;
+    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && parse_language->la_language == language_cplus)
+      return UNKNOWN_CPP_NAME;
 
     return NAME;
   }

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

* Re: [RFC] Koenig lookup patch 3
  2009-11-17 16:04                     ` Sami Wagiaalla
@ 2009-11-17 20:51                       ` Tom Tromey
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2009-11-17 20:51 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: Project Archer

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Sami> +    if (sym == NULL && !lookup_minimal_symbol (tmp, NULL, NULL) && parse_language->la_language == language_cplus)

This wraps.

More importantly, order the conditions so that the slowest one comes last.

Otherwise it seems reasonable to me.

Tom

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

end of thread, other threads:[~2009-11-17 20:51 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-13 19:58 [RFC] Koenig lookup patch Sami Wagiaalla
2009-03-13 22:10 ` Tom Tromey
2009-03-17 18:39   ` Sami Wagiaalla
2009-03-17 21:25     ` Tom Tromey
2009-04-29 15:51   ` [RFC] Koenig lookup patch 2 Sami Wagiaalla
2009-04-30  0:19     ` Tom Tromey
2009-08-27 14:35       ` Sami Wagiaalla
2009-08-27 21:49         ` Tom Tromey
2009-10-14 20:29           ` [RFC] Koenig lookup patch 3 Sami Wagiaalla
2009-10-14 21:01             ` Sami Wagiaalla
2009-10-15 20:48               ` Tom Tromey
2009-11-02 19:11                 ` Sami Wagiaalla
2009-11-09 19:29                   ` Tom Tromey
2009-11-17 16:04                     ` Sami Wagiaalla
2009-11-17 20:51                       ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).