changeset 24361:8bcfddad15ec

use shared_ptr to manage symbol_scope objects * symscope.h, symscope.cc (symbol_scope_rep): New class, renamed and adapted from symbol_scope. (symbol_scope): New class to manage symbol_scope_rep with shared_ptr. Change all uses of pointers ot symbol_scope objects to be symbol_scope objects or, in a few cases, pointers to symbol_scope_rep objects instead.
author John W. Eaton <jwe@octave.org>
date Mon, 27 Nov 2017 01:12:05 -0500
parents ff4717c3223f
children 3fc24b792a24
files libgui/src/main-window.cc libgui/src/workspace-view.cc libinterp/corefcn/call-stack.cc libinterp/corefcn/call-stack.h libinterp/corefcn/error.cc libinterp/corefcn/fcn-info.cc libinterp/corefcn/help.cc libinterp/corefcn/interpreter-private.cc libinterp/corefcn/interpreter-private.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/load-path.cc libinterp/corefcn/load-save.cc libinterp/corefcn/ls-mat5.cc libinterp/corefcn/mex.cc libinterp/corefcn/octave-link.cc libinterp/corefcn/symrec.cc libinterp/corefcn/symrec.h libinterp/corefcn/symscope.cc libinterp/corefcn/symscope.h libinterp/corefcn/symtab.cc libinterp/corefcn/symtab.h libinterp/corefcn/variables.cc libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-fcn-inline.cc libinterp/octave-value/ov-fcn.h libinterp/octave-value/ov-usr-fcn.cc libinterp/octave-value/ov-usr-fcn.h libinterp/parse-tree/lex.h libinterp/parse-tree/lex.ll libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/parse.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h libinterp/parse-tree/pt-fcn-handle.cc libinterp/parse-tree/pt-fcn-handle.h libinterp/parse-tree/pt-id.cc libinterp/parse-tree/pt-id.h libinterp/parse-tree/pt-jit.cc libinterp/parse-tree/pt-jit.h
diffstat 41 files changed, 806 insertions(+), 426 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libgui/src/main-window.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -2528,24 +2528,24 @@
 {
   Fload (ovl (file));
 
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
    = octave::__get_current_scope__ ("main_window::load_workspace_callback");
 
   if (scope)
-    octave_link::set_workspace (true, scope->workspace_info ());
+    octave_link::set_workspace (true, scope.workspace_info ());
 }
 
 void
 main_window::rename_variable_callback (const main_window::name_pair& names)
 {
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
     = octave::__get_current_scope__ ("main_window::rename_variable_callback");
 
   if (scope)
     {
-      scope->rename (names.first, names.second);
-
-      octave_link::set_workspace (true, scope->workspace_info ());
+      scope.rename (names.first, names.second);
+
+      octave_link::set_workspace (true, scope.workspace_info ());
     }
 
   // FIXME: if this action fails, do we need a way to display that info
@@ -2704,11 +2704,11 @@
 void
 main_window::force_refresh_workspace (void)
 {
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
    = octave::__get_current_scope__ ("main_window::load_workspace_callback");
 
   if (scope)
-    octave_link::set_workspace (true, scope->workspace_info (), false);
+    octave_link::set_workspace (true, scope.workspace_info (), false);
 }
 
 QList<octave_dock_widget *>
--- a/libgui/src/workspace-view.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libgui/src/workspace-view.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -411,10 +411,10 @@
     {
       QString var_name = get_var_name (index);
 
-      octave::symbol_scope *scope
+      octave::symbol_scope scope
         = octave::__get_current_scope__ ("workspace_view::handle_contextmenu_copy_value");
 
-      octave_value val = scope ? scope->varval (var_name.toStdString ()) : 0;
+      octave_value val = scope ? scope.varval (var_name.toStdString ()) : 0;
       std::ostringstream buf;
       val.print_raw (buf, true);
 
--- a/libinterp/corefcn/call-stack.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/call-stack.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -360,7 +360,7 @@
   }
 
   void
-  call_stack::push (octave_function *fcn, symbol_scope *scope,
+  call_stack::push (octave_function *fcn, const symbol_scope& scope,
                     symbol_table::context_id context)
   {
     size_t prev_frame = curr_frame;
@@ -394,7 +394,7 @@
                         << " at line " << elt.m_line
                         << " column " << elt.m_column
                         << " [" << elt.fcn_file_name () << "] "
-                        << " (scope = " << elt.m_scope
+                        << " (scope = " << elt.m_scope.get_rep_ptr ()
                         << "[context = " << elt.m_context << "])"
                         << std::endl;
       }
@@ -585,7 +585,7 @@
 
     for (const auto& frm : frames)
       {
-        scope(k)   = frm.m_scope;
+        scope(k)   = frm.m_scope.get_rep_ptr ();
         context(k) = frm.m_context;
         file(k)    = frm.fcn_file_name ();
         name(k)    = frm.fcn_name (print_subfn);
--- a/libinterp/corefcn/call-stack.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/call-stack.h	Mon Nov 27 01:12:05 2017 -0500
@@ -52,7 +52,7 @@
       friend class call_stack;
 
       stack_frame (octave_function *fcn = nullptr,
-                   symbol_scope *scope = nullptr,
+                   const symbol_scope& scope = symbol_scope (),
                    symbol_table::context_id context = 0, size_t prev = 0)
         : m_fcn (fcn), m_line (-1), m_column (-1), m_scope (scope),
           m_context (context), m_prev (prev)
@@ -78,7 +78,7 @@
       octave_function *m_fcn;
       int m_line;
       int m_column;
-      symbol_scope *m_scope;
+      symbol_scope m_scope;
       symbol_table::context_id m_context;
       size_t m_prev;
     };
@@ -124,10 +124,10 @@
 
     size_t num_user_code_frames (octave_idx_type& curr_user_frame) const;
 
-    symbol_scope *current_scope (void) const
+    symbol_scope current_scope (void) const
     {
       return (curr_frame > 0 && curr_frame < cs.size ()
-              ? cs[curr_frame].m_scope : nullptr);
+              ? cs[curr_frame].m_scope : symbol_scope ());
     }
 
     symbol_table::context_id current_context (void) const
@@ -173,7 +173,7 @@
     bool all_scripts (void) const;
 
     void push (octave_function *fcn);
-    void push (octave_function *fcn, symbol_scope *scope,
+    void push (octave_function *fcn, const symbol_scope& scope,
                symbol_table::context_id context);
 
     void push (void)
@@ -181,7 +181,7 @@
       push (nullptr);
     }
 
-    void push (symbol_scope *scope, symbol_table::context_id context)
+    void push (const symbol_scope& scope, symbol_table::context_id context)
     {
       push (nullptr, scope, context);
     }
--- a/libinterp/corefcn/error.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/error.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -1568,7 +1568,7 @@
           if (nargin == 3 && argv[3] == "local"
               && ! symtab.at_top_level ())
             {
-              octave::symbol_scope *scope
+              octave::symbol_scope scope
                 = symtab.require_current_scope ("warning");
 
               octave_scalar_map val = warning_query (arg2);
@@ -1578,7 +1578,7 @@
               // FIXME: this might be better with a dictionary object.
 
               octave_value curr_warning_states
-                = scope->varval (".saved_warning_states.");
+                = scope.varval (".saved_warning_states.");
 
               octave_map m;
 
@@ -1626,7 +1626,7 @@
               m.contents ("identifier") = ids;
               m.contents ("state") = states;
 
-              scope->force_assign (".saved_warning_states.", m);
+              scope.force_assign (".saved_warning_states.", m);
 
               // Now ignore the "local" argument and continue to
               // handle the current setting.
--- a/libinterp/corefcn/fcn-info.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/fcn-info.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -374,11 +374,11 @@
   {
     if (local_funcs)
       {
-        symbol_scope *curr_scope
+        symbol_scope curr_scope
           = __get_current_scope__ ("fcn_info::fcn_info_rep::xfind");
 
         octave_user_function *current_fcn
-          = curr_scope ? curr_scope->function () : nullptr;
+          = curr_scope ? curr_scope.function () : nullptr;
 
         // Local function.
 
@@ -393,10 +393,10 @@
             if (current_fcn->is_anonymous_function ())
               {
                 if (fcn_file.empty ()
-                    && curr_scope->parent_scope () != nullptr
-                    && curr_scope->parent_scope ()->function () != nullptr)
+                    && curr_scope.parent_scope ()
+                    && curr_scope.parent_scope ()->function () != nullptr)
                   fcn_file
-                    = curr_scope->parent_scope ()->function ()->fcn_file_name();
+                    = curr_scope.parent_scope ()->function ()->fcn_file_name();
               }
 
             if (! fcn_file.empty ())
@@ -592,10 +592,10 @@
 
     // Private function.
 
-    symbol_scope *curr_scope
+    symbol_scope curr_scope
       = __get_current_scope__ ("fcn_info::fcn_info_rep::x_builtin_find");
 
-    octave_user_function *current_fcn = curr_scope ? curr_scope->function () : nullptr;
+    octave_user_function *current_fcn = curr_scope ? curr_scope.function () : nullptr;
 
     if (current_fcn)
       {
@@ -659,7 +659,7 @@
 
     if (curr_scope)
       {
-        octave_value val = curr_scope->find_subfunction (name);
+        octave_value val = curr_scope.find_subfunction (name);
 
         if (val.is_defined ())
           return val;
--- a/libinterp/corefcn/help.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/help.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -494,8 +494,8 @@
     // All subfunctions are listed in the top-level function of this file.
     while (curr_fcn->is_subfunction ())
       {
-        symbol_scope *pscope = curr_fcn->parent_fcn_scope ();
-        curr_fcn = pscope->function ();
+        symbol_scope pscope = curr_fcn->parent_fcn_scope ();
+        curr_fcn = pscope.function ();
       }
 
     // Get subfunctions.
--- a/libinterp/corefcn/interpreter-private.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/interpreter-private.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -79,16 +79,16 @@
     return interp.get_symbol_table ();
   }
 
-  symbol_scope *__get_current_scope__ (const std::string& who)
+  symbol_scope __get_current_scope__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
 
     return interp.get_current_scope ();
   }
 
-  symbol_scope *__require_current_scope__ (const std::string& who)
+  symbol_scope __require_current_scope__ (const std::string& who)
   {
-    symbol_scope *scope = __get_current_scope__ (who);
+    symbol_scope scope = __get_current_scope__ (who);
 
     if (! scope)
       error ("%s: symbol table scope missing", who.c_str ());
--- a/libinterp/corefcn/interpreter-private.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/interpreter-private.h	Mon Nov 27 01:12:05 2017 -0500
@@ -51,10 +51,9 @@
 
   extern symbol_table& __get_symbol_table__ (const std::string& who);
 
-  extern symbol_scope *__get_current_scope__ (const std::string& who);
+  extern symbol_scope __get_current_scope__ (const std::string& who);
 
-  extern symbol_scope *
-  __require_current_scope__ (const std::string& who);
+  extern symbol_scope __require_current_scope__ (const std::string& who);
 
   extern tree_evaluator& __get_evaluator__ (const std::string& who);
 
--- a/libinterp/corefcn/interpreter.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/interpreter.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -539,12 +539,12 @@
   void interpreter::intern_nargin (octave_idx_type nargs)
   {
     // FIXME: should this explicitly be top_scope?
-    symbol_scope *scope = m_symbol_table.current_scope ();
+    symbol_scope scope = m_symbol_table.current_scope ();
 
     if (scope)
       {
-        scope->assign (".nargin.", nargs);
-        scope->mark_hidden (".nargin.");
+        scope.assign (".nargin.", nargs);
+        scope.mark_hidden (".nargin.");
       }
   }
 
@@ -1177,16 +1177,16 @@
     return m_url_handle_manager;
   }
 
-  symbol_scope *
+  symbol_scope
   interpreter::get_current_scope (void)
   {
     return m_symbol_table.current_scope ();
   }
 
-  symbol_scope *
+  symbol_scope
   interpreter::require_current_scope (const std::string& who)
   {
-    symbol_scope *scope = get_current_scope ();
+    symbol_scope scope = get_current_scope ();
 
     if (! scope)
       error ("%s: symbol table scope missing", who.c_str ());
--- a/libinterp/corefcn/interpreter.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/interpreter.h	Mon Nov 27 01:12:05 2017 -0500
@@ -167,8 +167,8 @@
       return m_symbol_table;
     }
 
-    symbol_scope * get_current_scope (void);
-    symbol_scope * require_current_scope (const std::string& who);
+    symbol_scope get_current_scope (void);
+    symbol_scope require_current_scope (const std::string& who);
 
     call_stack& get_call_stack (void);
 
--- a/libinterp/corefcn/load-path.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/load-path.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -121,9 +121,9 @@
   // Look in private directory corresponding to current function (if
   // any).
 
-  octave::symbol_scope *scope = octave::__get_current_scope__ ("find_private_file");
-
-  octave_user_function *curr_fcn = scope ? scope->function () : nullptr;
+  octave::symbol_scope scope = octave::__get_current_scope__ ("find_private_file");
+
+  octave_user_function *curr_fcn = scope ? scope.function () : nullptr;
 
   if (curr_fcn)
     {
--- a/libinterp/corefcn/load-save.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/load-save.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -148,17 +148,17 @@
   octave::symbol_table& symtab
     = octave::__get_symbol_table__ ("install_loaded_variable");
 
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
     = symtab.require_current_scope ("install_loaded_variable");
 
   if (global)
     {
-      scope->clear_variable (name);
-      scope->mark_global (name);
+      scope.clear_variable (name);
+      scope.mark_global (name);
       symtab.global_assign (name, val);
     }
   else
-    scope->assign (name, val);
+    scope.assign (name, val);
 }
 
 // Return TRUE if NAME matches one of the given globbing PATTERNS.
@@ -1010,11 +1010,11 @@
 save_vars (std::ostream& os, const std::string& pattern,
            load_save_format fmt, bool save_as_floats)
 {
-  octave::symbol_scope *scope = octave::__require_current_scope__ ("save_vars");
+  octave::symbol_scope scope = octave::__require_current_scope__ ("save_vars");
 
-  octave::symbol_record::context_id context = scope->current_context ();
+  octave::symbol_record::context_id context = scope.current_context ();
 
-  std::list<octave::symbol_record> vars = scope->glob (pattern);
+  std::list<octave::symbol_record> vars = scope.glob (pattern);
 
   size_t saved = 0;
 
@@ -1281,16 +1281,16 @@
 
       std::string struct_name = argv[argv_idx];
 
-      octave::symbol_scope *scope = octave::__get_current_scope__ ("save_vars");
+      octave::symbol_scope scope = octave::__get_current_scope__ ("save_vars");
 
       octave_value struct_var;
 
       if (scope)
         {
-          if (! scope->is_variable (struct_name))
+          if (! scope.is_variable (struct_name))
             error ("save: no such variable: '%s'", struct_name.c_str ());
 
-          struct_var = scope->varval (struct_name);
+          struct_var = scope.varval (struct_name);
         }
 
       if (! struct_var.isstruct () || struct_var.numel () != 1)
@@ -1335,11 +1335,11 @@
 
   octave::symbol_table& symtab = octave::__get_symbol_table__ ("dump_octave_core");
 
-  octave::symbol_scope *top_scope = symtab.top_scope ();
+  octave::symbol_scope top_scope = symtab.top_scope ();
 
-  octave::symbol_record::context_id context = top_scope->current_context ();
+  octave::symbol_record::context_id context = top_scope.current_context ();
 
-  std::list<octave::symbol_record> vars = top_scope->all_variables ();
+  std::list<octave::symbol_record> vars = top_scope.all_variables ();
 
   double save_mem_size = 0;
 
--- a/libinterp/corefcn/ls-mat5.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/ls-mat5.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -978,11 +978,11 @@
 
             octave::symbol_scope local_scope;
 
-            symtab.set_scope (&local_scope);
+            symtab.set_scope (local_scope);
 
             octave::call_stack& cs
               = octave::__get_call_stack__ ("read_mat5_binary_element");
-            cs.push (&local_scope, 0);
+            cs.push (local_scope, 0);
             frame.add_method (cs, &octave::call_stack::pop);
 
             if (m2.nfields () > 0)
--- a/libinterp/corefcn/mex.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/mex.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -3476,10 +3476,10 @@
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          octave::symbol_scope *scope
+          octave::symbol_scope scope
             = octave::__require_current_scope__ ("mexGetVariable");
 
-          val = scope->varval (name);
+          val = scope.varval (name);
         }
       else
         mexErrMsgTxt ("mexGetVariable: symbol table does not exist");
@@ -3547,10 +3547,10 @@
               frame.add_method (cs, &octave::call_stack::pop);
             }
 
-          octave::symbol_scope *scope
+          octave::symbol_scope scope
             = octave::__require_current_scope__ ("mexPutVariable");
 
-          scope->assign (name, mxArray::as_octave_value (ptr));
+          scope.assign (name, mxArray::as_octave_value (ptr));
         }
       else
         mexErrMsgTxt ("mexPutVariable: symbol table does not exist");
--- a/libinterp/corefcn/octave-link.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/octave-link.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -71,9 +71,9 @@
         = octave::__get_symbol_table__ ("octave_link::set_workspace");
 
       std::list<workspace_element> workspace_info;
-      octave::symbol_scope *scope = symtab.current_scope ();
+      octave::symbol_scope scope = symtab.current_scope ();
       if (scope)
-        workspace_info = scope->workspace_info ();
+        workspace_info = scope.workspace_info ();
 
       instance->do_set_workspace (symtab.at_top_level (),
                                   instance->debugging, workspace_info);
--- a/libinterp/corefcn/symrec.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symrec.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -60,7 +60,7 @@
   }
 
   symbol_record::symbol_record_rep *
