diff --git a/libinterp/corefcn/fcn-info.cc b/libinterp/corefcn/fcn-info.cc --- a/libinterp/corefcn/fcn-info.cc +++ b/libinterp/corefcn/fcn-info.cc @@ -377,6 +377,12 @@ namespace octave octave_user_function *current_fcn = search_scope ? search_scope.function () : nullptr; + if (search_scope.is_deleted () && current_fcn) + { + std::string nm = search_scope.name (); + error ("scope '%s' was deleted but current_fcn is valid?", nm.c_str ()); + } + // Subfunction. I think it only makes sense to check for // subfunctions if we are currently executing a function defined // from a .m file. diff --git a/libinterp/corefcn/symscope.h b/libinterp/corefcn/symscope.h --- a/libinterp/corefcn/symscope.h +++ b/libinterp/corefcn/symscope.h @@ -67,7 +67,7 @@ namespace octave : m_name (name), m_symbols (), m_subfunctions (), m_persistent_values (), m_fcn (nullptr), m_parent (), m_primary_parent (), m_children (), m_nesting_depth (0), - m_is_static (false) + m_is_static (false), m_deleted (false) { // All scopes have ans as the first symbol, initially undefined. @@ -102,6 +102,10 @@ namespace octave void mark_static (void) { m_is_static = true; } + bool is_deleted (void) const { return m_deleted; } + + void mark_deleted (void) { m_deleted = true; } + std::shared_ptr parent_scope_rep (void) const { return m_parent.lock (); @@ -131,6 +135,7 @@ namespace octave new_sid->m_children = m_children; new_sid->m_nesting_depth = m_nesting_depth; new_sid->m_is_static = m_is_static; + new_sid->m_deleted = m_deleted; return new_sid; } @@ -244,7 +249,10 @@ namespace octave void cache_name (const std::string& name) { m_name = name; } - octave_user_function *function (void) const { return m_fcn; } + octave_user_function *function (void) const + { + return m_deleted ? nullptr : m_fcn; + } void set_function (octave_user_function *fcn) { m_fcn = fcn; } @@ -320,6 +328,11 @@ namespace octave //! If true then no variables can be added. bool m_is_static; + + //! If true then this scope is no longer valid, most likely because + //! function containing it was deleted. + + bool m_deleted; }; class symbol_scope @@ -395,6 +408,17 @@ namespace octave m_rep->mark_static (); } + bool is_deleted (void) const + { + return m_rep ? m_rep->is_deleted () : false; + } + + void mark_deleted (void) + { + if (m_rep) + m_rep->mark_deleted (); + } + std::shared_ptr parent_scope (void) const { return m_rep ? m_rep->parent_scope_rep () : nullptr; diff --git a/libinterp/octave-value/ov-usr-fcn.cc b/libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc +++ b/libinterp/octave-value/ov-usr-fcn.cc @@ -64,6 +64,8 @@ static bool Voptimize_subsasgn_calls = t octave_user_code::~octave_user_code (void) { + m_scope.mark_deleted (); + // FIXME: shouldn't this happen automatically when deleting cmd_list? if (cmd_list) cmd_list->remove_all_breakpoints (file_name);