From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31657 invoked by alias); 18 Feb 2010 19:45:55 -0000 Mailing-List: contact archer-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: List-Id: Received: (qmail 31648 invoked by uid 22791); 18 Feb 2010 19:45:54 -0000 X-SWARE-Spam-Status: No, hits=-6.8 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Message-ID: <4B7D9890.1070607@redhat.com> Date: Thu, 18 Feb 2010 19:45:00 -0000 From: Sami Wagiaalla User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7) Gecko/20100120 Fedora/3.0.1-1.fc12 Thunderbird/3.0.1 MIME-Version: 1.0 To: Tom Tromey , Project Archer Subject: Re: [rfc] patch for pr8880 References: <4B703D65.302@redhat.com> <4B71B645.2050806@redhat.com> In-Reply-To: Content-Type: multipart/mixed; boundary="------------060407080705050204060000" X-SW-Source: 2010-q1/txt/msg00080.txt.bz2 This is a multi-part message in MIME format. --------------060407080705050204060000 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 6438 On 02/09/2010 06:35 PM, Tom Tromey wrote: > Tom> Why not just use value_ind? > > Sami> value_ind works. I just missed it :) > > Totally understandable, the value API is over-large. > > Sami> I could put this code in a function to be called from value_x_binop > Sami> and value_x_unop. That would at least avoid the awkward argument > Sami> counting but not earlier than that since the arguments need to have > Sami> been evaluated and/or add a check for la_language == language_cplus. > > I think that sounds ok. > Done! I learned that one can catch the exception to prevent value_struct_elt from exiting, attempt the ADL search then deliver the patch if that fails. > Tom> Also, ADL should only be done for unqualified names. > Tom> It isn't clear to me that this change satisfies that requirement. > > Sami> Let me look into this. It might be a general problem I don't think gdb > Sami> ever differentiates between qualified and unqualified names > > I was looking into this area a little bit recently. > > c-exp.y does sometimes differentiate the cases; it will emit an OP_SCOPE > in the qualified case. I think we do mishandle either "::name" or > "::name::name" here, in the sense that these aren't distinguished from a > name without a leading "::". (ADL also should be avoided for something > like obj->method(), but from what I remember your changes handled ok.) > Is it correct to assume then that qualified names should be treated through evaluation of OP_SCOPE and is not effected by this patch - baring lexer/parser bugs. Especially since the patch is now restricted to user defined operators. diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc index 6c2c01d..3c30cb2 100644 --- a/gdb/testsuite/gdb.cp/namespace-koenig.cc +++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc @@ -129,6 +129,42 @@ namespace L { } //------------ + +namespace M { + class O{ + public: + int operator== (int){ + return 18; + } + + int operator== (float){ + return 19; + } + + int operator+ (float){ + return 22; + } + + }; + + int operator!= (O, int){ + return 20; + } + + int operator!= (O, double){ + return 21; + } + + int operator+ (O, int){ + return 23; + } + + int operator++ (O){ + return 24; + } + +} +//------------ int main () { @@ -180,7 +216,15 @@ main () L::A::B::O labo; foo (labo); - + + M::O o; + o == 5; + o == 5.0f; + o != 5; + o != 5.0f; + o + 5; + o + 5.0f; + return first (0, c) + foo (eo) + foo (eo, eo) + foo (eo, eo, 1) + foo (fo, eo) + foo (1 ,fo, eo) + diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp index 616b816..c73e239 100644 --- a/gdb/testsuite/gdb.cp/namespace-koenig.exp +++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp @@ -93,3 +93,20 @@ gdb_test "p bar(ko,1)" "= -1" #test lookup of objects belonging to nested namespaces gdb_test "p foo(labo)" "= 17" + +# test lookup of namespace user-defined operators +# and overload resolution: + +# within class +gdb_test "p o == 5" "= 18" +gdb_test "p o == 5.0f" "= 19" + +# within namespace +gdb_test "p o != 5" "= 20" +gdb_test "p o != 5.0f" "= 21" + +# across namespace and class +gdb_test "p o + 5.0f" "= 22" +gdb_test "p o + 5" "= 23" + +gdb_test "p o++" "= 24" diff --git a/gdb/valarith.c b/gdb/valarith.c index ed76b09..c672a5b 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -31,6 +31,7 @@ #include "dfp.h" #include #include "infcall.h" +#include "exceptions.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ @@ -298,6 +299,62 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1) } } +struct value * +value_user_defined_adl_op (struct value **args, int nargs, char *operator) +{ + + struct symbol *symp; + struct type **arg_types; + int i; + + /* This function, if found, will not be a member function + and does not expect a pointer as its first argument + rather the explicit structure. */ + args[0] = value_ind (args[0]); + + arg_types = (struct type **)alloca (nargs * (sizeof (struct type *))); + /* Prepare list of argument types for overload resolution */ + for (i = 0; i < nargs; i++) + arg_types [i] = value_type (args [i]); + + find_overload_match (arg_types, nargs, operator, 0 /* not method */, + 0 /* strict match */, NULL, + NULL /* pass NULL symbol since symbol is unknown */, + NULL, &symp, NULL); + + if (symp) + return value_of_variable (symp, 0); + + return NULL; +} + +struct value * +value_user_defined_op (struct value **argp, struct value **args, char *name, + int *static_memfuncp, int nargs) +{ + struct value *result = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + result = value_struct_elt (argp, args, name, static_memfuncp, + "structure"); + } + + if (except.reason < 0) + { + + if (current_language->la_language == language_cplus) + /* Try ADL. */ + result = value_user_defined_adl_op (args, nargs, name); + + if (!result) + error ("%s", except.message); + } + + return result; +} + /* We know either arg1 or arg2 is a structure, so try to find the right user defined function. Create an argument vector that calls arg1.operator @ (arg1,arg2) and return that value (where '@' is any @@ -438,7 +495,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op, error (_("Invalid binary operation specified.")); } - argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure"); + argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr, + &static_memfuncp, 2); if (argvec[0]) { @@ -535,7 +593,8 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside) error (_("Invalid unary operation specified.")); } - argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure"); + argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr, + &static_memfuncp, 1); if (argvec[0]) { --------------060407080705050204060000 Content-Type: text/plain; name="patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="patch" Content-length: 4779 diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc index 6c2c01d..3c30cb2 100644 --- a/gdb/testsuite/gdb.cp/namespace-koenig.cc +++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc @@ -129,6 +129,42 @@ namespace L { } //------------ + +namespace M { + class O{ + public: + int operator== (int){ + return 18; + } + + int operator== (float){ + return 19; + } + + int operator+ (float){ + return 22; + } + + }; + + int operator!= (O, int){ + return 20; + } + + int operator!= (O, double){ + return 21; + } + + int operator+ (O, int){ + return 23; + } + + int operator++ (O){ + return 24; + } + +} +//------------ int main () { @@ -180,7 +216,15 @@ main () L::A::B::O labo; foo (labo); - + + M::O o; + o == 5; + o == 5.0f; + o != 5; + o != 5.0f; + o + 5; + o + 5.0f; + return first (0, c) + foo (eo) + foo (eo, eo) + foo (eo, eo, 1) + foo (fo, eo) + foo (1 ,fo, eo) + diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp index 616b816..c73e239 100644 --- a/gdb/testsuite/gdb.cp/namespace-koenig.exp +++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp @@ -93,3 +93,20 @@ gdb_test "p bar(ko,1)" "= -1" #test lookup of objects belonging to nested namespaces gdb_test "p foo(labo)" "= 17" + +# test lookup of namespace user-defined operators +# and overload resolution: + +# within class +gdb_test "p o == 5" "= 18" +gdb_test "p o == 5.0f" "= 19" + +# within namespace +gdb_test "p o != 5" "= 20" +gdb_test "p o != 5.0f" "= 21" + +# across namespace and class +gdb_test "p o + 5.0f" "= 22" +gdb_test "p o + 5" "= 23" + +gdb_test "p o++" "= 24" diff --git a/gdb/valarith.c b/gdb/valarith.c index ed76b09..c672a5b 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -31,6 +31,7 @@ #include "dfp.h" #include #include "infcall.h" +#include "exceptions.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ @@ -298,6 +299,62 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1) } } +struct value * +value_user_defined_adl_op (struct value **args, int nargs, char *operator) +{ + + struct symbol *symp; + struct type **arg_types; + int i; + + /* This function, if found, will not be a member function + and does not expect a pointer as its first argument + rather the explicit structure. */ + args[0] = value_ind (args[0]); + + arg_types = (struct type **)alloca (nargs * (sizeof (struct type *))); + /* Prepare list of argument types for overload resolution */ + for (i = 0; i < nargs; i++) + arg_types [i] = value_type (args [i]); + + find_overload_match (arg_types, nargs, operator, 0 /* not method */, + 0 /* strict match */, NULL, + NULL /* pass NULL symbol since symbol is unknown */, + NULL, &symp, NULL); + + if (symp) + return value_of_variable (symp, 0); + + return NULL; +} + +struct value * +value_user_defined_op (struct value **argp, struct value **args, char *name, + int *static_memfuncp, int nargs) +{ + struct value *result = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + result = value_struct_elt (argp, args, name, static_memfuncp, + "structure"); + } + + if (except.reason < 0) + { + + if (current_language->la_language == language_cplus) + /* Try ADL. */ + result = value_user_defined_adl_op (args, nargs, name); + + if (!result) + error ("%s", except.message); + } + + return result; +} + /* We know either arg1 or arg2 is a structure, so try to find the right user defined function. Create an argument vector that calls arg1.operator @ (arg1,arg2) and return that value (where '@' is any @@ -438,7 +495,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op, error (_("Invalid binary operation specified.")); } - argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure"); + argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr, + &static_memfuncp, 2); if (argvec[0]) { @@ -535,7 +593,8 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside) error (_("Invalid unary operation specified.")); } - argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure"); + argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr, + &static_memfuncp, 1); if (argvec[0]) { --------------060407080705050204060000--