-  symbol_record::symbol_record_rep::dup (symbol_scope *new_scope) const
+  symbol_record::symbol_record_rep::dup (symbol_scope_rep *new_scope) const
   {
     // FIXME: is this the right thing do to?
     if (auto t_fwd_rep = m_fwd_rep.lock ())
--- a/libinterp/corefcn/symrec.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symrec.h	Mon Nov 27 01:12:05 2017 -0500
@@ -38,7 +38,7 @@
 
 namespace octave
 {
-  class symbol_scope;
+  class symbol_scope_rep;
 
   class symbol_record
   {
@@ -78,8 +78,8 @@
     {
     public:
 
-      symbol_record_rep (const std::string& nm,
-                         const octave_value& v, unsigned int sc)
+      symbol_record_rep (const std::string& nm, const octave_value& v,
+                         unsigned int sc)
         : m_storage_class (sc), m_name (nm), m_fwd_scope (nullptr),
           m_fwd_rep (), m_value_stack (), m_valid (true)
       {
@@ -492,7 +492,7 @@
         m_valid = false;
       }
 
-      void bind_fwd_rep (symbol_scope *fwd_scope,
+      void bind_fwd_rep (symbol_scope_rep *fwd_scope,
                          const std::shared_ptr<symbol_record_rep>& fwd_rep)
       {
         if (auto t_fwd_rep = m_fwd_rep.lock ())
@@ -517,7 +517,7 @@
         m_fwd_rep.reset ();
       }
 
-      symbol_record_rep * dup (symbol_scope *new_scope) const;
+      symbol_record_rep * dup (symbol_scope_rep *new_scope) const;
 
       octave_value dump (context_id context) const;
 
@@ -531,7 +531,7 @@
 
       std::string m_name;
 
-      symbol_scope *m_fwd_scope;
+      symbol_scope_rep *m_fwd_scope;
 
       std::weak_ptr<symbol_record_rep> m_fwd_rep;
 
@@ -554,7 +554,7 @@
 
     ~symbol_record (void) = default;
 
-    symbol_record dup (symbol_scope *sid) const
+    symbol_record dup (symbol_scope_rep *sid) const
     {
       return symbol_record (m_rep->dup (sid));
     }
@@ -662,7 +662,7 @@
 
     unsigned int storage_class (void) const { return m_rep->storage_class (); }
 
-    void bind_fwd_rep (symbol_scope *fwd_scope, const symbol_record& sr)
+    void bind_fwd_rep (symbol_scope_rep *fwd_scope, const symbol_record& sr)
     {
       m_rep->bind_fwd_rep (fwd_scope, sr.m_rep);
     }
--- a/libinterp/corefcn/symscope.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symscope.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -40,13 +40,14 @@
 namespace octave
 {
   octave_value
-  symbol_scope::find (const std::string& name, const octave_value_list& args,
-                      bool skip_variables, bool local_funcs)
+  symbol_scope_rep::find (const std::string& name,
+                          const octave_value_list& args,
+                          bool skip_variables, bool local_funcs)
   {
     // Variable.
 
     symbol_table& symtab
-      = __get_symbol_table__ ("symbol_scope::find");
+      = __get_symbol_table__ ("symbol_scope_rep::find");
 
     if (! skip_variables)
       {
@@ -84,7 +85,7 @@
   }
 
   symbol_record&
-  symbol_scope::insert (const std::string& name, bool force_add)
+  symbol_scope_rep::insert (const std::string& name, bool force_add)
   {
     table_iterator p = m_symbols.find (name);
 
@@ -107,7 +108,7 @@
   }
 
   std::list<workspace_element>
-  symbol_scope::workspace_info (void) const
+  symbol_scope_rep::workspace_info (void) const
   {
     std::list<workspace_element> retval;
 
@@ -161,7 +162,7 @@
   }
 
   octave_value
-  symbol_scope::dump (void) const
+  symbol_scope_rep::dump (void) const
   {
     std::map<std::string, octave_value> m
       = {{ "name", m_name },
@@ -172,7 +173,7 @@
   }
 
   octave_value
-  symbol_scope::dump_symbols_map (void) const
+  symbol_scope_rep::dump_symbols_map (void) const
   {
     std::map<std::string, octave_value> info_map;
 
@@ -187,8 +188,9 @@
   }
 
   void
-  symbol_scope::install_subfunction (const std::string& name,
-                                     const octave_value& fval, bool is_nested)
+  symbol_scope_rep::install_subfunction (const std::string& name,
+                                         const octave_value& fval,
+                                         bool is_nested)
   {
     m_subfunctions[name] = fval;
 
@@ -196,9 +198,9 @@
     // object...
     octave_user_function *fcn = fval.user_function_value ();
 
-    symbol_scope *fcn_scope = fcn->scope ();
+    symbol_scope fcn_scope = fcn->scope ();
 
-    fcn_scope->set_parent (this);
+    fcn_scope.set_parent (this);
 
     if (is_nested)
       {
@@ -206,13 +208,12 @@
 
         fcn->mark_as_nested_function ();
 
-        fcn_scope->m_is_nested = true;
+        fcn_scope.mark_nested ();
       }
-
   }
 
   octave_value
-  symbol_scope::find_subfunction (const std::string& name) const
+  symbol_scope_rep::find_subfunction (const std::string& name) const
   {
     subfunctions_const_iterator p = m_subfunctions.find (name);
 
@@ -226,7 +227,7 @@
   }
 
   void
-  symbol_scope::mark_subfunctions_in_scope_as_private (const std::string& class_name)
+  symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
   {
     for (auto& nm_sf : m_subfunctions)
       {
@@ -238,7 +239,7 @@
   }
 
   void
-  symbol_scope::set_parent (symbol_scope *p)
+  symbol_scope_rep::set_parent (symbol_scope_rep *p)
   {
     m_parent = p;
 
@@ -260,7 +261,7 @@
   }
 
   void
-  symbol_scope::update_nest (void)
+  symbol_scope_rep::update_nest (void)
   {
     if (m_parent)
       {
@@ -286,12 +287,13 @@
         m_is_static = true;
       }
 
-    for (auto& symtab_p : m_children)
-      symtab_p->update_nest ();
+    for (auto& scope_obj : m_children)
+      scope_obj.update_nest ();
   }
 
   bool
-  symbol_scope::look_nonlocal (const std::string& name, symbol_record& result)
+  symbol_scope_rep::look_nonlocal (const std::string& name,
+                                   symbol_record& result)
   {
     table_iterator p = m_symbols.find (name);
     if (p == m_symbols.end ())
@@ -309,7 +311,7 @@
   }
 
   void
-  symbol_scope::bind_script_symbols (symbol_scope *curr_scope)
+  symbol_scope_rep::bind_script_symbols (symbol_scope_rep *curr_scope)
   {
     for (auto& nm_sr : m_symbols)
       nm_sr.second.bind_fwd_rep (curr_scope,
@@ -317,7 +319,7 @@
   }
 
   void
-  symbol_scope::unbind_script_symbols (void)
+  symbol_scope_rep::unbind_script_symbols (void)
   {
     for (auto& nm_sr : m_symbols)
       nm_sr.second.unbind_fwd_rep ();
--- a/libinterp/corefcn/symscope.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symscope.h	Mon Nov 27 01:12:05 2017 -0500
@@ -30,6 +30,7 @@
 #include <limits>
 #include <list>
 #include <map>
+#include <memory>
 #include <set>
 #include <string>
 
@@ -47,7 +48,9 @@
 
 namespace octave
 {
-  class symbol_scope
+  class symbol_scope;
+
+  class symbol_scope_rep
   {
   public:
 
@@ -63,7 +66,7 @@
     typedef std::map<std::string, octave_value>::iterator
     subfunctions_iterator;
 
-    symbol_scope (const std::string& name = "")
+    symbol_scope_rep (const std::string& name = "")
       : m_name (name), m_symbols (), m_subfunctions (),
         m_fcn (nullptr), m_parent (nullptr), m_parent_fcn (),
         m_children (), m_is_nested (false),
@@ -72,11 +75,11 @@
 
     // No copying!
 
-    symbol_scope (const symbol_scope&) = delete;
+    symbol_scope_rep (const symbol_scope&) = delete;
 
-    symbol_scope& operator = (const symbol_scope&) = delete;
+    symbol_scope_rep& operator = (const symbol_scope&) = delete;
 
-    ~symbol_scope (void) = default;
+    ~symbol_scope_rep (void) = default;
 
     void insert_symbol_record (const symbol_record& sr)
     {
@@ -91,12 +94,13 @@
 
     void mark_static (void) { m_is_static = true; }
 
-    symbol_scope * parent_scope (void) const { return m_parent; }
+    symbol_scope_rep * parent_scope_rep (void) const { return m_parent; }
+
     octave_value parent_fcn (void) const { return m_parent_fcn; }
 
-    symbol_scope * dup (void) const
+    symbol_scope_rep * dup (void) const
     {
-      symbol_scope *new_sid = new symbol_scope (m_name);
+      symbol_scope_rep *new_sid = new symbol_scope_rep (m_name);
 
       for (const auto& nm_sr : m_symbols)
         new_sid->insert_symbol_record (nm_sr.second.dup (new_sid));
@@ -121,7 +125,7 @@
         return p->second;
     }
 
-    void inherit_internal (symbol_scope& donor_scope)
+    void inherit_internal (symbol_scope_rep& donor_scope_rep)
     {
       for (auto& nm_sr : m_symbols)
         {
@@ -133,7 +137,7 @@
 
               if (nm != "__retval__")
                 {
-                  octave_value val = donor_scope.varval (nm);
+                  octave_value val = donor_scope_rep.varval (nm);
 
                   if (val.is_defined ())
                     {
@@ -146,20 +150,19 @@
         }
     }
 
-    void inherit (symbol_scope *donor_scope)
+    void inherit (symbol_scope_rep *donor_scope_rep)
     {
-      while (donor_scope)
+      while (donor_scope_rep)
         {
-          inherit_internal (*donor_scope);
+          inherit_internal (*donor_scope_rep);
 
-          if (donor_scope->is_nested ())
-            donor_scope = donor_scope->parent_scope ();
+          if (donor_scope_rep->is_nested ())
+            donor_scope_rep = parent_scope_rep ();
           else
             break;
         }
     }
 
-
     octave_value
     find (const std::string& name, const octave_value_list& args,
           bool skip_variables, bool local_funcs);
@@ -465,7 +468,7 @@
         nm_sf.second.unlock ();
     }
 
-    std::map<std::string, octave_value> subfunctions (void)
+    std::map<std::string, octave_value> subfunctions (void) const
     {
       return m_subfunctions;
     }
@@ -504,16 +507,18 @@
 
     void set_function (octave_user_function *fcn) { m_fcn = fcn; }
 
-    void set_parent (symbol_scope *p);
+    void set_parent (symbol_scope_rep *p);
 
     void update_nest (void);
 
     bool look_nonlocal (const std::string& name, symbol_record& result);
 
-    void bind_script_symbols (symbol_scope *curr_scope);
+    void bind_script_symbols (symbol_scope_rep *curr_scope);
 
     void unbind_script_symbols (void);
 
+    octave_value dump_symbols_map (void) const;
+
   private:
 
     // Name for this scope (usually the corresponding filename of the
@@ -534,11 +539,11 @@
     octave_user_function *m_fcn;
 
     // Parent of nested function (may be null).
-    symbol_scope *m_parent;
+    symbol_scope_rep *m_parent;
     octave_value m_parent_fcn;
 
     // Child nested functions.
-    std::vector<symbol_scope*> m_children;
+    std::vector<symbol_scope> m_children;
 
     // If true, then this scope belongs to a nested function.
     bool m_is_nested;
@@ -547,8 +552,393 @@
     bool m_is_static;
 
     context_id m_context;
+  };
 
-    octave_value dump_symbols_map (void) const;
+  class symbol_scope
+  {
+  public:
+
+    typedef symbol_record::context_id context_id;
+
+    symbol_scope (const std::string& name = "")
+      : m_rep (new symbol_scope_rep (name))
+    { }
+
+    symbol_scope (const symbol_scope&) = default;
+
+    symbol_scope& operator = (const symbol_scope&) = default;
+
+    ~symbol_scope (void) = default;
+
+    bool is_valid (void) const { return bool (m_rep); }
+
+    explicit operator bool () const { return bool (m_rep); }
+
+    void insert_symbol_record (const symbol_record& sr)
+    {
+      m_rep->insert_symbol_record (sr);
+    }
+
+    bool is_nested (void) const
+    {
+      return m_rep->is_nested ();
+    }
+
+    void mark_nested (void)
+    {
+      m_rep->mark_nested ();
+    }
+
+    bool is_static (void) const
+    {
+      return m_rep->is_static ();
+    }
+
+    void mark_static (void)
+    {
+      m_rep->mark_static ();
+    }
+
+    symbol_scope_rep * parent_scope (void) const
+    {
+      return m_rep->parent_scope_rep ();
+    }
+
+    octave_value parent_fcn (void) const
+    {
+      return m_rep->parent_fcn ();
+    }
+
+    symbol_scope dup (void) const
+    {
+      return symbol_scope (m_rep->dup ());
+    }
+
+    void set_context (context_id context)
+    {
+      m_rep->set_context (context);
+    }
+
+    context_id current_context (void) const
+    {
+      return m_rep->current_context ();
+    }
+
+    symbol_record find_symbol (const std::string& name)
+    {
+      return m_rep->find_symbol (name);
+    }
+
+    void inherit (const symbol_scope& donor_scope)
+    {
+      m_rep->inherit (donor_scope.get_rep ());
+    }
+
+    octave_value
+    find (const std::string& name, const octave_value_list& args,
+          bool skip_variables, bool local_funcs)
+    {
+      return m_rep->find (name, args, skip_variables, local_funcs);
+    }
+
+    symbol_record&
+    insert (const std::string& name, bool force_add = false)
+    {
+      return m_rep->insert (name, force_add);
+    }
+
+    void rename (const std::string& old_name, const std::string& new_name)
+    {
+      m_rep->rename (old_name, new_name);
+    }
+
+    void assign (const std::string& name, const octave_value& value,
+                 bool force_add)
+    {
+      m_rep->assign (name, value, force_add);
+    }
+
+    void assign (const std::string& name,
+                 const octave_value& value = octave_value ())
+    {
+      m_rep->assign (name, value);
+    }
+
+    void force_assign (const std::string& name, const octave_value& value)
+    {
+      m_rep->force_assign (name, value);
+    }
+
+    octave_value varval (const std::string& name) const
+    {
+      return m_rep->varval (name);
+    }
+
+    bool is_variable (const std::string& name) const
+    {
+      return m_rep->is_variable (name);
+    }
+
+    void push_context (void)
+    {
+      m_rep->push_context ();
+    }
+
+    void pop_context (void)
+    {
+      m_rep->pop_context ();
+    }
+
+    void refresh (void)
+    {
+      m_rep->refresh ();
+    }
+
+    void clear_variables (void)
+    {
+      m_rep->clear_variables ();
+    }
+
+    void clear_objects (void)
+    {
+      m_rep->clear_objects ();
+    }
+
+    void clear_variable (const std::string& name)
+    {
+      m_rep->clear_variable (name);
+    }
+
+    void clear_variable_pattern (const std::string& pat)
+    {
+      m_rep->clear_variable_pattern (pat);
+    }
+
+    void clear_variable_regexp (const std::string& pat)
+    {
+      m_rep->clear_variable_regexp (pat);
+    }
+
+    void mark_automatic (const std::string& name)
+    {
+      m_rep->mark_automatic (name);
+    }
+
+    void mark_hidden (const std::string& name)
+    {
+      m_rep->mark_hidden (name);
+    }
+
+    void mark_global (const std::string& name)
+    {
+      m_rep->mark_global (name);
+    }
+
+    std::list<symbol_record>
+    all_variables (bool defined_only = true,
+                   unsigned int exclude = symbol_record::hidden) const
+    {
+      return m_rep->all_variables (defined_only, exclude);
+    }
+
+    std::list<symbol_record>
+    glob (const std::string& pattern, bool vars_only = false) const
+    {
+      return m_rep->glob (pattern, vars_only);
+    }
+
+    std::list<symbol_record>
+    regexp (const std::string& pattern, bool vars_only = false) const
+    {
+      return m_rep->regexp (pattern, vars_only);
+    }
+
+    std::list<std::string> variable_names (void)
+    {
+      return m_rep->variable_names ();
+    }
+
+    bool is_local_variable (const std::string& name) const
+    {
+      return m_rep->is_local_variable (name);
+    }
+
+    bool is_global (const std::string& name) const
+    {
+      return m_rep->is_global (name);
+    }
+
+    void install_subfunction (const std::string& name,
+                              const octave_value& fval,
+                              bool is_nested = false)
+    {
+      m_rep->install_subfunction (name, fval, is_nested);
+    }
+
+    void install_nestfunction (const std::string& name,
+                               const octave_value& fval)
+    {
+      m_rep->install_nestfunction (name, fval);
+    }
+
+    octave_value find_subfunction (const std::string& name) const
+    {
+      return m_rep->find_subfunction (name);
+    }
+
+    void lock_subfunctions (void)
+    {
+      m_rep->lock_subfunctions ();
+    }
+
+    void unlock_subfunctions (void)
+    {
+      m_rep->unlock_subfunctions ();
+    }
+
+    std::map<std::string, octave_value> subfunctions (void) const
+    {
+      return m_rep->subfunctions ();
+    }
+
+    void erase_subfunctions (void)
+    {
+      m_rep->erase_subfunctions ();
+    }
+
+    void mark_subfunctions_in_scope_as_private (const std::string& class_name)
+    {
+      m_rep->mark_subfunctions_in_scope_as_private (class_name);
+    }
+
+    bool has_subfunctions (void) const
+    {
+      return m_rep->has_subfunctions ();
+    }
+
+    void stash_subfunction_names (const std::list<std::string>& names)
+    {
+      m_rep->stash_subfunction_names (names);
+    }
+
+    std::list<std::string> subfunction_names (void) const
+    {
+      return m_rep->subfunction_names ();
+    }
+
+    std::list<workspace_element> workspace_info (void) const
+    {
+      return m_rep->workspace_info ();
+    }
+
+    octave_value dump (void) const
+    {
+      return m_rep->dump ();
+    }
+
+    std::string name (void) const
+    {
+      return m_rep->name ();
+    }
+
+    void cache_name (const std::string& name)
+    {
+      m_rep->cache_name (name);
+    }
+
+    octave_user_function *function (void)
+    {
+      return m_rep->function ();
+    }
+
+    void set_function (octave_user_function *fcn)
+    {
+      m_rep->set_function (fcn);
+    }
+
+    void set_parent (const symbol_scope& p)
+    {
+      m_rep->set_parent (p.get_rep ());
+    }
+
+    void set_parent (symbol_scope_rep *p)
+    {
+      m_rep->set_parent (p);
+    }
+
+    void update_nest (void)
+    {
+      m_rep->update_nest ();
+    }
+
+    bool look_nonlocal (const std::string& name, symbol_record& result)
+    {
+      return m_rep->look_nonlocal (name, result);
+    }
+
+    void bind_script_symbols (const symbol_scope& curr_scope)
+    {
+      m_rep->bind_script_symbols (curr_scope.get_rep ());
+    }
+
+    void unbind_script_symbols (void)
+    {
+      m_rep->unbind_script_symbols ();
+    }
+
+    symbol_scope_rep * get_rep (void) const
+    {
+      return m_rep.get ();
+    }
+
+    friend bool operator == (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep == b.m_rep;
+    }
+
+    friend bool operator != (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep != b.m_rep;
+    }
+
+    friend bool operator < (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep < b.m_rep;
+    }
+
+    friend bool operator <= (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep <= b.m_rep;
+    }
+
+    friend bool operator >= (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep >= b.m_rep;
+    }
+
+    friend bool operator > (const symbol_scope& a, const symbol_scope& b)
+    {
+      return a.m_rep > b.m_rep;
+    }
+
+    symbol_scope_rep * get_rep_ptr (void) const { return m_rep.get (); }
+
+  private:
+
+    std::shared_ptr<symbol_scope_rep> m_rep;
+
+    // NEW_REP must be dynamically allocated or nullptr.
+    symbol_scope (symbol_scope_rep *new_rep) : m_rep (new_rep) { }
+
+    octave_value dump_symbols_map (void) const
+    {
+      return m_rep->dump_symbols_map ();
+    }
+
+    symbol_scope_rep * parent_scope_rep (void) const
+    {
+      return m_rep->parent_scope_rep ();
+    }
   };
 }
 
--- a/libinterp/corefcn/symtab.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symtab.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -295,13 +295,13 @@
   void
   symbol_table::clear_global (const std::string& name)
   {
-    m_global_scope->clear_variable (name);
+    m_global_scope.clear_variable (name);
   }
 
   void
   symbol_table::clear_global_pattern (const std::string& pattern)
   {
-    m_global_scope->clear_variable_pattern (pattern);
+    m_global_scope.clear_variable_pattern (pattern);
   }
 
   // Insert INF_CLASS in the set of class names that are considered
@@ -354,7 +354,7 @@
                       bool skip_variables, bool local_funcs)
   {
     return (m_current_scope
-            ? m_current_scope->find (name, args, skip_variables, local_funcs)
+            ? m_current_scope.find (name, args, skip_variables, local_funcs)
             : octave_value ());
   }
 
@@ -431,7 +431,7 @@
         else
           {
             std::string fcn_scope = name.substr (0, pos);
-            symbol_scope *stored_scope = m_current_scope;
+            symbol_scope stored_scope = m_current_scope;
             m_current_scope = m_top_scope;
             octave_value parent = find_function (name.substr (0, pos),
                                                  octave_value_list (), false);
@@ -470,7 +470,7 @@
     if (pos != std::string::npos)
       {
         std::string fcn_scope = full_name.substr (0, pos);
-        symbol_scope *stored_scope = m_current_scope;
+        symbol_scope stored_scope = m_current_scope;
         m_current_scope = m_top_scope;
         octave_value parent = find_function (full_name.substr (0, pos),
                                              octave_value_list (), false);
@@ -645,9 +645,9 @@
 {
   octave::symbol_table& symtab = interp.get_symbol_table ();
 
-  octave::symbol_scope *scope = symtab.current_scope ();
+  octave::symbol_scope scope = symtab.current_scope ();
 
-  std::string nm = scope ? scope->name () : "<unknown>";
+  std::string nm = scope ? scope.name () : "<unknown>";
 
   return ovl (nm, symtab.current_context ());
 }
--- a/libinterp/corefcn/symtab.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/symtab.h	Mon Nov 27 01:12:05 2017 -0500
@@ -61,9 +61,8 @@
 
     symbol_table (void)
       : m_fcn_table (), m_class_precedence_table (),
-        m_parent_map (), m_global_scope (new scope ("global scope")),
-        m_top_scope (new symbol_scope ("top scope")),
-        m_current_scope (m_top_scope)
+        m_parent_map (), m_global_scope ("global scope"),
+        m_top_scope ("top scope"), m_current_scope (m_top_scope)
       { }
 
     // No copying!
@@ -72,18 +71,14 @@
 
     symbol_table& operator = (const symbol_table&) = delete;
 
-    ~symbol_table (void)
-      {
-        delete m_top_scope;
-        delete m_global_scope;
-      }
+    ~symbol_table (void) = default;
 
-    symbol_scope *global_scope (void) { return m_global_scope; }
-    symbol_scope *top_scope (void) { return m_top_scope; }
+    symbol_scope global_scope (void) { return m_global_scope; }
+    symbol_scope top_scope (void) { return m_top_scope; }
 
-    symbol_scope *current_scope (void) { return m_current_scope; }
+    symbol_scope current_scope (void) { return m_current_scope; }
 
-    symbol_scope *require_current_scope (const std::string& who)
+    symbol_scope require_current_scope (const std::string& who)
     {
       if (! m_current_scope)
         error ("%s: missing scope", who.c_str ());
@@ -93,15 +88,15 @@
 
     context_id current_context (void) const
     {
-      return m_current_scope ? m_current_scope->current_context () : 0;
+      return m_current_scope ? m_current_scope.current_context () : 0;
     }
 
-    void set_scope (symbol_scope *sid)
+    void set_scope (const symbol_scope& sid)
     {
       set_scope_and_context (sid, 0);
     }
 
-    void set_scope_and_context (symbol_scope *sid, context_id context)
+    void set_scope_and_context (const symbol_scope& sid, context_id context)
     {
       if (sid == m_global_scope)
         error ("can't set scope to global");
@@ -109,12 +104,12 @@
       m_current_scope = sid;
 
       if (m_current_scope)
-        m_current_scope->set_context (context);
+        m_current_scope.set_context (context);
     }
 
-    symbol_record find_symbol (const std::string& name, symbol_scope *sid)
+    symbol_record find_symbol (const std::string& name, symbol_scope& sid)
     {
-      return sid ? sid->find_symbol (name) : symbol_record ();
+      return sid ? sid.find_symbol (name) : symbol_record ();
     }
 
     symbol_record find_symbol (const std::string& name)
@@ -131,13 +126,14 @@
       return sym;
     }
 
-    void inherit (symbol_scope *recipient_scope, symbol_scope *donor_scope)
+    void
+    inherit (symbol_scope& recipient_scope, const symbol_scope& donor_scope)
     {
       if (recipient_scope)
-        recipient_scope->inherit (donor_scope);
+        recipient_scope.inherit (donor_scope);
     }
 
-    void inherit (symbol_scope *recipient_scope)
+    void inherit (symbol_scope& recipient_scope)
     {
       inherit (recipient_scope, m_current_scope);
     }
@@ -154,43 +150,43 @@
     void assign (const std::string& name, const octave_value& value, bool force_add)
     {
       if (m_current_scope)
-        m_current_scope->assign (name, value, force_add);
+        m_current_scope.assign (name, value, force_add);
     }
 
     void assign (const std::string& name,
                  const octave_value& value = octave_value ())
     {
       if (m_current_scope)
-        m_current_scope->assign (name, value);
+        m_current_scope.assign (name, value);
     }
 
     octave_value varval (const std::string& name) const
     {
       return (m_current_scope
-              ? m_current_scope->varval (name) : octave_value ());
+              ? m_current_scope.varval (name) : octave_value ());
     }
 
     void global_assign (const std::string& name,
                         const octave_value& value = octave_value ())
     {
-      m_global_scope->assign (name, value);
+      m_global_scope.assign (name, value);
     }
 
     octave_value global_varval (const std::string& name) const
     {
-      return m_global_scope->varval (name);
+      return m_global_scope.varval (name);
     }
 
     void
       top_level_assign (const std::string& name,
                         const octave_value& value = octave_value ())
     {
-      m_top_scope->assign (name, value);
+      m_top_scope.assign (name, value);
     }
 
     octave_value top_level_varval (const std::string& name) const
     {
-      return m_top_scope->varval (name);
+      return m_top_scope.varval (name);
     }
 
     bool
@@ -370,10 +366,8 @@
 
     void clear_all (bool force = false)
     {
-      if (m_current_scope)
-        m_current_scope->clear_variables ();
-
-      m_global_scope->clear_variables ();
+      m_current_scope.clear_variables ();
+      m_global_scope.clear_variables ();
 
       clear_functions (force);
     }
@@ -404,7 +398,7 @@
       // FIXME: are we supposed to do both here?
 
       if (m_current_scope)
-        m_current_scope->clear_variable (name);
+        m_current_scope.clear_variable (name);
 
       clear_function (name);
     }
@@ -429,7 +423,7 @@
       // FIXME: are we supposed to do both here?
 
       if (m_current_scope)
-        m_current_scope->clear_variable_pattern (pat);
+        m_current_scope.clear_variable_pattern (pat);
 
       clear_function_pattern (pat);
     }
@@ -511,18 +505,18 @@
     std::list<symbol_record> glob (const std::string& pattern)
     {
       return (m_current_scope
-              ? m_current_scope->glob (pattern) : std::list<symbol_record> ());
+              ? m_current_scope.glob (pattern) : std::list<symbol_record> ());
     }
 
     std::list<symbol_record> glob_global_variables (const std::string& pattern)
     {
-      return m_global_scope->glob (pattern);
+      return m_global_scope.glob (pattern);
     }
 
     std::list<symbol_record>
     regexp_global_variables (const std::string& pattern)
     {
-      return m_global_scope->regexp (pattern);
+      return m_global_scope.regexp (pattern);
     }
 
     std::list<symbol_record> glob_variables (const string_vector& patterns)
@@ -536,7 +530,7 @@
 
       for (size_t i = 0; i < len; i++)
         {
-          std::list<symbol_record> tmp = m_current_scope->glob (patterns[i]);
+          std::list<symbol_record> tmp = m_current_scope.glob (patterns[i]);
 
           retval.insert (retval.begin (), tmp.begin (), tmp.end ());
         }
@@ -555,7 +549,7 @@
 
       for (size_t i = 0; i < len; i++)
         {
-          std::list<symbol_record> tmp = m_current_scope->regexp (patterns[i]);
+          std::list<symbol_record> tmp = m_current_scope.regexp (patterns[i]);
 
           retval.insert (retval.begin (), tmp.begin (), tmp.end ());
         }
@@ -581,19 +575,19 @@
 
     std::list<std::string> global_variable_names (void)
     {
-      return m_global_scope->variable_names ();
+      return m_global_scope.variable_names ();
     }
 
     std::list<std::string> top_level_variable_names (void)
     {
       return (m_top_scope
-              ? m_top_scope->variable_names () : std::list<std::string> ());
+              ? m_top_scope.variable_names () : std::list<std::string> ());
     }
 
     std::list<std::string> variable_names (void)
     {
       return (m_current_scope
-              ? m_current_scope->variable_names () : std::list<std::string> ());
+              ? m_current_scope.variable_names () : std::list<std::string> ());
     }
 
     std::list<std::string> built_in_function_names (void)
@@ -667,7 +661,7 @@
 
     octave_user_function * get_curr_fcn (void)
     {
-      return m_current_scope ? m_current_scope->function () : nullptr;
+      return m_current_scope ? m_current_scope.function () : nullptr;
     }
 
     void cleanup (void);
@@ -713,10 +707,10 @@
     typedef std::map<std::string, std::list<std::string>>::iterator
       parent_map_iterator;
 
-    symbol_scope *m_global_scope;
-    symbol_scope *m_top_scope;
+    symbol_scope m_global_scope;
+    symbol_scope m_top_scope;
 
-    symbol_scope *m_current_scope;
+    symbol_scope m_current_scope;
 
     octave_value dump_fcn_table_map (void) const;
   };
--- a/libinterp/corefcn/variables.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/corefcn/variables.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -204,9 +204,9 @@
 
   if (! name.empty ())
     {
-      octave::symbol_scope *scope = symtab.current_scope ();
-
-      octave_value val = scope ? scope->varval (name) : octave_value ();
+      octave::symbol_scope scope = symtab.current_scope ();
+
+      octave_value val = scope ? scope.varval (name) : octave_value ();
 
       retval = val.is_defined ();
     }
@@ -328,11 +328,11 @@
   if (! args(0).is_string ())
     error ("isglobal: NAME must be a string");
 
-  octave::symbol_scope *scope = symtab.current_scope ();
+  octave::symbol_scope scope = symtab.current_scope ();
 
   std::string name = args(0).string_value ();
 
-  return scope && scope->is_global (name);
+  return scope && scope.is_global (name);
 }
 
 DEFMETHOD (isglobal, interp, args, ,
@@ -389,9 +389,9 @@
 
   if (search_any || search_var)
     {
-      octave::symbol_scope *scope = symtab.current_scope ();
-
-      octave_value val = scope ? scope->varval (name) : octave_value ();
+      octave::symbol_scope scope = symtab.current_scope ();
+
+      octave_value val = scope ? scope.varval (name) : octave_value ();
 
       if (val.is_constant () || val.isobject ()
           || val.is_function_handle ()
@@ -1656,9 +1656,9 @@
 
           octave::symbol_scope tmp_scope;
 
-          symtab.set_scope (&tmp_scope);
-
-          cs.push (&tmp_scope, 0);
+          symtab.set_scope (tmp_scope);
+
+          cs.push (tmp_scope, 0);
           frame.add_method (cs, &octave::call_stack::pop);
 
           octave::feval ("load", octave_value (nm), 0);
@@ -1697,9 +1697,9 @@
   symbol_info_list symbol_stats;
   std::list<std::string> symbol_names;
 
-  octave::symbol_scope *scope = symtab.current_scope ();
-
-  octave::symbol_record::context_id context = scope->current_context ();
+  octave::symbol_scope scope = symtab.current_scope ();
+
+  octave::symbol_record::context_id context = scope.current_context ();
 
   for (int j = 0; j < npats; j++)
     {
@@ -1740,7 +1740,7 @@
 
                   std::string base_name = pat.substr (0, pos);
 
-                  if (scope && scope->is_variable (base_name))
+                  if (scope && scope.is_variable (base_name))
                     {
                       octave::symbol_record sr
                         = symtab.find_symbol (base_name);
@@ -2106,7 +2106,7 @@
                   const string_vector& argv, int argc, int idx,
                   bool exclusive = false)
 {
-  octave::symbol_scope *scope = symtab.current_scope ();
+  octave::symbol_scope scope = symtab.current_scope ();
 
   if (! scope)
     return;
@@ -2121,7 +2121,7 @@
         {
           std::string name = gvars[i];
 
-          scope->clear_variable (name);
+          scope.clear_variable (name);
           symtab.clear_global (name);
         }
     }
@@ -2139,7 +2139,7 @@
 
               if (! name_matches_any_pattern (name, argv, argc, idx))
                 {
-                  scope->clear_variable (name);
+                  scope.clear_variable (name);
                   symtab.clear_global (name);
                 }
             }
@@ -2150,7 +2150,7 @@
             {
               std::string pattern = argv[idx++];
 
-              scope->clear_variable_pattern (pattern);
+              scope.clear_variable_pattern (pattern);
               symtab.clear_global_pattern (pattern);
             }
         }
@@ -2162,18 +2162,18 @@
                     const string_vector& argv, int argc, int idx,
                     bool exclusive = false, bool have_regexp = false)
 {
-  octave::symbol_scope *scope = symtab.current_scope ();
+  octave::symbol_scope scope = symtab.current_scope ();
 
   if (! scope)
     return;
 
   if (idx == argc)
-    scope->clear_variables ();
+    scope.clear_variables ();
   else
     {
       if (exclusive)
         {
-          string_vector lvars = scope->variable_names ();
+          string_vector lvars = scope.variable_names ();
 
           int lcount = lvars.numel ();
 
@@ -2182,17 +2182,17 @@
               std::string nm = lvars[i];
 
               if (! name_matches_any_pattern (nm, argv, argc, idx, have_regexp))
-                scope->clear_variable (nm);
+                scope.clear_variable (nm);
             }
         }
       else
         {
           if (have_regexp)
             while (idx < argc)
-              scope->clear_variable_regexp (argv[idx++]);
+              scope.clear_variable_regexp (argv[idx++]);
           else
             while (idx < argc)
-              scope->clear_variable_pattern (argv[idx++]);
+              scope.clear_variable_pattern (argv[idx++]);
         }
     }
 }
@@ -2204,10 +2204,10 @@
 {
   if (idx == argc)
     {
-      octave::symbol_scope *scope = symtab.current_scope ();
+      octave::symbol_scope scope = symtab.current_scope ();
 
       if (scope)
-        scope->clear_variables ();
+        scope.clear_variables ();
     }
   else
     {
@@ -2235,7 +2235,7 @@
 {
   // This is supposed to be mostly Matlab compatible.
 
-  octave::symbol_scope *scope = symtab.current_scope ();
+  octave::symbol_scope scope = symtab.current_scope ();
 
   if (! scope)
     return;
@@ -2243,29 +2243,29 @@
   for (; idx < argc; idx++)
     {
       if (argv[idx] == "all"
-          && ! scope->is_local_variable ("all"))
+          && ! scope.is_local_variable ("all"))
         {
           symtab.clear_all ();
         }
       else if (argv[idx] == "functions"
-               && ! scope->is_local_variable ("functions"))
+               && ! scope.is_local_variable ("functions"))
         {
           do_clear_functions (symtab, argv, argc, ++idx);
         }
       else if (argv[idx] == "global"
-               && ! scope->is_local_variable ("global"))
+               && ! scope.is_local_variable ("global"))
         {
           do_clear_globals (symtab, argv, argc, ++idx);
         }
       else if (argv[idx] == "variables"
-               && ! scope->is_local_variable ("variables"))
+               && ! scope.is_local_variable ("variables"))
         {
-          scope->clear_variables ();
+          scope.clear_variables ();
         }
       else if (argv[idx] == "classes"
-               && ! scope->is_local_variable ("classes"))
+               && ! scope.is_local_variable ("classes"))
         {
-          scope->clear_objects ();
+          scope.clear_objects ();
           octave_class::clear_exemplar_map ();
           symtab.clear_all ();
         }
@@ -2384,7 +2384,7 @@
       bool have_regexp = false;
       bool have_dash_option = false;
 
-      octave::symbol_scope *scope = symtab.current_scope ();
+      octave::symbol_scope scope = symtab.current_scope ();
 
       while (++idx < argc)
         {
@@ -2473,7 +2473,7 @@
               else if (clear_objects)
                 {
                   if (scope)
-                    scope->clear_objects ();
+                    scope.clear_objects ();
                   octave_class::clear_exemplar_map ();
                   symtab.clear_all ();
                 }
@@ -2624,9 +2624,9 @@
 
   std::string name = args(0).xstring_value ("__varval__: first argument must be a variable name");
 
-  octave::symbol_scope *scope = interp.get_current_scope ();
-
-  return scope ? scope->varval (args(0).string_value ()) : octave_value ();
+  octave::symbol_scope scope = interp.get_current_scope ();
+
+  return scope ? scope.varval (args(0).string_value ()) : octave_value ();
 }
 
 static std::string Vmissing_component_hook;
@@ -2715,11 +2715,11 @@
 void
 clear_variable (const std::string& nm)
 {
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
     = octave::__get_current_scope__ ("clear_variable");
 
   if (scope)
-    scope->clear_variable (nm);
+    scope.clear_variable (nm);
 }
 
 void
@@ -2733,10 +2733,10 @@
 octave_value
 lookup_function_handle (const std::string& nm)
 {
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
     = octave::__get_current_scope__ ("lookup_function_handle");
 
-  octave_value val = scope ? scope->varval (nm) : octave_value ();
+  octave_value val = scope ? scope.varval (nm) : octave_value ();
 
   return val.is_function_handle () ? val : octave_value ();
 }
--- a/libinterp/octave-value/ov-classdef.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-classdef.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -1113,10 +1113,10 @@
           error ("cannot call superclass constructor with variable `%s'",
                  mname.c_str ());
 
-        octave::symbol_scope *scope
+        octave::symbol_scope scope
           = octave::__require_current_scope__ ("octave_classdef_superclass_ref::call");
 
-        octave_value sym = scope->varval (mname);
+        octave_value sym = scope.varval (mname);
 
         cls.run_constructor (to_cdef_ref (sym), idx);
 
--- a/libinterp/octave-value/ov-fcn-handle.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -87,10 +87,10 @@
 
   if (uf && nm != anonymous)
     {
-      octave::symbol_scope *uf_scope = uf->scope ();
+      octave::symbol_scope uf_scope = uf->scope ();
 
       if (uf_scope)
-        uf_scope->cache_name (nm);
+        uf_scope.cache_name (nm);
     }
 
   if (uf && uf->is_nested_function () && ! uf->is_subfunction ())
@@ -353,12 +353,12 @@
       std::list<octave::symbol_record> vars;
 
       octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope *f_scope = f->scope ();
       octave::symbol_record::context_id context = 0;
+      octave::symbol_scope f_scope = f->scope ();
       if (f_scope)
         {
-          vars = f_scope->all_variables ();
-          context = f_scope->current_context ();
+          vars = f_scope.all_variables ();
+          context = f_scope.current_context ();
         }
 
       size_t varlen = vars.size ();
@@ -411,10 +411,10 @@
 
           if (uf)
             {
-              octave::symbol_scope *uf_scope = uf->scope ();
+              octave::symbol_scope uf_scope = uf->scope ();
 
               if (uf_scope)
-                uf_scope->cache_name (nm);
+                uf_scope.cache_name (nm);
             }
         }
       else
@@ -475,12 +475,12 @@
 
       octave::symbol_scope local_scope (buf);
 
-      symtab.set_scope (&local_scope);
+      symtab.set_scope (local_scope);
 
       octave::call_stack& cs
         = octave::__get_call_stack__ ("octave_fcn_handle::load_ascii");
 
-      cs.push (&local_scope, 0);
+      cs.push (local_scope, 0);
       frame.add_method (cs, &octave::call_stack::pop);
 
       octave_idx_type len = 0;
@@ -534,12 +534,12 @@
       std::list<octave::symbol_record> vars;
 
       octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope *f_scope = f->scope ();
+      octave::symbol_scope f_scope = f->scope ();
       octave::symbol_record::context_id context = 0;
       if (f_scope)
         {
-          vars = f_scope->all_variables ();
-          context = f_scope->current_context ();
+          vars = f_scope.all_variables ();
+          context = f_scope.current_context ();
         }
 
       size_t varlen = vars.size ();
@@ -645,12 +645,12 @@
 
       octave::symbol_scope local_scope (ctmp2);
 
-      symtab.set_scope (&local_scope);
+      symtab.set_scope (local_scope);
 
       octave::call_stack& cs
         = octave::__get_call_stack__ ("octave_fcn_handle::load_binary");
 
-      cs.push (&local_scope, 0);
+      cs.push (local_scope, 0);
       frame.add_method (cs, &octave::call_stack::pop);
 
       if (len > 0)
@@ -794,12 +794,12 @@
       std::list<octave::symbol_record> vars;
 
       octave_user_function *f = fcn.user_function_value ();
-      octave::symbol_scope *f_scope = f->scope ();
+      octave::symbol_scope f_scope = f->scope ();
       octave::symbol_record::context_id context = 0;
       if (f_scope)
         {
-          vars = f_scope->all_variables ();
-          context = f_scope->current_context ();
+          vars = f_scope.all_variables ();
+          context = f_scope.current_context ();
         }
 
       size_t varlen = vars.size ();
@@ -1151,12 +1151,12 @@
 
       octave::symbol_scope local_scope (fcn_tmp);
 
-      symtab.set_scope (&local_scope);
+      symtab.set_scope (local_scope);
 
       octave::call_stack& cs
         = octave::__get_call_stack__ ("octave_fcn_handle::load_hdf5");
 
-      cs.push (&local_scope, 0);
+      cs.push (local_scope, 0);
       frame.add_method (cs, &octave::call_stack::pop);
 
       if (len > 0 && success)
@@ -1771,12 +1771,12 @@
       std::list<octave::symbol_record> vars;
 
       octave_user_function *fu = fh->user_function_value ();
-      octave::symbol_scope *fu_scope = fu->scope ();
+      octave::symbol_scope fu_scope = fu->scope ();
       octave::symbol_record::context_id context = 0;
       if (fu_scope)
         {
-          vars = fu_scope->all_variables ();
-          context = fu_scope->current_context ();
+          vars = fu_scope.all_variables ();
+          context = fu_scope.current_context ();
         }
 
       size_t varlen = vars.size ();
@@ -1997,10 +1997,10 @@
 
           if (arg_list && arg_list->length () > 0)
             {
-              octave::symbol_scope *scope = tw->get_current_scope ();
+              octave::symbol_scope scope = tw->get_current_scope ();
 
               octave::symbol_record::context_id context
-                = scope->current_context ();
+                = scope.current_context ();
 
               bool bad = false;
               int nargs = arg_list->length ();
--- a/libinterp/octave-value/ov-fcn-inline.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-fcn-inline.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -104,7 +104,7 @@
 
               if (curr_fcn)
                 {
-                  octave::symbol_scope *parent_scope
+                  octave::symbol_scope parent_scope
                     = curr_fcn->parent_fcn_scope ();
 
                   if (! parent_scope)
--- a/libinterp/octave-value/ov-fcn.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-fcn.h	Mon Nov 27 01:12:05 2017 -0500
@@ -80,12 +80,12 @@
 
   virtual std::string parent_fcn_name (void) const { return ""; }
 
-  virtual octave::symbol_scope * parent_fcn_scope (void) const
-  { return nullptr; }
+  virtual octave::symbol_scope parent_fcn_scope (void) const
+  { return octave::symbol_scope (); }
 
   virtual void mark_fcn_file_up_to_date (const octave::sys::time&) { }
 
-  virtual octave::symbol_scope * scope (void) { return nullptr; }
+  virtual octave::symbol_scope scope (void) { return octave::symbol_scope (); }
 
   virtual octave::sys::time time_parsed (void) const
   { return octave::sys::time (static_cast<time_t> (0)); }
--- a/libinterp/octave-value/ov-usr-fcn.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -64,7 +64,6 @@
 
 octave_user_code::~octave_user_code (void)
 {
-  delete m_scope;
   delete m_file_info;
 }
 
@@ -134,7 +133,7 @@
 
 octave_user_script::octave_user_script
   (const std::string& fnm, const std::string& nm,
-   octave::symbol_scope *scope, octave::tree_statement_list *cmds,
+   const octave::symbol_scope& scope, octave::tree_statement_list *cmds,
    const std::string& ds)
   : octave_user_code (nm, scope, ds), cmd_list (cmds), file_name (fnm),
     t_parsed (static_cast<time_t> (0)),
@@ -147,7 +146,7 @@
 
 octave_user_script::octave_user_script
   (const std::string& fnm, const std::string& nm,
-   octave::symbol_scope *scope, const std::string& ds)
+   const octave::symbol_scope& scope, const std::string& ds)
   : octave_user_code (nm, scope, ds), cmd_list (nullptr), file_name (fnm),
     t_parsed (static_cast<time_t> (0)),
     t_checked (static_cast<time_t> (0)),
@@ -207,7 +206,7 @@
 
       frame.add_method (m_scope,
                         &octave::symbol_scope::unbind_script_symbols);
-      m_scope->bind_script_symbols (tw.get_current_scope ());
+      m_scope.bind_script_symbols (tw.get_current_scope ());
 
       if (tw.echo ())
         tw.push_echo_state (frame, octave::tree_evaluator::ECHO_SCRIPTS,
@@ -241,7 +240,7 @@
 // extrinsic/intrinsic state?).
 
 octave_user_function::octave_user_function
-  (octave::symbol_scope *scope, octave::tree_parameter_list *pl,
+  (const octave::symbol_scope& scope, octave::tree_parameter_list *pl,
    octave::tree_parameter_list *rl, octave::tree_statement_list *cl)
   : octave_user_code ("", scope, ""),
     param_list (pl), ret_list (rl), cmd_list (cl),
@@ -254,7 +253,7 @@
     subfunction (false), inline_function (false),
     anonymous_function (false), nested_function (false),
     class_constructor (none), class_method (false),
-    parent_scope (nullptr)
+    parent_scope ()
 #if defined (HAVE_LLVM)
     , jit_info (0)
 #endif
@@ -263,7 +262,7 @@
     cmd_list->mark_as_function_body ();
 
   if (m_scope)
-    m_scope->set_function (this);
+    m_scope.set_function (this);
 }
 
 octave_user_function::~octave_user_function (void)
@@ -361,7 +360,7 @@
 }
 
 void
-octave_user_function::stash_parent_fcn_scope (octave::symbol_scope *ps)
+octave_user_function::stash_parent_fcn_scope (const octave::symbol_scope& ps)
 {
   parent_scope = ps;
 }
@@ -416,7 +415,7 @@
 void
 octave_user_function::erase_subfunctions (void)
 {
-  m_scope->erase_subfunctions ();
+  m_scope.erase_subfunctions ();
 }
 
 bool
@@ -434,7 +433,7 @@
 void
 octave_user_function::mark_as_private_function (const std::string& cname)
 {
-  m_scope->mark_subfunctions_in_scope_as_private (cname);
+  m_scope.mark_subfunctions_in_scope_as_private (cname);
 
   octave_function::mark_as_private_function (cname);
 }
@@ -442,37 +441,37 @@
 void
 octave_user_function::lock_subfunctions (void)
 {
-  m_scope->lock_subfunctions ();
+  m_scope.lock_subfunctions ();
 }
 
 void
 octave_user_function::unlock_subfunctions (void)
 {
-  m_scope->unlock_subfunctions ();
+  m_scope.unlock_subfunctions ();
 }
 
 std::map<std::string, octave_value>
 octave_user_function::subfunctions (void) const
 {
-  return m_scope->subfunctions ();
+  return m_scope.subfunctions ();
 }
 
 bool
 octave_user_function::has_subfunctions (void) const
 {
-  return m_scope->has_subfunctions ();
+  return m_scope.has_subfunctions ();
 }
 
 void
 octave_user_function::stash_subfunction_names (const std::list<std::string>& names)
 {
-  m_scope->stash_subfunction_names (names);
+  m_scope.stash_subfunction_names (names);
 }
 
 std::list<std::string>
 octave_user_function::subfunction_names (void) const
 {
-  return m_scope->subfunction_names ();
+  return m_scope.subfunction_names ();
 }
 
 octave_value_list
@@ -549,12 +548,12 @@
 
   if (call_depth > 0 && ! is_anonymous_function ())
     {
-      m_scope->push_context ();
+      m_scope.push_context ();
 
 #if 0
       std::cerr << name () << " scope: " << m_scope
                 << " call depth: " << call_depth
-                << " context: " << m_scope->current_context () << std::endl;
+                << " context: " << m_scope.current_context () << std::endl;
 #endif
 
       frame.add_method (m_scope, &octave::symbol_scope::pop_context);
@@ -566,7 +565,7 @@
     {
 #if 0
       std::cerr << "defining param list, scope: " << m_scope
-                << ", context: " << m_scope->current_context () << std::endl;
+                << ", context: " << m_scope.current_context () << std::endl;
 #endif
       tw.define_parameter_list_from_arg_vector (param_list, args);
     }
@@ -666,7 +665,7 @@
 
       if (ret_list->takes_varargs ())
         {
-          octave_value varargout_varval = m_scope->varval ("varargout");
+          octave_value varargout_varval = m_scope.varval ("varargout");
 
           if (varargout_varval.is_defined ())
             varargout = varargout_varval.xcell_value ("varargout must be a cell array object");
@@ -759,8 +758,8 @@
        { "nested_function", nested_function },
        { "ctor_type", ctor_type_str () },
        { "class_method", class_method },
-       { "parent_scope", parent_scope ? parent_scope->name () : "0x0" },
-       { "scope_info", m_scope ? m_scope->dump () : "0x0" }};
+       { "parent_scope", parent_scope ? parent_scope.name () : "0x0" },
+       { "scope_info", m_scope ? m_scope.dump () : "0x0" }};
 
   return octave_value (m);
 }
@@ -794,44 +793,44 @@
       // for backward compatibility of functions that use it directly.
 
       charMatrix chm (arg_names, tw.string_fill_char ());
-      m_scope->force_assign ("argn", chm);
-      m_scope->force_assign (".argn.", Cell (arg_names));
+      m_scope.force_assign ("argn", chm);
+      m_scope.force_assign (".argn.", Cell (arg_names));
 
-      m_scope->mark_hidden (".argn.");
+      m_scope.mark_hidden (".argn.");
 
-      m_scope->mark_automatic ("argn");
-      m_scope->mark_automatic (".argn.");
+      m_scope.mark_automatic ("argn");
+      m_scope.mark_automatic (".argn.");
     }
 
-  m_scope->force_assign (".nargin.", nargin);
-  m_scope->force_assign (".nargout.", nargout);
+  m_scope.force_assign (".nargin.", nargin);
+  m_scope.force_assign (".nargout.", nargout);
 
-  m_scope->mark_hidden (".nargin.");
-  m_scope->mark_hidden (".nargout.");
+  m_scope.mark_hidden (".nargin.");
+  m_scope.mark_hidden (".nargout.");
 
-  m_scope->mark_automatic (".nargin.");
-  m_scope->mark_automatic (".nargout.");
+  m_scope.mark_automatic (".nargin.");
+  m_scope.mark_automatic (".nargout.");
 
-  m_scope->force_assign (".saved_warning_states.", octave_value ());
+  m_scope.force_assign (".saved_warning_states.", octave_value ());
 
-  m_scope->mark_automatic (".saved_warning_states.");
-  m_scope->mark_automatic (".saved_warning_states.");
+  m_scope.mark_automatic (".saved_warning_states.");
+  m_scope.mark_automatic (".saved_warning_states.");
 
   if (takes_varargs ())
-    m_scope->assign ("varargin", va_args.cell_value ());
+    m_scope.assign ("varargin", va_args.cell_value ());
 
   Matrix ignored_fcn_outputs = tw.ignored_fcn_outputs ();
 
-  m_scope->force_assign (".ignored.", ignored_fcn_outputs);
+  m_scope.force_assign (".ignored.", ignored_fcn_outputs);
 
-  m_scope->mark_hidden (".ignored.");
-  m_scope->mark_automatic (".ignored.");
+  m_scope.mark_hidden (".ignored.");
+  m_scope.mark_automatic (".ignored.");
 }
 
 void
 octave_user_function::restore_warning_states (void)
 {
-  octave_value val = m_scope->varval (".saved_warning_states.");
+  octave_value val = m_scope.varval (".saved_warning_states.");
 
   if (val.is_defined ())
     {
@@ -932,8 +931,8 @@
     }
   else
     {
-      octave::symbol_scope *scope = symtab.require_current_scope ("nargin");
-      retval = scope->varval (".nargin.");
+      octave::symbol_scope scope = symtab.require_current_scope ("nargin");
+      retval = scope.varval (".nargin.");
 
       if (retval.is_undefined ())
         retval = 0;
@@ -1058,8 +1057,8 @@
       if (symtab.at_top_level ())
         error ("nargout: invalid call at top level");
 
-      octave::symbol_scope *scope = symtab.require_current_scope ("nargout");
-      retval = scope->varval (".nargout.");
+      octave::symbol_scope scope = symtab.require_current_scope ("nargout");
+      retval = scope.varval (".nargout.");
 
       if (retval.is_undefined ())
         retval = 0;
@@ -1131,12 +1130,12 @@
   if (symtab.at_top_level ())
     error ("isargout: invalid call at top level");
 
-  octave::symbol_scope *scope = symtab.require_current_scope ("isargout");
+  octave::symbol_scope scope = symtab.require_current_scope ("isargout");
 
-  int nargout1 = scope->varval (".nargout.").int_value ();
+  int nargout1 = scope.varval (".nargout.").int_value ();
 
   Matrix ignored;
-  octave_value tmp = scope->varval (".ignored.");
+  octave_value tmp = scope.varval (".ignored.");
   if (tmp.is_defined ())
     ignored = tmp.matrix_value ();
 
--- a/libinterp/octave-value/ov-usr-fcn.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/octave-value/ov-usr-fcn.h	Mon Nov 27 01:12:05 2017 -0500
@@ -61,7 +61,7 @@
 protected:
 
   octave_user_code (const std::string& nm,
-                    octave::symbol_scope *scope = nullptr,
+                    const octave::symbol_scope& scope = octave::symbol_scope (),
                     const std::string& ds = "")
     : octave_function (nm, ds), m_scope (scope), m_file_info (nullptr),
       curr_unwind_protect_frame (nullptr)
@@ -70,7 +70,7 @@
 public:
 
   octave_user_code (void)
-    : octave_function (), m_scope (nullptr), m_file_info (nullptr),
+    : octave_function (), m_scope (), m_file_info (nullptr),
       curr_unwind_protect_frame (nullptr)
   { }
 
@@ -97,7 +97,7 @@
   void cache_function_text (const std::string& text,
                             const octave::sys::time& timestamp);
 
-  octave::symbol_scope *scope (void) { return m_scope; }
+  octave::symbol_scope scope (void) { return m_scope; }
 
   virtual std::map<std::string, octave_value> subfunctions (void) const;
 
@@ -108,7 +108,7 @@
   void get_file_info (void);
 
   // Our symbol table scope.
-  octave::symbol_scope *m_scope;
+  octave::symbol_scope m_scope;
 
   // Cached text of function or script code with line offsets
   // calculated.
@@ -128,12 +128,12 @@
   octave_user_script (void);
 
   octave_user_script (const std::string& fnm, const std::string& nm,
-                      octave::symbol_scope *scope = nullptr,
+                      const octave::symbol_scope& scope = octave::symbol_scope (),
                       octave::tree_statement_list *cmds = nullptr,
                       const std::string& ds = "");
 
   octave_user_script (const std::string& fnm, const std::string& nm,
-                      octave::symbol_scope *scope = nullptr,
+                      const octave::symbol_scope& scope = octave::symbol_scope (),
                       const std::string& ds = "");
 
   // No copying!
@@ -207,7 +207,7 @@
 {
 public:
 
-  octave_user_function (octave::symbol_scope *scope = nullptr,
+  octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope (),
                         octave::tree_parameter_list *pl = nullptr,
                         octave::tree_parameter_list *rl = nullptr,
                         octave::tree_statement_list *cl = nullptr);
@@ -260,7 +260,7 @@
 
   void stash_parent_fcn_name (const std::string& p) { parent_name = p; }
 
-  void stash_parent_fcn_scope (octave::symbol_scope *ps);
+  void stash_parent_fcn_scope (const octave::symbol_scope& ps);
 
   void stash_leading_comment (octave::comment_list *lc) { lead_comm = lc; }
 
@@ -280,7 +280,7 @@
 
   std::string parent_fcn_name (void) const { return parent_name; }
 
-  octave::symbol_scope *
+  octave::symbol_scope
   parent_fcn_scope (void) const { return parent_scope; }
 
   octave::sys::time time_parsed (void) const { return t_parsed; }
@@ -481,7 +481,7 @@
   bool class_method;
 
   // The scope of the parent function, if any.
-  octave::symbol_scope *parent_scope;
+  octave::symbol_scope parent_scope;
 
 #if defined (HAVE_LLVM)
   octave::jit_function_info *jit_info;
--- a/libinterp/parse-tree/lex.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/lex.h	Mon Nov 27 01:12:05 2017 -0500
@@ -69,17 +69,17 @@
 
       void pop (void);
 
-      void push (symbol_scope *scope)
+      void push (const symbol_scope& scope)
       {
         frame_stack.push_front (scope);
       }
 
-      symbol_scope *curr_scope (void) const;
-      symbol_scope *parent_scope (void) const;
+      symbol_scope curr_scope (void) const;
+      symbol_scope parent_scope (void) const;
 
     private:
 
-      std::deque<symbol_scope*> frame_stack;
+      std::deque<symbol_scope> frame_stack;
     };
 
     // Track nesting of square brackets, curly braces, and parentheses.
@@ -602,7 +602,7 @@
 
     bool inside_any_object_index (void);
 
-    bool is_variable (const std::string& name, symbol_scope *scope);
+    bool is_variable (const std::string& name, const symbol_scope& scope);
 
     int is_keyword_token (const std::string& s);
 
--- a/libinterp/parse-tree/lex.ll	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/lex.ll	Mon Nov 27 01:12:05 2017 -0500
@@ -2079,13 +2079,7 @@
   lexical_feedback::symbol_table_context::clear (void)
   {
     while (! frame_stack.empty ())
-      {
-        symbol_scope *scope = curr_scope ();
-
-        delete scope;
-
-        frame_stack.pop_front ();
-      }
+      frame_stack.pop_front ();
   }
 
   void
@@ -2097,12 +2091,12 @@
     frame_stack.pop_front ();
   }
 
-  symbol_scope *
+  symbol_scope
   lexical_feedback::symbol_table_context::curr_scope (void) const
   {
     if (empty ())
       {
-        symbol_scope *scope
+        symbol_scope scope
           = __get_current_scope__ ("lexical_feedback::symbol_table_context::curr_scope");
 
         return scope;
@@ -2111,12 +2105,12 @@
       return frame_stack.front ();
   }
 
-  symbol_scope *
+  symbol_scope
   lexical_feedback::symbol_table_context::parent_scope (void) const
   {
     size_t sz = size ();
 
-    return sz > 1 ? frame_stack[1] : (sz == 1 ? frame_stack[0] : nullptr);
+    return sz > 1 ? frame_stack[1] : (sz == 1 ? frame_stack[0] : symbol_scope ());
   }
 
   lexical_feedback::~lexical_feedback (void)
@@ -2522,9 +2516,9 @@
 
   bool
   base_lexer::is_variable (const std::string& name,
-                           symbol_scope *scope)
+                           const symbol_scope& scope)
   {
-    return ((scope && scope->is_variable (name))
+    return ((scope && scope.is_variable (name))
             || (pending_local_variables.find (name)
                 != pending_local_variables.end ()));
   }
@@ -3156,9 +3150,9 @@
 
     // Find the token in the symbol table.
 
-    symbol_scope *scope = symtab_context.curr_scope ();
-
-    symbol_record sr = (scope ? scope->insert (ident) : symbol_record (ident));
+    symbol_scope scope = symtab_context.curr_scope ();
+
+    symbol_record sr = (scope ? scope.insert (ident) : symbol_record (ident));
 
     token *tok = new token (NAME, sr, input_line_number, current_input_column);
 
--- a/libinterp/parse-tree/oct-parse.in.yy	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/oct-parse.in.yy	Mon Nov 27 01:12:05 2017 -0500
@@ -1285,8 +1285,7 @@
                       parser.m_max_fcn_depth = parser.m_curr_fcn_depth;
 
                     // Will get a real name later.
-                    lexer.symtab_context.push (new octave::symbol_scope ("parser:push_fcn_symtab"));
-
+                    lexer.symtab_context.push (octave::symbol_scope ("parser:push_fcn_symtab"));
                     parser.m_function_scopes.push (lexer.symtab_context.curr_scope ());
 
                     if (! lexer.reading_script_file
@@ -1316,7 +1315,7 @@
                     if (lexer.looking_at_function_handle)
                       {
                         // Will get a real name later.
-                        lexer.symtab_context.push (new octave::symbol_scope ("parser:param_lsit_beg"));
+                        lexer.symtab_context.push (octave::symbol_scope ("parser:param_lsit_beg"));
                         lexer.looking_at_function_handle--;
                         lexer.looking_at_anon_fcn_args = true;
                       }
@@ -1454,7 +1453,7 @@
                     $$ = 0;
 
                     // Will get a real name later.
-                    lexer.symtab_context.push (new octave::symbol_scope ("parser:push_script_symtab"));
+                    lexer.symtab_context.push (octave::symbol_scope ("parser:push_script_symtab"));
                   }
                 ;
 
@@ -1475,7 +1474,6 @@
                         // base_parser::m_primary_fcn_ptr.
 
                         // Unused symbol table context.
-                        delete lexer.symtab_context.curr_scope ();
                         lexer.symtab_context.pop ();
 
                         delete $3;
@@ -1498,7 +1496,6 @@
                     YYUSE ($5);
 
                     // Unused symbol table context.
-                    delete lexer.symtab_context.curr_scope ();
                     lexer.symtab_context.pop ();
 
                     parser.finish_classdef_file ($3, $6);
@@ -1541,9 +1538,9 @@
                         YYABORT;
                       }
 
-                    octave::symbol_scope *curr_scope
+                    octave::symbol_scope curr_scope
                       = lexer.symtab_context.curr_scope ();
-                    curr_scope->cache_name (id);
+                    curr_scope.cache_name (id);
 
                     lexer.parsed_function_name.top () = true;
                     lexer.maybe_classdef_get_set_method = false;
@@ -1649,7 +1646,7 @@
                       }
 
                     // Create invalid parent scope.
-                    lexer.symtab_context.push (nullptr);
+                    lexer.symtab_context.push (octave::symbol_scope ());
                     lexer.parsing_classdef = true;
                     $$ = $1;
                   }
@@ -2103,7 +2100,7 @@
   }
 
   void
