This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Koenig lookup patch


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

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