Fix evaluation of method calls under EVAL_SKIP.
authorSiva Chandra <sivachandra@chromium.org>
Sat, 18 Oct 2014 13:14:00 +0000 (06:14 -0700)
committerSiva Chandra <sivachandra@chromium.org>
Tue, 4 Nov 2014 02:01:39 +0000 (18:01 -0800)
When evaluating method calls under EVAL_SKIP, the "object" and the
arguments to the method should also be evaluated under EVAL_SKIP,
instead of skipping to evaluate them as was being done previously.

gdb/ChangeLog:

PR c++/17494
* eval.c (evaluate_subexp_standard): Evaluate the "object" and
the method args also under EVAL_SKIP when evaluating method
calls under EVAL_SKIP.

gdb/testsuite/ChangeLog:

PR c++/17494
* gdb.cp/pr17494.cc: New file.
* gdb.cp/pr17494.exp: New file.

gdb/ChangeLog
gdb/eval.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/pr17494.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/pr17494.exp [new file with mode: 0644]

index 928efef..5f13708 100644 (file)
@@ -1,3 +1,10 @@
+2014-11-03  Siva Chandra Reddy  <sivachandra@google.com>
+
+       PR c++/17494
+       * eval.c (evaluate_subexp_standard): Evaluate the "object" and
+       the method args also under EVAL_SKIP when evaluating method
+       calls under EVAL_SKIP.
+
 2014-11-02  Victor Kamensky  <victor.kamensky@linaro.org>
 
        * dwarf2loc.c (read_pieced_value): Do big endian
index 5906744..ab431c6 100644 (file)
@@ -1332,9 +1332,6 @@ evaluate_subexp_standard (struct type *expect_type,
          /* First, evaluate the structure into arg2.  */
          pc2 = (*pos)++;
 
-         if (noside == EVAL_SKIP)
-           goto nosideret;
-
          if (op == STRUCTOP_MEMBER)
            {
              arg2 = evaluate_subexp_for_address (exp, pos, noside);
@@ -1353,7 +1350,10 @@ evaluate_subexp_standard (struct type *expect_type,
          arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
          type = check_typedef (value_type (arg1));
-         if (TYPE_CODE (type) == TYPE_CODE_METHODPTR)
+         if (noside == EVAL_SKIP)
+           tem = 1;  /* Set it to the right arg index so that all arguments
+                        can also be skipped.  */
+         else if (TYPE_CODE (type) == TYPE_CODE_METHODPTR)
            {
              if (noside == EVAL_AVOID_SIDE_EFFECTS)
                arg1 = value_zero (TYPE_TARGET_TYPE (type), not_lval);
@@ -1396,8 +1396,6 @@ evaluate_subexp_standard (struct type *expect_type,
          pc2 = (*pos)++;
          tem2 = longest_to_int (exp->elts[pc2 + 1].longconst);
          *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1);
-         if (noside == EVAL_SKIP)
-           goto nosideret;
 
          if (op == STRUCTOP_STRUCT)
            {
@@ -1546,6 +1544,9 @@ evaluate_subexp_standard (struct type *expect_type,
       /* Signal end of arglist.  */
       argvec[tem] = 0;
 
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+
       if (op == OP_ADL_FUNC)
         {
           struct symbol *symp;
index 2aff9de..7983271 100644 (file)
@@ -1,3 +1,9 @@
+2014-11-03  Siva Chandra Reddy  <sivachandra@google.com>
+
+       PR c++/17494
+       * gdb.cp/pr17494.cc: New file.
+       * gdb.cp/pr17494.exp: New file.
+
 2014-11-02  Yao Qi  <yao@codesourcery.com>
 
        * gdb.python/python.exp: Get working directory and match the
diff --git a/gdb/testsuite/gdb.cp/pr17494.cc b/gdb/testsuite/gdb.cp/pr17494.cc
new file mode 100644 (file)
index 0000000..77653e1
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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 <http://www.gnu.org/licenses/>.  */
+
+
+/* One could use unique_ptr instead, but that requires a GCC which can
+   support "-std=c++11".  */
+
+int
+func (int i, int j)
+{
+  return i + j;
+}
+
+class A
+{
+public:
+  A () { a = 12345; f = &func; }
+  int geta ();
+  int adda (int i);
+
+  int a;
+  int (*f) (int, int);
+};
+
+int
+A::geta ()
+{
+  return a;
+}
+
+int
+A::adda (int i)
+{
+  return a + i;
+}
+
+int
+main ()
+{
+  A a;
+  A *a_ptr = &a;
+  int (A::*m1) ();
+  int (A::*m2) (int);
+
+  m1 = &A::geta;
+  m2 = &A::adda;
+
+  return (a.*m1) () + (a.*m2) (12) + (a.*(&A::f)) (1, 2);  /* Break here  */
+}
diff --git a/gdb/testsuite/gdb.cp/pr17494.exp b/gdb/testsuite/gdb.cp/pr17494.exp
new file mode 100644 (file)
index 0000000..7f2e0cf
--- /dev/null
@@ -0,0 +1,57 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+# 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++}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "Break here"]
+gdb_continue_to_breakpoint "Break here"
+
+gdb_test "p a.geta()" ".* = 12345" "a.geta()"
+gdb_test "p a_ptr->geta()" ".* = 12345" "a.geta()"
+
+gdb_test "p false ? a.geta() : 123" ".* = 123" "ternop 1"
+gdb_test "p false ? a_ptr->geta() : 123" ".* = 123" "ternop 2"
+gdb_test "p (true ? 123 : a.geta()) + 123" ".* = 246" "ternop 3"
+gdb_test "p (true ? 123 : a_ptr->geta()) + 123" ".* = 246" "ternop 4"
+gdb_test "p false ? (a.*m1)() : 123" ".* = 123" "ternop 5"
+gdb_test "p false ? (a_ptr->*m1)() : 123" ".* = 123" "ternop 6"
+gdb_test "p (true ? 123 : (a.*m1)()) + 123" ".* = 246" "ternop 7"
+gdb_test "p (true ? 123 : (a_ptr->*m1)()) + 123" ".* = 246" "ternop 8"
+
+gdb_test "p false ? a.adda(456) : 123" ".* = 123" "ternop 9"
+gdb_test "p false ? a_ptr->adda(456) : 123" ".* = 123" "ternop 10"
+gdb_test "p (true ? 123 : a.adda(456)) + 123" ".* = 246" "ternop 11"
+gdb_test "p (true ? 123 : a_ptr->adda(456)) + 123" ".* = 246" "ternop 12"
+gdb_test "p false ? (a.*m2)(123) : 123" ".* = 123" "ternop 13"
+gdb_test "p false ? (a_ptr->*m2)(123) : 123" ".* = 123" "ternop 14"
+gdb_test "p (true ? 123 : (a.*m2)(123)) + 123" ".* = 246" "ternop 15"
+gdb_test "p (true ? 123 : (a_ptr->*m2)(123)) + 123" ".* = 246" "ternop 16"
+
+gdb_test "p false ? (a.*(&A::f))(1, 2) : 123" ".* = 123" "ternop 17"
+gdb_test "p false ? (a_ptr->*(&A::f))(1, 2) : 123" ".* = 123" "ternop 18"
+gdb_test "p (true ? 123 : (a.*(&A::f))(1, 2)) + 123" ".* = 246" "ternop 19"
+gdb_test "p (true ? 123 : (a_ptr->*(&A::f))(1, 2)) + 123" ".* = 246" "ternop 20"