-  base_parser::parent_scope_info::push (symbol_scope *scope)
+  base_parser::parent_scope_info::push (const symbol_scope& scope)
   {
     push (value_type (scope, ""));
   }
@@ -2156,10 +2153,10 @@
     return true;
   }
 
-  symbol_scope *
+  symbol_scope
   base_parser::parent_scope_info::parent_scope (void) const
   {
-    return size () > 1 ? m_info[size()-2].first : nullptr;
+    return size () > 1 ? m_info[size()-2].first : symbol_scope ();
   }
 
   std::string
@@ -2178,7 +2175,7 @@
     : m_endfunction_found (false), m_autoloading (false),
       m_fcn_file_from_relative_lookup (false),
       m_parsing_subfunctions (false), m_parsing_local_functions (false),
-      m_max_fcn_depth (0), m_curr_fcn_depth (0), m_primary_fcn_scope (nullptr),
+      m_max_fcn_depth (0), m_curr_fcn_depth (0), m_primary_fcn_scope (),
       m_curr_class_name (), m_curr_package_name (), m_function_scopes (),
       m_primary_fcn_ptr (nullptr), m_subfunction_names (),
       m_classdef_object (nullptr), m_stmt_list (nullptr), m_lexer (lxr),
@@ -2212,7 +2209,7 @@
     m_parsing_local_functions = false;
     m_max_fcn_depth = 0;
     m_curr_fcn_depth = 0;
