Add new argument NOSIDE to find_overload_match.
authorSiva Chandra <sivachandra@chromium.org>
Wed, 9 Jul 2014 17:25:48 +0000 (10:25 -0700)
committerSiva Chandra <sivachandra@chromium.org>
Sat, 16 Aug 2014 01:28:59 +0000 (18:28 -0700)
This is a fix for PR c++/17132.
If this new argument is set to EVAL_AVOID_SIDE_EFFECTS, then the object's
memory will not be read while picking the best overload match.

gdb/

* eval.c: Update all calls to find_overload_match.
* valarith.c: Likewise.
(value_user_defined_cpp_op, value_user_defined_op): New
argument NOSIDE.  Update all callers.
* valops.c (find_overload_match): New argument NOSIDE.
* value.h (find_overload_match): Update signature.

gdb/testsuite

* gdb.cp/pr17132.cc: New file.
* gdb.cp/pr17132.exp: New file.

gdb/ChangeLog
gdb/eval.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/pr17132.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/pr17132.exp [new file with mode: 0644]
gdb/valarith.c
gdb/valops.c
gdb/value.h

index 6bcd1c016b6df3114840ad1ca1982ea07245edf1..0c5e3a1d1d833a8d5a1f70a823616639a8ff4d09 100644 (file)
@@ -1,3 +1,13 @@
+2014-08-15  Siva Chandra Reddy  <sivachandra@google.com>
+
+       PR c++/17132
+       * eval.c: Update all calls to find_overload_match.
+       * valarith.c: Likewise.
+       (value_user_defined_cpp_op, value_user_defined_op): New
+       argument NOSIDE.  Update all callers.
+       * valops.c (find_overload_match): New argument NOSIDE.
+       * value.h (find_overload_match): Update signature.
+
 2014-08-15  Siva Chandra Reddy  <sivachandra@google.com>
 
        * python/lib/gdb/command/xmethods.py (set_xm_status1): Use the
index de8e8ecb29bd8fde73430a454ce6a8c41a2f32c7..c3792090fcecfb490aa3c1e9f2919d9f0d4a71ce 100644 (file)
@@ -1563,7 +1563,7 @@ evaluate_subexp_standard (struct type *expect_type,
                                NON_METHOD, /* not method */
                                NULL, NULL, /* pass NULL symbol since
                                              symbol is unknown */
-                               NULL, &symp, NULL, 0);
+                               NULL, &symp, NULL, 0, noside);
 
           /* Now fix the expression being evaluated.  */
           exp->elts[save_pos1 + 2].symbol = symp;
@@ -1599,7 +1599,7 @@ evaluate_subexp_standard (struct type *expect_type,
                                          METHOD, /* method */
                                          &arg2,  /* the object */
                                          NULL, &valp, NULL,
-                                         &static_memfuncp, 0);
+                                         &static_memfuncp, 0, noside);
 
              if (op == OP_SCOPE && !static_memfuncp)
                {
@@ -1670,7 +1670,7 @@ evaluate_subexp_standard (struct type *expect_type,
                                          NULL,        /* no need for name */
                                          NON_METHOD,  /* not method */
                                          NULL, function, /* the function */
-                                         NULL, &symp, NULL, no_adl);
+                                         NULL, &symp, NULL, no_adl, noside);
 
              if (op == OP_VAR_VALUE)
                {
index 38682fa76427634dbe67583e0dce4e2ef1105a04..553f6951681b130c9b38e8c0ee7e0df4dcf1dd8d 100644 (file)
@@ -1,3 +1,9 @@
+2014-08-15  Siva Chandra Reddy  <sivachandra@google.com>
+
+       PR c++/17132
+       * gdb.cp/pr17132.cc: New file.
+       * gdb.cp/pr17132.exp: New file.
+
 2014-08-15  Siva Chandra Reddy  <sivachandra@google.com>
 
        * gdb.python/py-xmethods.py (A_getarrayind)
diff --git a/gdb/testsuite/gdb.cp/pr17132.cc b/gdb/testsuite/gdb.cp/pr17132.cc
new file mode 100644 (file)
index 0000000..42d99af
--- /dev/null
@@ -0,0 +1,61 @@
+/* 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".  */
+
+template <typename T>
+class smart_ptr
+{
+public:
+  smart_ptr (T *obj) : _obj (obj) { }
+  ~smart_ptr () { delete _obj; }
+
+  T *operator-> ();
+
+private:
+  T *_obj;
+};
+
+template <typename T>
+T *
+smart_ptr<T>::operator-> ()
+{
+  return _obj;
+}
+
+class A
+{
+public:
+  virtual int func ();
+};
+
+int
+A::func ()
+{
+  return 3;
+}
+
+int
+main ()
+{
+  A *a_ptr = 0;
+  smart_ptr<A> a (new A);
+
+  return a->func();  /* Break here  */
+}
diff --git a/gdb/testsuite/gdb.cp/pr17132.exp b/gdb/testsuite/gdb.cp/pr17132.exp
new file mode 100644 (file)
index 0000000..26a02a2
--- /dev/null
@@ -0,0 +1,40 @@
+# 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 "ptype a_ptr->func ()" ".* = int" "ptype a_ptr->func ()"
+gdb_test "ptype a->func ()" ".* = int" "ptype a->func ()"
+gdb_test "p sizeof (a_ptr->func()) == sizeof (int)" ".* = true" \
+  "p sizeof (a_ptr->func())"
+gdb_test "p sizeof (a->func()) == sizeof (int)" ".* = true" \
+  "p sizeof (a->func())"
+gdb_test "p 1 && a->func()" ".* = true" "p 1 && a->func()"
+gdb_test "p 0 || a->func()" ".* = true" "p 0 || a->func()"
index d60dedb290855ea4449c34adabdfe9eb88c0657e..44673a112676915a813efd2bdc18aed4ccf3b49f 100644 (file)
@@ -286,7 +286,7 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
 
 static struct value *
 value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
-                           int *static_memfuncp)
+                           int *static_memfuncp, enum noside noside)
 {
 
   struct symbol *symp = NULL;
@@ -295,7 +295,7 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
   find_overload_match (args, nargs, operator, BOTH /* could be method */,
                        &args[0] /* objp */,
                        NULL /* pass NULL symbol since symbol is unknown */,
-                       &valp, &symp, static_memfuncp, 0);
+                       &valp, &symp, static_memfuncp, 0, noside);
 
   if (valp)
     return valp;
