From patchwork Mon Dec 1 08:32:05 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siva Chandra Reddy X-Patchwork-Id: 4020 Received: (qmail 31407 invoked by alias); 1 Dec 2014 08:32:10 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 31396 invoked by uid 89); 1 Dec 2014 08:32:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mail-ob0-f173.google.com Received: from mail-ob0-f173.google.com (HELO mail-ob0-f173.google.com) (209.85.214.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 01 Dec 2014 08:32:07 +0000 Received: by mail-ob0-f173.google.com with SMTP id uy5so7546284obc.4 for ; Mon, 01 Dec 2014 00:32:05 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:content-type; bh=yO4333v+tPAkcDJif9hxL6FC3xSdDLSdN4g1JPb83Cc=; b=B8NefKuPbop5iHvkbey09RDWLvyO5EcZz3xg48EryFnvOcqWO/W+6CAWqlaMaJoBny W/3c48Ss2X4PiU8SmGLStWmLRu3lbr0RU+bP5Axm4LXD9dmvff1VvZ1PcuDpHx5QKBxF rrgyDb1X3ihX6rMAw2i5YC3NrriBE5Jzq2+Hovvz0qkkEGcttVKBeElnlSWBBrd7ODiz q1lRRAeMKFVTSdV5tLC8OKBFynmqyVSkDlZl5ilIz0ISJdInt0Kx4thDO1GkUlqbK3oh L6m930Vy/QnzTEJZOiCiwIZFnM3HNJTTZtmavJgmynK0c3QEgzXfK9WD+D5al/eQEcBE yjHw== X-Gm-Message-State: ALoCoQmYVltKOoQOlqwtznLM1m5MJpCWUDT6OSgb0mOhfvbfiKpl0Lsi+Koo3H76zJmpbmHgmPxg MIME-Version: 1.0 X-Received: by 10.202.55.86 with SMTP id e83mr6688084oia.112.1417422725801; Mon, 01 Dec 2014 00:32:05 -0800 (PST) Received: by 10.202.225.68 with HTTP; Mon, 1 Dec 2014 00:32:05 -0800 (PST) In-Reply-To: References: Date: Mon, 1 Dec 2014 00:32:05 -0800 Message-ID: Subject: Re: [PATCH] Enable invoking overloaded operator() method on class and union values. From: Siva Chandra To: gdb-patches X-IsSubscribed: yes On Thu, Nov 20, 2014 at 8:56 AM, Siva Chandra wrote: > Hello, > > The attached patch enables invoking overloaded operator() method on > class and union values when evaluating expressions. > > gdb/ChangeLog: > > 2014-11-20 Siva Chandra Reddy > > * eval.c (evaluate_subexp_standard): Extend handling of > OP_FUNCALL operation to enable invoking overloaded > operator() methods. > > gdb/testsuite/ChangeLog: > > 2014-11-20 Siva Chandra Reddy > > * gdb.cp/member-ptr.exp: Modify expected pattern of > "print diamond.*diamond_pfunc_ptr (20)" and > "print diamond.*left_vpmf ()". > * gdb.cp/paren-op.cc: New file. > * gdb.cp/paren-op.exp: New file. > > Regression tested on x86_64 GNU/Linux. > > Thank you, > Siva Chandra Ping. Rebased patch is attached. diff --git a/gdb/eval.c b/gdb/eval.c index c2ab879..fb9ed75 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -707,6 +707,7 @@ evaluate_subexp_standard (struct type *expect_type, struct type *type; int nargs; struct value **argvec; + struct type *callable_type = NULL; int code; int ix; long mem_offset; @@ -1524,21 +1525,48 @@ evaluate_subexp_standard (struct type *expect_type, } else { - /* Non-method function call. */ + /* It could either be a normal function call, or an overloaded + operator() call. */ + struct value *callable_value; + int fptr = 0, struct_or_union = 0, internal_func = 0; save_pos1 = *pos; tem = 1; - /* If this is a C++ function wait until overload resolution. */ - if (op == OP_VAR_VALUE - && overload_resolution - && (exp->language_defn->la_language == language_cplus)) + callable_value = evaluate_subexp_with_coercion (exp, pos, noside); + callable_type = check_typedef (value_type (callable_value)); + if (TYPE_CODE (callable_type) == TYPE_CODE_PTR) { - (*pos) += 4; /* Skip the evaluation of the symbol. */ + callable_type = check_typedef (TYPE_TARGET_TYPE (callable_type)); + if (TYPE_CODE (callable_type) != TYPE_CODE_FUNC) + error (_("Operand to '()' operator is not a callable.")); + fptr = 1; + } + else if (exp->language_defn->la_language == language_cplus + && class_or_union_p (callable_type)) + struct_or_union = 1; /* There could be an operator() method. */ + else if (TYPE_CODE (callable_type) == TYPE_CODE_INTERNAL_FUNCTION) + internal_func = 1; + else if (TYPE_CODE (callable_type) == TYPE_CODE_FUNC) + ; /* Normal function call. */ + else + error (_("Operand to '()' operator is not a callable.")); + + /* If this is C++, wait until overload resolution. */ + if (!fptr && !internal_func + && exp->language_defn->la_language == language_cplus + && (overload_resolution || struct_or_union)) + { + if (struct_or_union) + { + arg2 = value_addr (callable_value); + nargs++; + tem = 2; + } argvec[0] = NULL; } else { - argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside); + argvec[0] = callable_value; type = value_type (argvec[0]); if (type && TYPE_CODE (type) == TYPE_CODE_PTR) type = TYPE_TARGET_TYPE (type); @@ -1593,10 +1621,11 @@ evaluate_subexp_standard (struct type *expect_type, } if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR - || (op == OP_SCOPE && function_name != NULL)) + || (op == OP_SCOPE && function_name != NULL) + || (callable_type != NULL && class_or_union_p (callable_type))) { int static_memfuncp; - char *tstr; + const char *tstr; /* Method invocation: stuff "this" as first parameter. If the method turns out to be static we undo this below. */ @@ -1604,8 +1633,13 @@ evaluate_subexp_standard (struct type *expect_type, if (op != OP_SCOPE) { - /* Name of method from expression. */ - tstr = &exp->elts[pc2 + 2].string; + if (callable_type == NULL) + { + /* Name of method from expression. */ + tstr = &exp->elts[pc2 + 2].string; + } + else + tstr = "operator()"; } else tstr = function_name; diff --git a/gdb/testsuite/gdb.cp/member-ptr.exp b/gdb/testsuite/gdb.cp/member-ptr.exp index c13b852..649fe89 100644 --- a/gdb/testsuite/gdb.cp/member-ptr.exp +++ b/gdb/testsuite/gdb.cp/member-ptr.exp @@ -389,7 +389,7 @@ gdb_test "ptype diamond.*diamond_pfunc_ptr" \ # call the member pointer as a normal pointer-to-function. gdb_test "print diamond.*diamond_pfunc_ptr (20)" \ - "Invalid data type for function to be called." + "Operand to '\\(\\)' operator is not a callable\\." # With parentheses, it is valid. @@ -665,7 +665,7 @@ gdb_test "print base_vpmf" \ # Make sure we parse this correctly; it's invalid. gdb_test "print diamond.*left_vpmf ()" \ - "Invalid data type for function to be called\\." + "Operand to '\\(\\)' operator is not a callable\\." # NULL pointer to member tests. gdb_test "print null_pmi" "$vhn = NULL" diff --git a/gdb/testsuite/gdb.cp/paren-op.cc b/gdb/testsuite/gdb.cp/paren-op.cc new file mode 100644 index 0000000..89a085a --- /dev/null +++ b/gdb/testsuite/gdb.cp/paren-op.cc @@ -0,0 +1,60 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +struct S +{ + int operator() (int x); +}; + +int +S::operator() (int x) +{ + return x + 5; +} + +int +s (int a, int b) +{ + return a + b; +} + +int (*s1_ptr) (int, int) = &s; + +int +s (int a) +{ + return a * a; +} + +union U +{ + int operator () (int x); +}; + +int +U::operator() (int x) +{ + return x + 10; +} + +int main () { + S s; + U u; + int i = 10; + + return 0; /* Break here */ +} diff --git a/gdb/testsuite/gdb.cp/paren-op.exp b/gdb/testsuite/gdb.cp/paren-op.exp new file mode 100644 index 0000000..152b8c9 --- /dev/null +++ b/gdb/testsuite/gdb.cp/paren-op.exp @@ -0,0 +1,37 @@ +# Copyright 2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite + +if {[skip_cplus_tests]} { continue } + +standard_testfile .cc + +if {[prepare_for_testing $testfile.exp $testfile $srcfile \ + {debug c++ additional_flags=-std=c++11}]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +gdb_breakpoint [gdb_get_line_number "Break here"] +gdb_continue_to_breakpoint "Break here" + +gdb_test "p s(12340)" ".* = 12345" "p s()" +gdb_test "p u(446)" ".* = 456" "p u()" +gdb_test "p i(789)" "Operand to '\\(\\)' operator is not a callable\\." "p i()" +gdb_test "p s1_ptr(500, 67)" ".* = 567" "p s1_ptr()"