changeset 28012:9a965fec21c1

refactor index_exception classes to accommodate std::exception::what method Since the std::exception::what method returns a pointer to a character buffer, make sure that we will return a pointer that is valid at least until the next non-const method is called for the exception object. * quit.h (execution_exception::message): No longer virtual. * lo-array-errwarn.h, lo-array-errwarn.cc (index_exception::message, index_exception::what, index_exception::idx, index_exception::details): Delete. (index_exception::update_message): New virtual method. Call it in constructors and non-const methods. (invalid_index::details, out_of_range::details): Delete. (invalid_index::update_message, out_of_range::update_message): New functions. * data.cc (index_error): Delete static function. Change all uses to call error directly and to use index_exception::what instead of idx and details. * sub2ind.cc (Find2sub): Use use index_exception::what instead of idx and details. Update test. * utils.cc (dims_to_numel): Use use index_exception::what instead of idx and details. * ov-base-mat.cc (octave_base_matrix<MT>::assign): Consistent with other functions in the same file, use index_exception::set_pos_if_unset and rethrow exception instead of calling err_invalid_index. * ov-complex.cc (complex_index_exception::details): Delete. (complex_index_exception::update_message): New function.
author John W. Eaton <jwe@octave.org>
date Sun, 26 Jan 2020 23:07:45 -0500
parents b31a118729ed
children 0b67847e4f97
files libinterp/corefcn/data.cc libinterp/corefcn/sub2ind.cc libinterp/corefcn/utils.cc libinterp/octave-value/ov-base-mat.cc libinterp/octave-value/ov-complex.cc liboctave/util/lo-array-errwarn.cc liboctave/util/lo-array-errwarn.h liboctave/util/quit.h
diffstat 8 files changed, 58 insertions(+), 77 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/data.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/libinterp/corefcn/data.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -66,12 +66,6 @@
 #include "variables.h"
 #include "xnorm.h"
 
-static void
-index_error (const char *fmt, const std::string& idx, const std::string& msg)
-{
-  error (fmt, idx.c_str (), msg.c_str ());
-}
-
 DEFUN (all, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} all (@var{x})
@@ -7118,8 +7112,7 @@
     }
   catch (const octave::index_exception& e)
     {
-      index_error ("nth_element: invalid N value %s. %s",
-                   e.idx (), e.details ());
+      error ("nth_element: invalid index %s", e.what ());
     }
 
   return retval;
@@ -7218,8 +7211,7 @@
     }
   catch (const octave::index_exception& e)
     {
-      index_error ("__accumarray_sum__: invalid IDX %s. %s",
-                   e.idx (), e.details ());
+      error ("__accumarray_sum__: invalid index %s", e.what ());
     }
 
   return retval;
@@ -7330,8 +7322,7 @@
     }
   catch (const octave::index_exception& e)
     {
-      index_error ("do_accumarray_minmax_fun: invalid index %s. %s",
-                   e.idx (), e.details ());
+      error ("do_accumarray_minmax_fun: invalid index %s", e.what ());
     }
 
   return retval;
@@ -7438,8 +7429,7 @@
     }
   catch (const octave::index_exception& e)
     {
-      index_error ("__accumdim_sum__: invalid IDX %s. %s",
-                   e.idx (), e.details ());
+      error ("__accumdim_sum__: invalid index %s", e.what ());
     }
 
   return retval;
--- a/libinterp/corefcn/sub2ind.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/libinterp/corefcn/sub2ind.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -272,8 +272,7 @@
     }
   catch (const octave::index_exception& e)
     {
-      error ("ind2sub: Invalid index %s. %s", e.idx ().c_str (),
-             e.details ().c_str ());
+      error ("ind2sub: invalid index %s", e.what ());
     }
 
   return retval;
@@ -316,5 +315,5 @@
 
 %!error <DIMS must contain integers> ind2sub ([2, -2], 3);
 %!error <index out of range> ind2sub ([2, 2, 2], 1:9);