-    m_primary_fcn_scope = nullptr;
+    m_primary_fcn_scope = symbol_scope ();
     m_curr_class_name = "";
     m_curr_package_name = "";
     m_function_scopes.clear ();
@@ -2450,14 +2447,14 @@
     int l = m_lexer.input_line_number;
     int c = m_lexer.current_input_column;
 
-    symbol_scope *fcn_scope = m_lexer.symtab_context.curr_scope ();
-    symbol_scope *parent_scope = m_lexer.symtab_context.parent_scope ();
+    symbol_scope fcn_scope = m_lexer.symtab_context.curr_scope ();
+    symbol_scope parent_scope = m_lexer.symtab_context.parent_scope ();
 
     m_lexer.symtab_context.pop ();
 
     expr->set_print_flag (false);
 
-    fcn_scope->mark_static ();
+    fcn_scope.mark_static ();
 
     tree_anon_fcn_handle *retval
       = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
@@ -2480,7 +2477,7 @@
 
     std::string scope_name = buf.str ();
 
-    fcn_scope->cache_name (scope_name);
+    fcn_scope.cache_name (scope_name);
 
     // FIXME: Stash the filename.  This does not work and produces
     // errors when executed.
@@ -3269,9 +3266,9 @@
 
     cmds->append (end_script);
 