@@ -317,12 +317,15 @@ value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
 
 static struct value *
 value_user_defined_op (struct value **argp, struct value **args, char *name,
-                       int *static_memfuncp, int nargs)
+                       int *static_memfuncp, int nargs, enum noside noside)
 {
   struct value *result = NULL;
 
   if (current_language->la_language == language_cplus)
-    result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp);
+    {
+      result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp,
+                                         noside);
+    }
   else
     result = value_struct_elt (argp, args, name, static_memfuncp,
                                "structure");
@@ -471,7 +474,7 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
     }
 
   argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
-                                     &static_memfuncp, 2);
+                                     &static_memfuncp, 2, noside);
 
   if (argvec[0])
     {
@@ -582,7 +585,7 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
     }
 
   argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
-                                     &static_memfuncp, nargs);
+                                     &static_memfuncp, nargs, noside);
 
   if (argvec[0])
     {
index d9ce2f23039d729b38e7d9139c1add5a18486b55..e1decf05fd1cbdd3d880475b9cb5e98f03d1a5c8 100644 (file)
@@ -2449,6 +2449,12 @@ value_find_oload_method_list (struct value **argp, const char *method,
    ADL overload candidates when performing overload resolution for a fully
    qualified name.
 
+   If NOSIDE is EVAL_AVOID_SIDE_EFFECTS, then OBJP's memory cannot be
+   read while picking the best overload match (it may be all zeroes and thus
+   not have a vtable pointer), in which case skip virtual function lookup.
+   This is ok as typically EVAL_AVOID_SIDE_EFFECTS is only used to determine
+   the result type.
+
    Note: This function does *not* check the value of
    overload_resolution.  Caller must check it to see whether overload
    resolution is permitted.  */
@@ -2458,7 +2464,8 @@ find_overload_match (struct value **args, int nargs,
                     const char *name, enum oload_search_type method,
                     struct value **objp, struct symbol *fsym,
                     struct value **valp, struct symbol **symp, 
-                    int *staticp, const int no_adl)
+                    int *staticp, const int no_adl,
+                    const enum noside noside)
 {
   struct value *obj = (objp ? *objp : NULL);
   struct type *obj_type = obj ? value_type (obj) : NULL;
@@ -2764,9 +2771,13 @@ find_overload_match (struct value **args, int nargs,
     {
       if (src_method_oload_champ >= 0)
        {
-         if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
-           *valp = value_virtual_fn_field (&temp, fns_ptr, method_oload_champ,
-                                           basetype, boffset);
+         if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ)
+             && noside != EVAL_AVOID_SIDE_EFFECTS)
+           {
+             *valp = value_virtual_fn_field (&temp, fns_ptr,
+                                             method_oload_champ, basetype,
+                                             boffset);
+           }
          else
            *valp = value_fn_field (&temp, fns_ptr, method_oload_champ,
                                    basetype, boffset);
index 46540423c44353cb09056f94456edba37ff69b64..843478b4766f206f104cb7a3b12e2f7839ec1820 100644 (file)
@@ -693,7 +693,8 @@ extern int find_overload_match (struct value **args, int nargs,
                                enum oload_search_type method,
                                struct value **objp, struct symbol *fsym,
                                struct value **valp, struct symbol **symp,
-                               int *staticp, const int no_adl);
+                               int *staticp, const int no_adl,
+                               enum noside noside);
 
 extern struct value *value_field (struct value *arg1, int fieldno);