-%!error <Invalid index> ind2sub ([2, 2, 2], -1:8);
+%!error <invalid index> ind2sub ([2, 2, 2], -1:8);
 */
--- a/libinterp/corefcn/utils.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/libinterp/corefcn/utils.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -1286,11 +1286,7 @@
                   }
                 catch (const index_exception& e)
                   {
-                    std::string idx = e.idx ();
-                    std::string msg = e.details ();
-
-                    error ("dims_to_numel: Invalid IDX %s. %s",
-                           idx.c_str (), msg.c_str ());
+                    error ("dims_to_numel: invalid index %s", e.what ());
                   }
               }
           }
--- a/libinterp/octave-value/ov-base-mat.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/libinterp/octave-value/ov-base-mat.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -271,9 +271,11 @@
           break;
         }
     }
-  catch (const octave::index_exception& e)
+  catch (octave::index_exception& e)
     {
-      octave::err_invalid_index (e.idx (), n_idx, k+1);
+      // Rethrow to allow more info to be reported later.
+      e.set_pos_if_unset (n_idx, k+1);
+      throw;
     }
 
   // Clear cache.
@@ -375,9 +377,11 @@
           break;
         }
     }
-  catch (const octave::index_exception& e)
+  catch (octave::index_exception& e)
     {
-      octave::err_invalid_index (e.idx (), n_idx, k+1);
+      // Rethrow to allow more info to be reported later.
+      e.set_pos_if_unset (n_idx, k+1);
+      throw;
     }
 
   // Clear cache.
--- a/libinterp/octave-value/ov-complex.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/libinterp/octave-value/ov-complex.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -74,13 +74,18 @@
   public:
 
     complex_index_exception (const std::string& value)
-      : index_exception (value) { }
+      : index_exception (value)
+    {
+      // Virtual, but the one we want to call is defined in this class.
+      update_message ();
+    }
 
     ~complex_index_exception (void) = default;
 
-    std::string details (void) const
+    void update_message (void)
     {
-      return "subscripts must be real (forgot to initialize i or j?)";
+      set_message (expression ()
+                   + ": subscripts must be real (forgot to initialize i or j?)");
     }
 
     // ID of error to throw.
--- a/liboctave/util/lo-array-errwarn.cc	Sun Jan 26 23:16:24 2020 -0500
+++ b/liboctave/util/lo-array-errwarn.cc	Sun Jan 26 23:07:45 2020 -0500
@@ -118,23 +118,6 @@
        is1d ? "I" : "..,I,..", idx, ext);
   }
 
-  // Common procedures of base class index_exception, thrown whenever an
-  // object is indexed incorrectly, such as by an index that is out of
-  // range, negative, fractional, complex, or of a non-numeric type.
-
-  std::string
-  index_exception::message (void) const
-  {
-    return expression () + ": " + details ();
-  }
-
-  const char * index_exception::what (void) const noexcept
-  {
-    std::string tmp = message ();
-
-    return tmp.c_str ();
-   }
-
   // Show the expression that caused the error, e.g.,  "A(-1,_)",
   // "A(0+1i)", "A(_,3)".  Show how many indices come before/after the
   // offending one, e.g., (<error>), (<error>,_), or (_,<error>,...[x5]...)
@@ -164,7 +147,7 @@
           buf << "(...[x" << m_dim - 1 << "]...";
       }
 
