changeset 32864:2e26c017d9c9 bytecode-interpreter

maint: merge default to bytecode-interpreter
author John W. Eaton <jwe@octave.org>
date Fri, 26 Jan 2024 16:25:50 -0500
parents 68614372c504 (current diff) 0c9675a32703 (diff)
children cc7dec89dee2
files test/Makefile.am
diffstat 30 files changed, 198 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/fcn-info.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/corefcn/fcn-info.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -972,28 +972,33 @@
   auto q = class_methods.find (dispatch_type);
 
   if (q == class_methods.end ())
-    {
-      octave_value val = load_class_method (dispatch_type);
-
-      if (val.is_defined ())
-        return val;
-    }
+    retval = load_class_method (dispatch_type);
   else
     {
-      octave_value& fval = q->second;
+      retval = q->second;
 
-      if (fval.is_defined ())
-        out_of_date_check (fval, dispatch_type);
+      if (retval.is_defined ())
+        out_of_date_check (retval, dispatch_type);
+
+      if (! retval.is_defined ())
+        retval = load_class_method (dispatch_type);
+    }
 
-      if (fval.is_defined ())
-        return fval;
-      else
-        {
-          octave_value val = load_class_method (dispatch_type);
+  // Ignore any classdef constructors that were found by
+  // load_class_method above, either for dispatch_type or any
+  // superclasses of that class.
 
-          if (val.is_defined ())
-            return val;
-        }
+  // FIXME: Maybe there is a better way of managing classdef
+  // constructors (which may actually be octave_classdef_meta objects)
+  // so they don't appear in both the class_methods and
+  // class_constructors maps?
+
+  if (retval.is_classdef_meta ())
+    {
+      octave_function *fcn = retval.function_value ();
+
+      if (fcn && fcn->is_classdef_constructor (dispatch_type))
+        retval = octave_value ();
     }
 
   return retval;
--- a/libinterp/corefcn/mex.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/corefcn/mex.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -47,7 +47,6 @@
 #include <string>
 
 #include "f77-fcn.h"
-#include "lo-ieee.h"
 #include "oct-locbuf.h"
 #include "quit.h"
 
@@ -3559,19 +3558,19 @@
 bool
 mxIsFinite (const double v)
 {
-  return lo_ieee_isfinite (v) != 0;
+  return octave::math::isfinite (v) != 0;
 }
 
 bool
 mxIsInf (const double v)
 {
-  return lo_ieee_isinf (v) != 0;
+  return octave::math::isinf (v) != 0;
 }
 
 bool
 mxIsNaN (const double v)
 {
-  return lo_ieee_isnan (v) != 0;
+  return octave::math::isnan (v) != 0;
 }
 
 double
