This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
Re: [RFC] Koenig lookup patch 2
- From: Sami Wagiaalla <swagiaal at redhat dot com>
- To: Tom Tromey <tromey at redhat dot com>
- Cc: Project Archer <archer at sourceware dot org>
- Date: Wed, 29 Apr 2009 11:50:41 -0400
- Subject: Re: [RFC] Koenig lookup patch 2
- References: <49BABABE.9080606@redhat.com> <m3d4clrs4z.fsf@fleche.redhat.com>
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);
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);