-    buf << idx ();
+    buf << m_index;
 
     if (show_parens)
       {
@@ -190,15 +173,19 @@
     invalid_index (const std::string& value, octave_idx_type ndim,
                    octave_idx_type dimen)
       : index_exception (value, ndim, dimen)
-    { }
+    {
+      // Virtual, but the one we want to call is defined in this class.
+      update_message ();
+    }
 
-    std::string details (void) const
+    void update_message (void)
     {
-#if defined (OCTAVE_ENABLE_64)
-      return "subscripts must be either integers 1 to (2^63)-1 or logicals";
-#else
-      return "subscripts must be either integers 1 to (2^31)-1 or logicals";
-#endif
+      static std::string exp
+        = std::to_string (std::numeric_limits<octave_idx_type>::digits);
+
+      set_message (expression ()
+                   + ": subscripts must be either integers 1 to (2^" + exp
+                   + ")-1 or logicals");
     }
 
     // ID of error to throw
@@ -254,14 +241,16 @@
                   octave_idx_type dim, octave_idx_type ext,
                   const dim_vector& size)
       : index_exception (value, nd, dim), m_size (size), m_extent (ext)
-    { }
-
-    std::string details (void) const
     {
-      std::string expl;
+      // Virtual, but the one we want to call is defined in this class.
+      update_message ();
+    }
 
-      return "out of bound " + std::to_string (m_extent)
-        + " (dimensions are " + m_size.str ('x') + ")";
+    void update_message (void)
+    {
+      set_message (expression () + ": out of bound "
+                   + std::to_string (m_extent)
+                   + " (dimensions are " + m_size.str ('x') + ")");
     }
 
     // ID of error to throw.
--- a/liboctave/util/lo-array-errwarn.h	Sun Jan 26 23:16:24 2020 -0500
+++ b/liboctave/util/lo-array-errwarn.h	Sun Jan 26 23:07:45 2020 -0500
@@ -45,33 +45,28 @@
   {
   public:
 
-    index_exception (const std::string& index_arg, octave_idx_type nd_arg = 0,
-                     octave_idx_type dim_arg = -1, const char *var_arg = "")
-      : m_index (index_arg), m_nd (nd_arg), m_dim (dim_arg), m_var (var_arg)
-    { }
+    index_exception (const std::string& index, octave_idx_type nd = 0,
+                     octave_idx_type dim = -1, const char *var = "")
+      : m_index (index), m_nd (nd), m_dim (dim), m_var (var)
+    {
+      set_message (expression ());
+    }
 
     ~index_exception (void) = default;
 
-    // Erroneous index value.  Called in message method and by external
-    // code (e.g., nth_element) to make a custom error message.
-    std::string idx (void) const { return m_index; }
-
-    // details set by subclass.
-    virtual std::string details (void) const = 0;
-
     // ID of error to throw.
     virtual const char * err_id (void) const = 0;
 
-    virtual std::string message (void) const;
-
-    // Provided for std::exception interface.
-    const char * what (void) const noexcept;
+    // By default, update message to show the erroneous index expression.
+    virtual void update_message (void) { set_message (expression ()); }
 
     // Position of error: dimension in error, and number of dimensions.
     void set_pos (octave_idx_type nd_arg, octave_idx_type dim_arg)
     {
       m_nd = nd_arg;
       m_dim = dim_arg;
+
+      update_message ();
     }
 
     void set_pos_if_unset (octave_idx_type nd_arg, octave_idx_type dim_arg)
@@ -80,6 +75,8 @@
         {
           m_nd  = nd_arg;
           m_dim = dim_arg;
+
+          update_message ();
         }
     }
 
@@ -87,6 +84,8 @@
     void set_var (const std::string& var_arg = "")
     {
       m_var = var_arg;
+
+      update_message ();
     }
 
   private:
@@ -107,7 +106,6 @@
 
     // Name of variable being indexed.
     std::string m_var;
-
   };
 
   OCTAVE_NORETURN OCTAVE_API extern void
--- a/liboctave/util/quit.h	Sun Jan 26 23:16:24 2020 -0500
+++ b/liboctave/util/quit.h	Sun Jan 26 23:07:45 2020 -0500
@@ -130,7 +130,7 @@
       m_message = msg;
     }
 
-    virtual std::string message (void) const { return m_message; }
+    std::string message (void) const { return m_message; }
 
     // Provided for std::exception interface.
     const char * what (void) const noexcept { return m_message.c_str (); }