--- a/libinterp/corefcn/oct-stream.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/corefcn/oct-stream.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -110,7 +110,7 @@
 
   if (! conv_err)
     {
-      if (! lo_ieee_isnan (dval))
+      if (! math::isnan (dval))
         {
           int ival = math::nint (dval);
 
@@ -131,7 +131,7 @@
 {
   octave_idx_type retval = -1;
 
-  if (lo_ieee_isnan (d))
+  if (math::isnan (d))
     ::error ("%s: NaN invalid as size specification", who.c_str ());
 
   if (math::isinf (d))
@@ -5817,7 +5817,7 @@
         }
 
       const char *tval;
-      if (lo_ieee_isinf (dval))
+      if (math::isinf (dval))
         {
           if (elt->flags.find ('+') != std::string::npos)
             tval = (dval < 0 ? "-Inf" : "+Inf");
--- a/libinterp/corefcn/pr-output.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/corefcn/pr-output.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -1546,7 +1546,7 @@
   if (! bank_format)
     {
       T i = cval.imag ();
-      if (! (hex_format || bit_format) && lo_ieee_signbit (i))
+      if (! (hex_format || bit_format) && std::signbit (i))
         {
           os << " - ";
           i = -i;
--- a/libinterp/octave-value/ov-classdef.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/octave-value/ov-classdef.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -476,6 +476,29 @@
             retval = true;
         }
     }
+  else if (m_object.is_method ())
+    {
+      octave::cdef_method meth (m_object);
+
+      if (meth.is_constructor ())
+        {
+          std::string meth_name = meth.get_name ();
+
+          // Only consider METH to be a constructor if the dispatch
+          // class CNAME is the same as or derived from the class of
+          // METH.
+
+          if (cname == meth_name)
+            retval = true;
+          else
+            {
+              octave::cdef_class meth_cls = octave::lookup_class (meth_name, false, false);
+              octave::cdef_class dispatch_cls = octave::lookup_class (cname, false, false);
+
+              retval = octave::is_superclass (meth_cls, dispatch_cls);
+            }
+        }
+    }
 
   return retval;
 }
--- a/libinterp/octave-value/ov-complex.h	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/octave-value/ov-complex.h	Fri Jan 26 16:25:50 2024 -0500
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "mx-base.h"
 #include "str-vec.h"
 
@@ -85,8 +84,8 @@
   octave_value any (int = 0) const
   {
     return (scalar != Complex (0, 0)
-            && ! (lo_ieee_isnan (scalar.real ())
-                  || lo_ieee_isnan (scalar.imag ())));
+            && ! (octave::math::isnan (scalar.real ())
+                  || octave::math::isnan (scalar.imag ())));
   }
 
   builtin_type_t builtin_type () const { return btyp_complex; }
--- a/libinterp/octave-value/ov-float.h	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/octave-value/ov-float.h	Fri Jan 26 16:25:50 2024 -0500
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 #include "mx-base.h"
@@ -81,7 +80,7 @@
   { return octave::idx_vector (scalar); }
 
   octave_value any (int = 0) const
-  { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
+  { return (scalar != 0 && ! octave::math::isnan (scalar)); }
 
   builtin_type_t builtin_type () const { return btyp_float; }
 
--- a/libinterp/octave-value/ov-flt-complex.h	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/octave-value/ov-flt-complex.h	Fri Jan 26 16:25:50 2024 -0500
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "mx-base.h"
 #include "str-vec.h"
 
@@ -81,8 +80,8 @@
   octave_value any (int = 0) const
   {
     return (scalar != FloatComplex (0, 0)
-            && ! (lo_ieee_isnan (scalar.real ())
-                  || lo_ieee_isnan (scalar.imag ())));
+            && ! (octave::math::isnan (scalar.real ())
+                  || octave::math::isnan (scalar.imag ())));
   }
 
   builtin_type_t builtin_type () const { return btyp_float_complex; }
--- a/libinterp/octave-value/ov-scalar.h	Thu Jan 25 20:45:16 2024 +0100
+++ b/libinterp/octave-value/ov-scalar.h	Fri Jan 26 16:25:50 2024 -0500
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 #include "mx-base.h"
@@ -80,7 +79,7 @@
   { return octave::idx_vector (scalar); }
 
   octave_value any (int = 0) const
-  { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
+  { return (scalar != 0 && ! octave::math::isnan (scalar)); }
 
   builtin_type_t builtin_type () const { return btyp_double; }
 
--- a/liboctave/array/dSparse.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/array/dSparse.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -7186,7 +7186,7 @@
   if (neg_zero)
     {
       for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (data (i)))
+        if (octave::math::signbit (data (i)))
           return true;
     }
   else
--- a/liboctave/external/Faddeeva/Faddeeva.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/external/Faddeeva/Faddeeva.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -184,10 +184,7 @@
 #  define FADDEEVA_RE(name) Faddeeva::name
 
 // isnan/isinf were introduced in C++11
-#  if defined (lo_ieee_isnan) && defined (lo_ieee_isinf)
-#    define isnan lo_ieee_isnan
-#    define isinf lo_ieee_isinf
-#  elif (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF))
+#  if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF))
 static inline bool my_isnan(double x) { return x != x; }
 #    define isnan my_isnan
 static inline bool my_isinf(double x) { return 1/x == 0.; }
--- a/liboctave/numeric/lo-mappers.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/numeric/lo-mappers.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -178,9 +178,9 @@
 }
 
 bool
-negative_sign (double x) { return __lo_ieee_signbit (x); }
+negative_sign (double x) { return signbit (x); }
 bool
-negative_sign (float x) { return __lo_ieee_float_signbit (x); }
+negative_sign (float x) { return signbit (x); }
 
 // Sometimes you need a large integer, but not always.
 
--- a/liboctave/numeric/oct-norm.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/numeric/oct-norm.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -357,7 +357,7 @@
     FCN_NAME (v, res, norm_accumulator_2<R> ());              \
   else if (p == 1)                                            \
     FCN_NAME (v, res, norm_accumulator_1<R> ());              \
