changeset 28710:68c792e54d19

check and mark private status when reloading functions (bug #40117) * fcn-info.cc (load_out_of_date_fcn): Look at function location to determine private status and class membership. Store status in loaded function. * test/bug-40117.tst: New file. * test/module.mk: Update.
author John W. Eaton <jwe@octave.org>
date Thu, 10 Sep 2020 11:36:50 -0400
parents 9dc9f15dac64
children e8b7863a7e6b
files libinterp/corefcn/fcn-info.cc test/bug-40117.tst test/module.mk
diffstat 3 files changed, 117 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/fcn-info.cc	Thu Sep 10 17:49:43 2020 +0200
+++ b/libinterp/corefcn/fcn-info.cc	Thu Sep 10 11:36:50 2020 -0400
@@ -409,21 +409,59 @@
   // would not check for it when finding symbol definitions.
 
   static inline bool
-  load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
+  load_out_of_date_fcn (const std::string& file_name,
+                        const std::string& dir_name_arg,
                         octave_value& function,
                         const std::string& dispatch_type = "",
                         const std::string& package_name = "")
   {
     bool retval = false;
 
+    std::string dir_name = dir_name_arg;
+
+    if (dir_name.empty ())
+      {
+        size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
+
+        dir_name = file_name.substr (0, pos);
+      }
+
+    // FIXME: do the following job of determining private status and
+    // class membership in a separate function?
+
+    size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());
+
+    bool is_private_fcn
+      = pos != std::string::npos && dir_name.substr (pos+1) == "private";
+
+    if (is_private_fcn)
+      dir_name = dir_name.substr (0, pos);
+
+    std::string class_name;
+
+    pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());
+
+    if (pos != std::string::npos)
+      {
+        std::string tmp = dir_name.substr (pos+1);
+
+        if (tmp[0] == '@')
+          class_name = tmp.substr (1);
+      }
+
     octave_value ov_fcn
-      = load_fcn_from_file (ff, dir_name, dispatch_type,
+      = load_fcn_from_file (file_name, dir_name, dispatch_type,
                             package_name);
 
     if (ov_fcn.is_defined ())
       {
         retval = true;
 
+        octave_function *fcn = ov_fcn.function_value ();
+
+        if (is_private_fcn)
+          fcn->mark_as_private_function (class_name);
+
         function = ov_fcn;
       }
     else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-40117.tst	Thu Sep 10 11:36:50 2020 -0400
@@ -0,0 +1,76 @@
+########################################################################
+##
+## Copyright (C) 2020 The Octave Project Developers
+##
+## See the file COPYRIGHT.md in the top-level directory of this
+## distribution or <https://octave.org/copyright/>.
+##
+## This file is part of Octave.
+##
+## Octave is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, see
+## <https://www.gnu.org/licenses/>.
+##
+########################################################################
+
+%!function __mktestfun_40117__ (file, varargin)
+%!  unwind_protect
+%!    fid = fopen (file, "w");
+%!    fprintf (fid, "%s\n", varargin{:});
+%!  unwind_protect_cleanup
+%!    if (fid > 0)
+%!      fclose (fid);
+%!    endif
+%!  end_unwind_protect
+%!endfunction
+
+%!test <40117>
+%! unwind_protect
+%!   tmp_dir = tempname ();
+%!   mkdir (tmp_dir);
+%!   a_dir = fullfile (tmp_dir, "a");
+%!   a_private_dir = fullfile (a_dir, "private");
+%!   mkdir (a_dir);
+%!   mkdir (a_private_dir);
+%!   __mktestfun_40117__ (fullfile (a_dir, "main_40117.m"),
+%!                        "function r = main_40117 ()",
+%!                        "  r = p1_40117 ();",
+%!                        "endfunction");
+%!   __mktestfun_40117__ (fullfile (a_private_dir, "p1_40117.m"),
+%!                        "function r = p1_40117 ()",
+%!                        "  r = p2_40117 ();",
+%!                        "endfunction");
+%!   __mktestfun_40117__ (fullfile (a_private_dir, "p2_40117.m"),
+%!                        "function r = p2_40117 ()",
+%!                        "  r = 'a_p2_40117';",
+%!                        "endfunction");
+%!   addpath (a_dir);
+%!   assert (main_40117 (), "a_p2_40117");
+%!
+%!   ## Update the secondary private function, attempting to avoid
+%!   ## filesystem timestamp resolution problems.
+%!   pause (1);
+%!   __mktestfun_40117__ (fullfile (a_private_dir, "p2_40117.m"),
+%!                        "function r = p2_40117 ()",
+%!                        "  r = 'new function!';",
+%!                        "endfunction");
+%!
+%!   ## Force new functions to be found.
+%!   rehash ();
+%!
+%!   assert (main_40117 (), "new function!");
+%! unwind_protect_cleanup
+%!   rmpath (a_dir);
+%!   confirm_recursive_rmdir (false, "local");
+%!   rmdir (tmp_dir, "s");
+%! end_unwind_protect
--- a/test/module.mk	Thu Sep 10 17:49:43 2020 +0200
+++ b/test/module.mk	Thu Sep 10 11:36:50 2020 -0400
@@ -8,6 +8,7 @@
   %reldir%/fntests.m \
   %reldir%/args.tst \
   %reldir%/bug-31371.tst \
+  %reldir%/bug-40117.tst \
   %reldir%/bug-45969.tst \
   %reldir%/bug-45972.tst \
   %reldir%/bug-46330.tst \