changeset 26924:ab9520ef3895

ensure classdef dtor doesn't wipe out expression value (bug #53844, bug #55758) * pt-eval.cc (tree_evaluator::visit_index_expression): Delete any temporary values from intermediate expression evaluations prior to pushing final result value(s). * test/bug-55758/bug-55758.tst, test/bug-55758/class_bug_55758.m, test/bug-55758/module.mk: New files.
author John W. Eaton <jwe@octave.org>
date Fri, 15 Mar 2019 17:26:12 +0000
parents c81b471cdb28
children 7fdbb03d5f76
files libinterp/parse-tree/pt-eval.cc test/bug-55758/bug-55758.tst test/bug-55758/class_bug_55758.m test/bug-55758/module.mk test/module.mk
diffstat 5 files changed, 64 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/parse-tree/pt-eval.cc	Fri Mar 15 10:37:21 2019 -0700
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Mar 15 17:26:12 2019 +0000
@@ -2257,6 +2257,12 @@
                   {
                     // No more indices, so we are done.
 
+                    // See note at end of function about deleting
+                    // temporaries prior to pushing result.
+
+                    base_expr_val = octave_value ();
+                    first_args = octave_value_list ();
+
                     push_result (retval);
                     return;
                   }
@@ -2444,6 +2450,19 @@
           }
       }
 
+    // Delete any temporary values prior to pushing the result and
+    // returning so that destructors for any temporary classdef handle
+    // objects will be called before we return.  Otherwise, the
+    // destructor may push result values that will wipe out the result
+    // that we push below.  Although the method name is "push_result"
+    // there is only a single register (either an octave_value or an
+    // octave_value_list) not a stack.
+
+    idx.clear ();
+    partial_expr_val = octave_value ();
+    base_expr_val = octave_value ();
+    val = octave_value ();
+
     push_result (retval);
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/bug-55758.tst	Fri Mar 15 17:26:12 2019 +0000
@@ -0,0 +1,16 @@
+%!test
+%! global class_bug_55758_dtor_called
+%! class_bug_55758_dtor_called = false;
+%!
+%! assert (class_bug_55758 (5).value, 5);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (class_bug_55758 (5)(1), 5);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (size (class_bug_55758 (5)), [1, 1]);
+%! assert (class_bug_55758_dtor_called);
+%!
+%! assert (numel (class_bug_55758 (5)), 1);
+%! assert (class_bug_55758_dtor_called);
+%! clear -global class_bug_55758_dtor_called;  # cleanup after test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/class_bug_55758.m	Fri Mar 15 17:26:12 2019 +0000
@@ -0,0 +1,23 @@
+classdef class_bug_55758 < handle
+  properties
+    value
+  endproperties
+
+  methods
+    function self = class_bug_55758 (val)
+      if (nargin < 1)
+        val = 0;
+      endif
+      self.value = val;
+    endfunction
+
+    function delete (self)
+      global class_bug_55758_dtor_called;
+      class_bug_55758_dtor_called = true;
+    endfunction
+
+    function ret = subsref (self, idx)
+      ret = self.value;
+    endfunction
+  endmethods
+endclassdef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-55758/module.mk	Fri Mar 15 17:26:12 2019 +0000
@@ -0,0 +1,5 @@
+bug_55758_TEST_FILES = \
+  %reldir%/bug-55758.tst \
+  %reldir%/class_bug_55758.m
+
+TEST_FILES += $(bug_55758_TEST_FILES)
--- a/test/module.mk	Fri Mar 15 10:37:21 2019 -0700
+++ b/test/module.mk	Fri Mar 15 17:26:12 2019 +0000
@@ -78,6 +78,7 @@
 include %reldir%/bug-53027/module.mk
 include %reldir%/bug-53468/module.mk
 include %reldir%/bug-54995/module.mk
+include %reldir%/bug-55758/module.mk
 include %reldir%/class-concat/module.mk
 include %reldir%/classdef/module.mk
 include %reldir%/classdef-multiple-inheritance/module.mk