changeset 27189:946c6f117091

use dummy stack frame when creating meta class (bug #55766 and #55768) * pt-classdef.h (tree_classdef::m_scope): New data member. (tree_classdef::tree_classdef): New arg, SCOPE. * oct-parse.yy (base_parser::make_classdef): Pass current dummy scope to tree_classdef constructor. * cdef_class.cc (cdef_class::make_meta_class): Push dummy stack frame when for expression evaluation while creating meta class object.
author John W. Eaton <jwe@octave.org>
date Sat, 15 Jun 2019 11:04:52 -0500
parents 792fe198c105
children 8ebe70b98e97
files libinterp/octave-value/cdef-class.cc libinterp/parse-tree/oct-parse.yy libinterp/parse-tree/pt-classdef.h
diffstat 3 files changed, 26 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/cdef-class.cc	Fri Jun 14 15:34:44 2019 -0500
+++ b/libinterp/octave-value/cdef-class.cc	Sat Jun 15 11:04:52 2019 -0500
@@ -49,6 +49,7 @@
 #include "pt-misc.h"
 #include "pt-stmt.h"
 #include "pt-walk.h"
+#include "unwind-prot.h"
 
 // Define to 1 to enable debugging statements.
 #define DEBUG_TRACE 0
@@ -861,6 +862,18 @@
     std::cerr << "class: " << full_class_name << std::endl;
 #endif
 
+    // Push a dummy scope frame on the call stack that corresponds to
+    // the scope that was used when parsing classdef object.  Without
+    // this, we may pick up stray values from the current scope when
+    // evaluating expressions found in things like attribute lists.
+
+    unwind_protect frame;
+
+    tree_evaluator& tw = interp.get_evaluator ();
+
+    tw.push_dummy_scope (full_class_name);
+    frame.add_method (tw, &octave::tree_evaluator::pop_scope);
+
     std::list<cdef_class> slist;
 
     if (t->superclass_list ())
@@ -899,8 +912,6 @@
 
     // Class attributes
 
-    tree_evaluator& tw = interp.get_evaluator ();
-
     if (t->attribute_list ())
       {
         for (const auto& attr : (*t->attribute_list ()))
--- a/libinterp/parse-tree/oct-parse.yy	Fri Jun 14 15:34:44 2019 -0500
+++ b/libinterp/parse-tree/oct-parse.yy	Sat Jun 15 11:04:52 2019 -0500
@@ -3624,7 +3624,8 @@
             if (! body)
               body = new tree_classdef_body ();
 
-            retval = new tree_classdef (a, id, sc, body, lc, tc,
+            retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (),
+                                        a, id, sc, body, lc, tc,
                                         m_curr_package_name, l, c);
           }
         else
--- a/libinterp/parse-tree/pt-classdef.h	Fri Jun 14 15:34:44 2019 -0500
+++ b/libinterp/parse-tree/pt-classdef.h	Sat Jun 15 11:04:52 2019 -0500
@@ -727,13 +727,14 @@
   {
   public:
 
-    tree_classdef (tree_classdef_attribute_list *a, tree_identifier *i,
+    tree_classdef (const octave::symbol_scope& scope,
+                   tree_classdef_attribute_list *a, tree_identifier *i,
                    tree_classdef_superclass_list *sc,
                    tree_classdef_body *b, comment_list *lc,
                    comment_list *tc,
                    const std::string& pn = "", int l = -1,
                    int c = -1)
-      : tree_command (l, c), m_attr_list (a), m_id (i),
+      : tree_command (l, c), m_scope (scope), m_attr_list (a), m_id (i),
         m_supclass_list (sc), m_element_list (b), m_lead_comm (lc),
         m_trail_comm (tc), m_pack_name (pn)
     { }
@@ -754,6 +755,8 @@
       delete m_trail_comm;
     }
 
+    octave::symbol_scope scope (void) { return m_scope; }
+
     tree_classdef_attribute_list *
     attribute_list (void) { return m_attr_list; }
 
@@ -779,6 +782,12 @@
 
   private:
 
+    // The scope that was used when parsing the classdef object and that
+    // corresponds to any identifiers that were found in attribute lists
+    // (for example).  Used again when computing the meta class object.
+
+    octave::symbol_scope m_scope;
+
     tree_classdef_attribute_list *m_attr_list;
 
     tree_identifier *m_id;