public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
From: Sami Wagiaalla <swagiaal@redhat.com>
To: Project Archer <archer@sourceware.org>
Subject: [RFC] Koenig lookup patch
Date: Fri, 13 Mar 2009 19:58:00 -0000	[thread overview]
Message-ID: <49BABABE.9080606@redhat.com> (raw)

[-- 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:

             reply	other threads:[~2009-03-13 19:58 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-13 19:58 Sami Wagiaalla [this message]
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

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=49BABABE.9080606@redhat.com \
    --to=swagiaal@redhat.com \
    --cc=archer@sourceware.org \
    /path/to/YOUR_REPLY

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

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