-    symbol_scope *script_scope = m_lexer.symtab_context.curr_scope ();
-
-    script_scope->cache_name (m_lexer.fcn_file_full_name);
+    symbol_scope script_scope = m_lexer.symtab_context.curr_scope ();
+
+    script_scope.cache_name (m_lexer.fcn_file_full_name);
 
     octave_user_script *script
       = new octave_user_script (m_lexer.fcn_file_full_name,
@@ -3484,8 +3481,8 @@
         if (! file.empty ())
           tmp += ": " + file;
 
-        symbol_scope *fcn_scope = fcn->scope ();
-        fcn_scope->cache_name (tmp);
+        symbol_scope fcn_scope = fcn->scope ();
+        fcn_scope.cache_name (tmp);
 
         if (lc)
           fcn->stash_leading_comment (lc);
@@ -3500,21 +3497,21 @@
 
             if (m_endfunction_found && m_function_scopes.size () > 1)
               {
-                symbol_scope *pscope = m_function_scopes.parent_scope ();
-
-                pscope->install_nestfunction (nm, ov_fcn);
+                symbol_scope pscope = m_function_scopes.parent_scope ();
+
+                pscope.install_nestfunction (nm, ov_fcn);
               }
             else
               {
                 fcn->mark_as_subfunction ();
                 m_subfunction_names.push_back (nm);
 
-                m_primary_fcn_scope->install_subfunction (nm, ov_fcn);
+                m_primary_fcn_scope.install_subfunction (nm, ov_fcn);
                }
           }
 
         if (m_curr_fcn_depth == 1)
