From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19351 invoked by alias); 27 Aug 2009 14:35:01 -0000 Mailing-List: contact archer-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: List-Id: Received: (qmail 19332 invoked by uid 22791); 27 Aug 2009 14:34:58 -0000 X-SWARE-Spam-Status: No, hits=1.0 required=5.0 tests=BAYES_00,J_CHICKENPOX_26,J_CHICKENPOX_31,J_CHICKENPOX_32,J_CHICKENPOX_33,J_CHICKENPOX_44,J_CHICKENPOX_54,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Message-ID: <4A969900.6040100@redhat.com> Date: Thu, 27 Aug 2009 14:35:00 -0000 From: Sami Wagiaalla User-Agent: Thunderbird 2.0.0.17 (X11/20081009) MIME-Version: 1.0 To: Tom Tromey CC: Project Archer Subject: Re: [RFC] Koenig lookup patch 2 References: <49BABABE.9080606@redhat.com> <49F87751.8050405@redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2009-q3/txt/msg00157.txt.bz2 Tom Tromey wrote: >>>>>> "Sami" == Sami Wagiaalla 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 * 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 STRING %token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token UNKNOWN_NAME %token COMPLETE %token TYPENAME %type 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,