# HG changeset patch # User John W. Eaton # Date 1580098065 18000 # Node ID 9a965fec21c1f04867f32c846564cf00bacdc2aa # Parent b31a118729eded61f646c49a5978d8126eb4c15b 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::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. diff -r b31a118729ed -r 9a965fec21c1 libinterp/corefcn/data.cc --- 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; diff -r b31a118729ed -r 9a965fec21c1 libinterp/corefcn/sub2ind.cc --- 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 ind2sub ([2, -2], 3); %!error ind2sub ([2, 2, 2], 1:9); -%!error ind2sub ([2, 2, 2], -1:8); +%!error ind2sub ([2, 2, 2], -1:8); */ diff -r b31a118729ed -r 9a965fec21c1 libinterp/corefcn/utils.cc --- 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 ()); } } } diff -r b31a118729ed -r 9a965fec21c1 libinterp/octave-value/ov-base-mat.cc --- 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. diff -r b31a118729ed -r 9a965fec21c1 libinterp/octave-value/ov-complex.cc --- 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. diff -r b31a118729ed -r 9a965fec21c1 liboctave/util/lo-array-errwarn.cc --- 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., (), (,_), or (_,,...[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::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. diff -r b31a118729ed -r 9a965fec21c1 liboctave/util/lo-array-errwarn.h --- 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 diff -r b31a118729ed -r 9a965fec21c1 liboctave/util/quit.h --- 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 (); }