-  else if (lo_ieee_isinf (p))                                 \
+  else if (math::isinf (p))                                   \
     {                                                         \
       if (p > 0)                                              \
         FCN_NAME (v, res, norm_accumulator_inf<R> ());        \
@@ -551,7 +551,7 @@
     }
   else if (p == 1)
     res = xcolnorms (m, static_cast<R> (1)).max ();
-  else if (lo_ieee_isinf (p) && p > 1)
+  else if (math::isinf (p) && p > 1)
     res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
@@ -573,7 +573,7 @@
   R res = 0;
   if (p == 1)
     res = xcolnorms (m, static_cast<R> (1)).max ();
-  else if (lo_ieee_isinf (p) && p > 1)
+  else if (math::isinf (p) && p > 1)
     res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
--- a/liboctave/numeric/randgamma.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/numeric/randgamma.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -87,6 +87,7 @@
 #include <cmath>
 
 #include "lo-ieee.h"
+#include "lo-mappers.h"
 #include "randgamma.h"
 #include "randmtzig.h"
 
@@ -100,7 +101,7 @@
   const T c = 1./std::sqrt (9.*d);
 
   /* Handle invalid cases */
-  if (a <= 0 || lo_ieee_isinf (a))
+  if (a <= 0 || math::isinf (a))
     {
       for (i=0; i < n; i++)
         r[i] = numeric_limits<T>::NaN ();
--- a/liboctave/numeric/randpoisson.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/numeric/randpoisson.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -36,6 +36,7 @@
 #include "f77-fcn.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
+#include "lo-mappers.h"
 #include "randmtzig.h"
 #include "randpoisson.h"
 
@@ -404,7 +405,7 @@
 {
   double L = L_arg;
   octave_idx_type i;
-  if (L < 0.0 || lo_ieee_isinf (L))
+  if (L < 0.0 || math::isinf (L))
     {
       for (i=0; i<n; i++)
         p[i] = numeric_limits<T>::NaN ();
@@ -461,7 +462,7 @@
       /* numerical recipes */
       poisson_rejection<T> (L, &ret, 1);
     }
-  else if (lo_ieee_isinf (L))
+  else if (math::isinf (L))
     {
       /* FIXME: R uses NaN, but the normal approximation suggests that
        * limit should be Inf.  Which is correct? */
--- a/liboctave/util/lo-ieee.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/util/lo-ieee.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -60,7 +60,7 @@
 {
   lo_ieee_double t;
   t.value = x;
-  return (__lo_ieee_isnan (x) && t.word[lo_ieee_hw] == LO_IEEE_NA_HW
+  return (std::isnan (x) && t.word[lo_ieee_hw] == LO_IEEE_NA_HW
           && t.word[lo_ieee_lw] == LO_IEEE_NA_LW) ? 1 : 0;
 }
 
@@ -93,7 +93,7 @@
 {
   lo_ieee_float t;
   t.value = x;
-  return (__lo_ieee_float_isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;
+  return (std::isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;
 }
 
 float
--- a/liboctave/util/lo-ieee.h	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/util/lo-ieee.h	Fri Jan 26 16:25:50 2024 -0500
@@ -28,10 +28,12 @@
 
 #include "octave-config.h"
 
-#include <cmath>
+#if defined (__cplusplus)
+#  include <cmath>
 
-#if defined (__cplusplus)
 extern "C" {
+#else
+#  include <math.h>
 #endif
 
 /*  Octave's idea of infinity.  */
@@ -67,31 +69,61 @@
   unsigned int word;
 } lo_ieee_float;
 
-extern OCTAVE_API void octave_ieee_init ();
+extern OCTAVE_API void octave_ieee_init (void);
 
+#if defined (__cplusplus)
+OCTAVE_DEPRECATED (10, "use std::isnan instead")
 inline int __lo_ieee_isnan (double x) { return std::isnan (x); }
+OCTAVE_DEPRECATED (10, "use std::isfinite instead")
 inline int __lo_ieee_isfinite (double x) { return std::isfinite (x); }
+OCTAVE_DEPRECATED (10, "use std::isinf instead")
 inline int __lo_ieee_isinf (double x) { return std::isinf (x); }
 
+OCTAVE_DEPRECATED (10, "use std::signbit instead")
+inline int __lo_ieee_signbit (double x) { return std::signbit (x); }
+
+OCTAVE_DEPRECATED (10, "use std::isnan instead")
+inline int __lo_ieee_float_isnan (float x) { return std::isnan (x); }
+OCTAVE_DEPRECATED (10, "use std::isfinite instead")
+inline int __lo_ieee_float_isfinite (float x) { return std::isfinite (x); }
+OCTAVE_DEPRECATED (10, "use std::isinf instead")
+inline int __lo_ieee_float_isinf (float x) { return std::isinf (x); }
+
+OCTAVE_DEPRECATED (10, "use std::signbit instead")
+inline int __lo_ieee_float_signbit (float x) { return std::signbit (x); }
+#else
+OCTAVE_DEPRECATED (10, "use isnan instead")
+inline int __lo_ieee_isnan (double x) { return isnan (x); }
+OCTAVE_DEPRECATED (10, "use isfinite instead")
+inline int __lo_ieee_isfinite (double x) { return isfinite (x); }
+OCTAVE_DEPRECATED (10, "use isinf instead")
+inline int __lo_ieee_isinf (double x) { return isinf (x); }
+
+OCTAVE_DEPRECATED (10, "use signbit instead")
+inline int __lo_ieee_signbit (double x) { return signbit (x); }
+
+OCTAVE_DEPRECATED (10, "use isnan instead")
+inline int __lo_ieee_float_isnan (float x) { return isnan (x); }
+OCTAVE_DEPRECATED (10, "use isfinite instead")
+inline int __lo_ieee_float_isfinite (float x) { return isfinite (x); }
+OCTAVE_DEPRECATED (10, "use isinf instead")
+inline int __lo_ieee_float_isinf (float x) { return isinf (x); }
+
+OCTAVE_DEPRECATED (10, "use signbit instead")
+inline int __lo_ieee_float_signbit (float x) { return signbit (x); }
+#endif
+
 extern OCTAVE_API int __lo_ieee_is_NA (double);
 
-extern OCTAVE_API double lo_ieee_inf_value ();
-extern OCTAVE_API double lo_ieee_na_value ();
-extern OCTAVE_API double lo_ieee_nan_value ();
-
-inline int __lo_ieee_signbit (double x) { return std::signbit (x); }
-
-inline int __lo_ieee_float_isnan (float x) { return std::isnan (x); }
-inline int __lo_ieee_float_isfinite (float x) { return std::isfinite (x); }
-inline int __lo_ieee_float_isinf (float x) { return std::isinf (x); }
+extern OCTAVE_API double lo_ieee_inf_value (void);
+extern OCTAVE_API double lo_ieee_na_value (void);
+extern OCTAVE_API double lo_ieee_nan_value (void);
 
 extern OCTAVE_API int __lo_ieee_float_is_NA (float);
 
-extern OCTAVE_API float lo_ieee_float_inf_value ();
-extern OCTAVE_API float lo_ieee_float_na_value ();
-extern OCTAVE_API float lo_ieee_float_nan_value ();
-
-inline int __lo_ieee_float_signbit (float x) { return std::signbit (x); }
+extern OCTAVE_API float lo_ieee_float_inf_value (void);
+extern OCTAVE_API float lo_ieee_float_na_value (void);
+extern OCTAVE_API float lo_ieee_float_nan_value (void);
 
 #if defined (__cplusplus)
 }
@@ -113,10 +145,6 @@
   (sizeof (x) == sizeof (float)                         \
    ? __lo_ieee_float_is_NA (x) : __lo_ieee_is_NA (x))
 
-#define lo_ieee_is_NaN_or_NA(x)                                         \
-  (sizeof (x) == sizeof (float)                                         \
-   ? __lo_ieee_float_is_NaN_or_NA (x) : __lo_ieee_is_NaN_or_NA (x))
-
 #define lo_ieee_signbit(x)                                      \
   (sizeof (x) == sizeof (float)                                 \
    ? __lo_ieee_float_signbit (x) : __lo_ieee_signbit (x))
--- a/liboctave/util/lo-utils.cc	Thu Jan 25 20:45:16 2024 +0100
+++ b/liboctave/util/lo-utils.cc	Fri Jan 26 16:25:50 2024 -0500
@@ -446,9 +446,9 @@
 {
   if (lo_ieee_is_NA (value))
     os << "NA";
-  else if (lo_ieee_isnan (value))
+  else if (math::isnan (value))
     os << "NaN";
-  else if (lo_ieee_isinf (value))
+  else if (math::isinf (value))
     os << (value < 0 ? "-Inf" : "Inf");
   else
     os << value;
@@ -474,9 +474,9 @@
 {
   if (lo_ieee_is_NA (value))
     os << "NA";
-  else if (lo_ieee_isnan (value))
+  else if (math::isnan (value))
     os << "NaN";
-  else if (lo_ieee_isinf (value))
+  else if (math::isinf (value))
     os << (value < 0 ? "-Inf" : "Inf");
   else
     os << value;
--- a/test/Makefile.am	Thu Jan 25 20:45:16 2024 +0100
+++ b/test/Makefile.am	Fri Jan 26 16:25:50 2024 -0500
@@ -75,6 +75,7 @@
 include bug-38236/module.mk
 include bug-38691/module.mk
 include bug-41723/module.mk
+include bug-44643/module.mk
 include bug-44940/module.mk
 include bug-45351/module.mk
 include bug-46660/module.mk
@@ -83,6 +84,7 @@
 include bug-49379/module.mk
 include bug-50014/module.mk
 include bug-50035/module.mk
+include bug-50395/module.mk
 include bug-50716/module.mk
 include bug-50831/module.mk
 include bug-51192/module.mk
@@ -110,6 +112,7 @@
 include bug-61105/module.mk
 include bug-61191/module.mk
 include bug-63841/module.mk
+include bug-65037/module.mk
 include class-concat/module.mk
 include classdef/module.mk
 include classdef-debug/module.mk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/bug-44643.tst	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,8 @@
+%!test <44643>
+%! a = bug44643 ();
+%! b = bug44643 ();
+%! a.parent = b;
+%! b.child  = a;
+%!
+%! assert (isequal (a, b));
+%! assert (isequal (a, a));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/bug44643.m	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,6 @@
+classdef bug44643 < handle
+  properties
+    child
+    parent
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/module.mk	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,5 @@
+bug_44643_TEST_FILES = \
+  %reldir%/bug-44643.tst \
+  %reldir%/bug44643.m
+
+TEST_FILES += $(bug_44643_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug-50395.tst	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,5 @@
+%!test <50395>
+%! a = bug50395_a ();
+%! clear all
+%! c = 3;
+%! a = bug50395_a ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug50395_a.m	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,6 @@
+classdef bug50395_a < bug50395_c
+  methods
+     function obj = bug50395_a ()
+     end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug50395_c.m	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,2 @@
+classdef bug50395_c
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/module.mk	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,6 @@
+bug_50395_TEST_FILES = \
+  %reldir%/bug-50395.tst \
+  %reldir%/bug50395_a.m \
+  %reldir%/bug50395_c.m
+
+TEST_FILES += $(bug_50395_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-65037/bug-65037.tst	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,9 @@
+%!test <65037>
+%! base_1 = bug65037_base ('base class arg');
+%! derived = bug65037_derived ('derived class arg');
+%! base_2 = bug65037_base (base_1);
+%! base_3 = bug65037_base (derived);
+%! assert (base_1.ctor_nargin, 1);
+%! assert (derived.ctor_nargin, 1);
+%! assert (base_2.ctor_nargin, 1);
+%! assert (base_3.ctor_nargin, 1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-65037/bug65037_base.m	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,10 @@
+classdef bug65037_base
+  properties
+    ctor_nargin;
+  end
+  methods
+    function obj = bug65037_base (varargin)
+      obj.ctor_nargin = nargin;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-65037/bug65037_derived.m	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,7 @@
+classdef bug65037_derived < bug65037_base
+  methods
+    function obj = bug65037_derived (varargin)
+      obj@bug65037_base (varargin{:});
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-65037/module.mk	Fri Jan 26 16:25:50 2024 -0500
@@ -0,0 +1,6 @@
+bug_65037_TEST_FILES = \
+  %reldir%/bug-65037.tst \
+  %reldir%/bug65037_base.m \
+  %reldir%/bug65037_derived.m
+
+TEST_FILES += $(bug_65037_TEST_FILES)