-          fcn_scope->update_nest ();
+          fcn_scope.update_nest ();
 
         if (! m_lexer.reading_fcn_file && m_curr_fcn_depth == 1)
           {
@@ -3814,7 +3811,7 @@
             // Create a dummy function that is used until the real method
             // is loaded.
 
-            retval = new octave_user_function (nullptr, pl);
+            retval = new octave_user_function (symbol_scope (), pl);
 
             retval->stash_function_name (mname);
 
@@ -5421,10 +5418,10 @@
 
                     if (expr->is_identifier ())
                       {
-                        octave::symbol_scope *scope = tw.get_current_scope ();
+                        octave::symbol_scope scope = tw.get_current_scope ();
 
                         octave::symbol_record::context_id context
-                          = scope->current_context ();
+                          = scope.current_context ();
 
                         tree_identifier *id
                           = dynamic_cast<tree_identifier *> (expr);
@@ -5671,10 +5668,10 @@
       if (octave::is_keyword (nm))
         error ("assignin: invalid assignment to keyword '%s'", nm.c_str ());
 
-      octave::symbol_scope *scope = interp.get_current_scope ();
+      octave::symbol_scope scope = interp.get_current_scope ();
 
       if (scope)
-        scope->assign (nm, args(2));
+        scope.assign (nm, args(2));
     }
   else
     error ("assignin: invalid variable name in argument VARNAME");
--- a/libinterp/parse-tree/parse.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/parse.h	Mon Nov 27 01:12:05 2017 -0500
@@ -101,7 +101,7 @@
     {
     public:
 
-      typedef std::pair<symbol_scope*, std::string> value_type;
+      typedef std::pair<symbol_scope, std::string> value_type;
 
       typedef std::deque<value_type>::iterator iterator;
       typedef std::deque<value_type>::const_iterator const_iterator;
@@ -121,7 +121,7 @@
 
       void push (const value_type& elt);
 
-      void push (symbol_scope *id);
+      void push (const symbol_scope& id);
 
       void pop (void);
 
@@ -129,7 +129,7 @@
 
       bool name_current_scope (const std::string& name);
 
-      symbol_scope *parent_scope (void) const;
+      symbol_scope parent_scope (void) const;
 
       std::string parent_name (void) const;
 
@@ -448,7 +448,7 @@
 
     // Scope where we install all subfunctions and nested functions.  Only
     // used while reading function files.
-    symbol_scope *m_primary_fcn_scope;
+    symbol_scope m_primary_fcn_scope;
 
     // Name of the current class when we are parsing class methods or
     // constructors.
--- a/libinterp/parse-tree/pt-eval.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-eval.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -92,20 +92,23 @@
     tree_parameter_list *param_list = anon_fh.parameter_list ();
     tree_expression *expr = anon_fh.expression ();
 
-    symbol_scope *af_scope = anon_fh.scope ();
+    symbol_scope af_scope = anon_fh.scope ();
 
     symbol_table& symtab = m_interpreter.get_symbol_table ();
 
-    symbol_scope *af_parent_scope
-      = anon_fh.has_parent_scope () ? symtab.current_scope () : nullptr;
-
-    symbol_scope *new_scope = af_scope ? af_scope->dup () : nullptr;
+    symbol_scope af_parent_scope;
+    if (anon_fh.has_parent_scope ())
+      af_parent_scope = symtab.current_scope ();
+
+    symbol_scope new_scope;
+    if (af_scope)
+      new_scope = af_scope.dup ();
 
     if (new_scope && af_parent_scope)
-      new_scope->inherit (af_parent_scope);
+      new_scope.inherit (af_parent_scope);
 
     tree_parameter_list *param_list_dup
-      = param_list ? param_list->dup (*new_scope) : nullptr;
+      = param_list ? param_list->dup (new_scope) : nullptr;
 
     tree_parameter_list *ret_list = nullptr;
 
@@ -113,7 +116,7 @@
 
     if (expr)
       {
-        tree_expression *expr_dup = expr->dup (*new_scope);
+        tree_expression *expr_dup = expr->dup (new_scope);
         tree_statement *stmt = new tree_statement (expr_dup, nullptr);
         stmt_list = new tree_statement_list (stmt);
       }
@@ -122,7 +125,7 @@
       = new octave_user_function (new_scope, param_list_dup, ret_list,
                                   stmt_list);
 
-    new_scope->set_parent (af_parent_scope);
+    new_scope.set_parent (af_parent_scope);
 
     octave_function *curr_fcn = m_call_stack.current ();
 
@@ -582,9 +585,9 @@
       return varargout;
     else if (nargout <= len)
       {
-        symbol_scope *scope = get_current_scope ();
-
-        symbol_record::context_id context = scope->current_context ();
+        symbol_scope scope = get_current_scope ();
+
+        symbol_record::context_id context = scope.current_context ();
 
         octave_value_list retval (nargout);
 
@@ -673,7 +676,7 @@
     return false;
   }
 
-  symbol_scope *
+  symbol_scope
   tree_evaluator::get_current_scope (void)
   {
     symbol_table& symtab = m_interpreter.get_symbol_table ();
@@ -1029,10 +1032,10 @@
         // Make sure that any variable with the same name as the new
         // function is cleared.
 
-        symbol_scope *scope = symtab.current_scope ();
+        symbol_scope scope = symtab.current_scope ();
 
         if (scope)
-          scope->assign (nm);
+          scope.assign (nm);
       }
   }
 
@@ -1041,9 +1044,9 @@
   {
     octave_value_list retval;
 
-    symbol_scope *scope = get_current_scope ();
-
-    symbol_record::context_id context = scope->current_context ();
+    symbol_scope scope = get_current_scope ();
+
+    symbol_record::context_id context = scope.current_context ();
 
     symbol_record sym = expr.symbol ();
 
@@ -1156,10 +1159,10 @@
   // FIXME: make this a member function for direct access to symbol
   // table and scope?
 
-  octave::symbol_scope *scope
+  octave::symbol_scope scope
     = octave::__require_current_scope__ ("final_index_error");
 
-  octave::symbol_record::context_id context = scope->current_context ();
+  octave::symbol_record::context_id context = scope.current_context ();
 
   if (expr->is_identifier ()
       && dynamic_cast<const octave::tree_identifier *> (expr)->is_variable (context))
@@ -1288,9 +1291,9 @@
       {
         tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
 
-        symbol_scope *scope = get_current_scope ();
-
-        symbol_record::context_id context = scope->current_context ();
+        symbol_scope scope = get_current_scope ();
+
+        symbol_record::context_id context = scope.current_context ();
 
         if (! id->is_variable (context))
           {
@@ -2278,9 +2281,9 @@
 
                 if (expr->is_identifier ())
                   {
-                    symbol_scope *scope = get_current_scope ();
-
-                    symbol_record::context_id context = scope->current_context ();
+                    symbol_scope scope = get_current_scope ();
+
+                    symbol_record::context_id context = scope.current_context ();
 
                     tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
 
@@ -2738,9 +2741,9 @@
           }
         else
           {
-            symbol_scope *scope = get_current_scope ();
-
-            scope->force_assign (ans, val);
+            symbol_scope scope = get_current_scope ();
+
+            scope.force_assign (ans, val);
 
             if (print)
               {
--- a/libinterp/parse-tree/pt-eval.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-eval.h	Mon Nov 27 01:12:05 2017 -0500
@@ -313,7 +313,7 @@
 
     profiler& get_profiler (void) { return m_profiler; }
 
-    symbol_scope *get_current_scope (void);
+    symbol_scope get_current_scope (void);
 
     int max_recursion_depth (void) const { return m_max_recursion_depth; }
 
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -59,7 +59,6 @@
   {
     delete m_parameter_list;
     delete m_expression;
-    delete m_scope;
   }
 
   tree_expression *
@@ -68,13 +67,16 @@
     tree_parameter_list *param_list = parameter_list ();
     tree_expression *expr = expression ();
 
-    symbol_scope *af_scope = m_scope;
-    symbol_scope *af_parent_scope = m_parent_scope;
+    symbol_scope af_scope = m_scope;
+    symbol_scope af_parent_scope = m_parent_scope;
 
     symbol_table& symtab
       = __get_symbol_table__ ("tree_anon_fcn_handle::dup");
 
-    symbol_scope *new_scope = af_scope ? af_scope->dup () : nullptr;
+    symbol_scope new_scope;
+
+    if (af_scope)
+      new_scope = af_scope.dup ();
 
     // FIXME: why should we inherit from the current scope here?  That
     // doesn't seem right, but with the way things work now it appears
@@ -86,8 +88,8 @@
     // FIXME: if new scope is nullptr, then we are in big trouble here...
 
     tree_anon_fcn_handle *new_afh = new
-      tree_anon_fcn_handle (param_list ? param_list->dup (*new_scope) : nullptr,
-                            expr ? expr->dup (*new_scope) : nullptr,
+      tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : nullptr,
+                            expr ? expr->dup (new_scope) : nullptr,
                             new_scope, af_parent_scope, line (), column ());
 
     new_afh->copy_base (*this);
--- a/libinterp/parse-tree/pt-fcn-handle.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Mon Nov 27 01:12:05 2017 -0500
@@ -92,13 +92,13 @@
 
     tree_anon_fcn_handle (int l = -1, int c = -1)
       : tree_expression (l, c), m_parameter_list (nullptr),
-        m_expression (nullptr), m_scope (nullptr), m_parent_scope (nullptr),
+        m_expression (nullptr), m_scope (), m_parent_scope (),
         m_file_name ()
     { }
 
     tree_anon_fcn_handle (tree_parameter_list *pl, tree_expression *ex,
-                          symbol_scope *scope,
-                          symbol_scope *parent_scope,
+                          const symbol_scope& scope,
+                          const symbol_scope& parent_scope,
                           int l = -1, int c = -1)
       : tree_expression (l, c), m_parameter_list (pl), m_expression (ex),
         m_scope (scope), m_parent_scope (parent_scope), m_file_name ()
@@ -123,11 +123,11 @@
 
     tree_expression * expression (void) const { return m_expression; }
 
-    symbol_scope *scope (void) const { return m_scope; }
+    symbol_scope scope (void) const { return m_scope; }
 
-    symbol_scope *parent_scope (void) const { return m_parent_scope; }
+    symbol_scope parent_scope (void) const { return m_parent_scope; }
 
-    bool has_parent_scope (void) const { return m_parent_scope; }
+    bool has_parent_scope (void) const { return m_parent_scope.is_valid (); }
 
     tree_expression * dup (symbol_scope& scope) const;
 
@@ -146,10 +146,10 @@
     tree_expression *m_expression;
 
     // Function scope.
-    symbol_scope *m_scope;
+    symbol_scope m_scope;
 
-    // Parent scope, or 0 if none.
-    symbol_scope *m_parent_scope;
+    // Parent scope, or an invalid scope if none.
+    symbol_scope m_parent_scope;
 
     // Filename where the handle was defined.
     std::string m_file_name;
--- a/libinterp/parse-tree/pt-id.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-id.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -40,11 +40,11 @@
 
   class tree_evaluator;
 
-  void tree_identifier::link_to_global (symbol_scope *global_scope,
+  void tree_identifier::link_to_global (const symbol_scope& global_scope,
                                         const symbol_record& global_sym)
   {
     if (! sym.is_global ())
-      sym.bind_fwd_rep (global_scope, global_sym);
+      sym.bind_fwd_rep (global_scope.get_rep (), global_sym);
   }
 
   void
@@ -70,9 +70,9 @@
     if (sym.is_added_static ())
       static_workspace_error ();
 
-    symbol_scope *scope = tw->get_current_scope ();
+    symbol_scope scope = tw->get_current_scope ();
 
-    return octave_lvalue (sym, scope->current_context ());
+    return octave_lvalue (sym, scope.current_context ());
   }
 
   tree_identifier *
--- a/libinterp/parse-tree/pt-id.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-id.h	Mon Nov 27 01:12:05 2017 -0500
@@ -105,7 +105,7 @@
       return sym.find (context, args);
     }
 
-    void link_to_global (symbol_scope *global_scope,
+    void link_to_global (const symbol_scope& global_scope,
                          const symbol_record& global_sym);
 
     void mark_persistent (void) { sym.init_persistent (); }
--- a/libinterp/parse-tree/pt-jit.cc	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-jit.cc	Mon Nov 27 01:12:05 2017 -0500
@@ -797,7 +797,7 @@
           {
             tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
 
-            do_bind_ans = (! id->is_variable (scope->current_context ()));
+            do_bind_ans = (! id->is_variable (scope.current_context ()));
           }
         else
           do_bind_ans = (! expr->is_assignment_expression ());
@@ -1088,7 +1088,7 @@
   }
 
   void
-  jit_convert::initialize (symbol_scope *s)
+  jit_convert::initialize (const symbol_scope& s)
   {
     scope = s;
     iterator_count = 0;
@@ -1144,7 +1144,7 @@
       return create_variable (vname, jit_typeinfo::get_any (), false);
     else
       {
-        octave_value val = record.varval (scope->current_context ());
+        octave_value val = record.varval (scope.current_context ());
         if (val.is_undefined ())
           val = symtab.find_function (vname);
 
@@ -2680,7 +2680,7 @@
 
     function (&real_arguments[0]);
 
-    symbol_table& symtab = __get_symbol_table__ ("jit_info::execute");
+    symbol_scope scope = __require_current_scope__ ("jit_info::execute");
 
     for (size_t i = 0; i < arguments.size (); ++i)
       {
@@ -2688,7 +2688,7 @@
 
         // do not store for loop bounds temporary
         if (name.size () && name[0] != '#')
-          symtab.assign (arguments[i].first, real_arguments[i]);
+          scope.assign (arguments[i].first, real_arguments[i]);
       }
 
     octave_quit ();
@@ -2803,9 +2803,9 @@
 
     if (iter == extra_vars.end ())
       {
-        symbol_scope *scope = __require_current_scope__ ("jit_convert::find");
-
-        return scope->varval (vname);
+        symbol_scope scope = __require_current_scope__ ("jit_convert::find");
+
+        return scope.varval (vname);
       }
     else
       return *iter->second;
--- a/libinterp/parse-tree/pt-jit.h	Tue Dec 05 11:35:11 2017 -0800
+++ b/libinterp/parse-tree/pt-jit.h	Mon Nov 27 01:12:05 2017 -0500
@@ -179,7 +179,7 @@
     bool converting_function;
 
     // the scope of the function we are converting, or the current scope
-    symbol_scope *scope;
+    symbol_scope scope;
 
     jit_factory factory;
 
@@ -204,7 +204,7 @@
 
     variable_map vmap;
 
-    void initialize (symbol_scope *s);
+    void initialize (const symbol_scope& s);
 
     jit_call * create_checked_impl (jit_call *ret);