# HG changeset patch # User John W. Eaton # Date 1443730699 14400 # Node ID b70cc4bd8109b0f7784874a5f13e32ec1f3786da # Parent fcb792acab9b2bbfc011e7b2687c80831254d0ae begin removal of global error_state variable * gripes.h, gripes.cc (gripe_library_execution_error): Delete. * error.cc (warning_state): Delete unused variable. (reset_error_handler): Don't set warning_state or error_state. (debug_or_throw_exception): New static function. (verror): Don't check error_state. (vmessage): Call debug_or_throw_exception instead of setting error_state. (error_1, error_2): Combine into single function, error_1 that prints error message and ultimately calls debug_or_throw_exception. (verror, verror_with_cfn, verror_with_id_cfn): Call error_1. Don't check or set warning_state. (error): Don't check error_state. (Flasterror, Flasterr): Adapt to not using error_state. (interpreter_try): Don't unwind_protect error_state. * NEWS: Update. * doc/interpreter/external.txi: Explain octave_execution_exception instead of error_state for matrix addition example. * jit-typeinfo.cc (octave_jit_gripe_nan_to_logical_conversion, octave_jit_ginvalid_index, octave_jit_gindex_range, octave_jit_paren_scalar, octave_jit_paren_scalar_subsasgn): Don't catch octave_execution_exception. * cellfun.cc (Fcellfun): Use exceptions instead of error_state. * ls-mat-ascii.cc (save_mat_ascii_data): Likewise. * mex.cc (mexCallMATLAB, mexEvalString): Likewise. * variables.cc (safe_symbol_lookup): Likewise. * svd.cc (Fsvd): Eliminate use of error_state. * __magick_read__.cc (read_file, write_file): Likewise. * variables.cc (generate_struct_completions): Eliminate use of obsolete warning_state variable. * ov-builtin.cc (octave_builtin::do_multi_index_op): Don't catch octave_execution_exception and call gripe_library_execution_error. * ov-class.cc (octave_class::reconstruct_exemplar): Eliminate use of error_state. Catch possible octave_execution_exception in do_multi_index_op. * ov-mex-fcn.cc (octave_mex_function::do_multi_index_op): Eliminate use of error_state. Catch possible octave_execution_exception in call_mex. * ov-fcn-handle.cc (octave_fcn_binder::maybe_binder): Eliminate use of error_state. * ov-oncleanup.cc (octave_oncleanup::~octave_oncleanup): Eliminate use of error_state. Propagate possible octave_execution_exception from do_multi_index_op. * ov.cc (octave_value::assign, do_binary_op, do_unary_op, octave_value::do_non_const_unary_op): Don't catch octave_execution_exception here. * oct-parse.in.yy (octave_base_parser::finish_colon_expression, octave_base_parser::finish_array_list): Eliminate use of warning_state and error_state. (Feval, Fevalin): Use exceptions instead of error_state. * pt-eval.cc, pt-eval.h (tree_evaluator::unwind_protect_exception): New static variable. * (tree_evaluator::visit_statement): Don't catch octave_execution_exception here. (tree_evaluator::visit_try_catch_command, tree_evaluator::do_unwind_protect_cleanup): Eliminate use of error_state. (tree_evaluator::visit_unwind_protect_command): Use unwind_protect_exception to track whether an exception has occurred in the try block. diff -r fcb792acab9b -r b70cc4bd8109 NEWS --- a/NEWS Thu Sep 24 12:58:46 2015 +0200 +++ b/NEWS Thu Oct 01 16:18:19 2015 -0400 @@ -71,6 +71,12 @@ java_debug read_readline_init_file java_invoke saving_history + ** The global error_state variable in Octave's C++ API has been + deprecated and will be removed in a future version. Now the error + and print_usage functions throw an exception + (octave_execution_error) after displaying the error message. This + makes the error and print_usage functions in C++ work more like the + corresponding functions in the scripting language. Summary of important user-visible changes for version 4.0: --------------------------------------------------------- diff -r fcb792acab9b -r b70cc4bd8109 doc/interpreter/external.txi --- a/doc/interpreter/external.txi Thu Sep 24 12:58:46 2015 +0200 +++ b/doc/interpreter/external.txi Thu Oct 01 16:18:19 2015 -0400 @@ -363,12 +363,15 @@ explicitly checks that there are sufficient arguments available before accessing these arguments. It then obtains two multi-dimensional arrays of type @code{NDArray} and adds these together. Note that the array_value -method is called without using the @code{is_matrix_type} type, and instead the -error_state is checked before returning @code{A + B}. The reason to +method is called without using the @code{is_matrix_type} type. If an +error occurs when attempting to extract the value, Octave will print a +message and throw an exception. The reason to prefer this is that the arguments might be a type that is not an @code{NDArray}, but it would make sense to convert it to one. The @code{array_value} method allows this conversion to be performed -transparently if possible, and sets @code{error_state} if it is not. +transparently if possible. If you need to catch errors like this and +perform some kind of cleanup or other operation, you can catch the +@code{octave_execution_error} exception. @code{A + B}, operating on two @code{NDArray}'s returns an @code{NDArray}, which is cast to an @code{octave_value} on the return diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/cellfun.cc Thu Oct 01 16:18:19 2015 -0400 @@ -70,17 +70,22 @@ octave_value& error_handler) { octave_value_list tmp; + + bool execution_error = false; + try { tmp = func.do_multi_index_op (nargout, inputlist); } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { if (error_handler.is_defined ()) - error_state = 1; + execution_error = true; + else + octave_throw_execution_exception (); } - if (error_state) + if (execution_error) { if (error_handler.is_defined ()) { @@ -96,14 +101,7 @@ buffer_error_messages--; - error_state = 0; - tmp = error_handler.do_multi_index_op (nargout, errlist); - - buffer_error_messages++; - - if (error_state) - tmp.clear (); } else tmp.clear (); diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/error.cc Thu Oct 01 16:18:19 2015 -0400 @@ -93,22 +93,11 @@ // // Valid values: // -// -2: an error has occurred, but don't print any messages. -// -1: an error has occurred, we are printing a traceback // 0: no error // 1: an error has occurred // int error_state = 0; -// Current warning state. -// -// Valid values: -// -// 0: no warning -// 1: a warning has occurred -// -int warning_state = 0; - // Tell the error handler whether to print messages, or just store // them for later. Used for handling errors in eval() and // the 'unwind_protect' statement. @@ -123,8 +112,6 @@ void reset_error_handler (void) { - error_state = 0; - warning_state = 0; buffer_error_messages = 0; discard_error_messages = false; } @@ -146,6 +133,26 @@ return octave_call_stack::empty_backtrace (); } +static void +debug_or_throw_exception (void) +{ + if ((interactive || forced_interactive) + && Vdebug_on_error && octave_call_stack::caller_user_code ()) + { + unwind_protect frame; + frame.protect_var (Vdebug_on_error); + Vdebug_on_error = false; + + tree_evaluator::debug_mode = true; + + tree_evaluator::current_frame = octave_call_stack::current_frame (); + + do_keyboard (octave_value_list ()); + } + else + octave_throw_execution_exception (); +} + // Warning messages are never buffered. static void @@ -204,7 +211,7 @@ std::string base_msg = output_buf.str (); - bool to_beep_or_not_to_beep_p = Vbeep_on_error && ! error_state; + bool to_beep_or_not_to_beep_p = Vbeep_on_error; std::string msg_string; @@ -238,7 +245,7 @@ msg_string += base_msg + "\n"; - if (! error_state && save_last_error) + if (save_last_error) { // This is the first error in a possible series. @@ -332,48 +339,6 @@ } } -// Note that we don't actually print any message if the error string -// is just "" or "\n". This allows error ("") and error ("\n") to -// just set the error state. - -static void -error_1 (std::ostream& os, const char *name, const char *id, - const char *fmt, va_list args, bool with_cfn = false) -{ - if (error_state != -2) - { - if (fmt && *fmt) - { - size_t len = strlen (fmt); - - if (len > 0) - { - if (fmt[len - 1] == '\n') - { - if (len > 1) - { - // Strip newline before issuing error - std::string tmp_fmt (fmt, len - 1); - verror (true, os, name, id, tmp_fmt.c_str (), - args, with_cfn); - } - - error_state = -2; - } - else - { - verror (true, os, name, id, fmt, args, with_cfn); - - if (! error_state) - error_state = 1; - } - } - } - else - panic ("error_1: invalid format"); - } -} - void vmessage (const char *name, const char *fmt, va_list args) { @@ -409,7 +374,8 @@ usage_1 (const char *id, const char *fmt, va_list args) { verror (true, std::cerr, "usage", id, fmt, args); - error_state = -1; + + debug_or_throw_exception (); } void @@ -443,37 +409,49 @@ } static void -error_2 (const char *id, const char *fmt, va_list args, bool with_cfn = false) +error_1 (std::ostream& os, const char *name, const char *id, + const char *fmt, va_list args, bool with_cfn = false) { - int init_state = error_state; - - error_1 (std::cerr, "error", id, fmt, args, with_cfn); - - bool in_user_code = octave_call_stack::caller_user_code () != 0; - - if (error_state != -2 && in_user_code && ! discard_error_messages) - pr_where ("error"); - - if (interactive && Vdebug_on_error && init_state == 0 && in_user_code) + if (fmt) { - unwind_protect frame; - frame.protect_var (Vdebug_on_error); - Vdebug_on_error = false; - - error_state = 0; + if (*fmt) + { + size_t len = strlen (fmt); - tree_evaluator::debug_mode = true; + if (len > 0) + { + if (fmt[len - 1] == '\n') + { + if (len > 1) + { + char *tmp_fmt = strsave (fmt); + tmp_fmt[len - 1] = '\0'; + verror (true, os, name, id, tmp_fmt, args, with_cfn); + delete [] tmp_fmt; + } + } + else + { + verror (true, os, name, id, fmt, args, with_cfn); - tree_evaluator::current_frame = octave_call_stack::current_frame (); + bool in_user_code = octave_call_stack::caller_user_code () != 0; - do_keyboard (octave_value_list ()); + if (in_user_code && ! discard_error_messages) + pr_where ("error"); + } + } + } } + else + panic ("error_1: invalid format"); + + debug_or_throw_exception (); } void verror (const char *fmt, va_list args) { - error_2 ("", fmt, args); + error_1 (std::cerr, "error", "", fmt, args); } void @@ -488,7 +466,7 @@ void verror_with_cfn (const char *fmt, va_list args) { - error_2 ("", fmt, args, true); + error_1 (std::cerr, "error", "", fmt, args, true); } void @@ -503,7 +481,7 @@ void verror_with_id (const char *id, const char *fmt, va_list args) { - error_2 (id, fmt, args); + error_1 (std::cerr, "error", id, fmt, args); } void @@ -518,7 +496,7 @@ void verror_with_id_cfn (const char *id, const char *fmt, va_list args) { - error_2 (id, fmt, args, true); + error_1 (std::cerr, "error", id, fmt, args, true); } void @@ -632,7 +610,7 @@ { // Handle this warning as an error. - error_2 (id, fmt, args); + error_1 (std::cerr, "error", id, fmt, args); } else if (warn_opt == 1) { @@ -651,14 +629,11 @@ bool in_user_code = octave_call_stack::caller_user_code () != 0; - if (! fmt_suppresses_backtrace && in_user_code - && Vbacktrace_on_warning && ! warning_state + && Vbacktrace_on_warning && ! discard_warning_messages) pr_where ("warning"); - warning_state = 1; - if ((interactive || forced_interactive) && Vdebug_on_warning && in_user_code) { @@ -860,120 +835,117 @@ { const octave_scalar_map err = args(0).scalar_map_value (); - if (! error_state) + if (err.contains ("message") && err.contains ("identifier")) { - if (err.contains ("message") && err.contains ("identifier")) - { - std::string msg = err.contents ("message").string_value (); - std::string id = err.contents ("identifier").string_value (); - int len = msg.length (); - - std::string file; - std::string nm; - int l = -1; - int c = -1; - - octave_map err_stack = initialize_last_error_stack (); - - if (err.contains ("stack")) - { - err_stack = err.contents ("stack").map_value (); + std::string msg = err.contents ("message").string_value (); + std::string id = err.contents ("identifier").string_value (); + int len = msg.length (); - if (err_stack.numel () > 0) - { - if (err_stack.contains ("file")) - file = err_stack.contents ("file")(0).string_value (); - - if (err_stack.contains ("name")) - nm = err_stack.contents ("name")(0).string_value (); + std::string file; + std::string nm; + int l = -1; + int c = -1; - if (err_stack.contains ("line")) - l = err_stack.contents ("line")(0).nint_value (); + octave_map err_stack = initialize_last_error_stack (); - if (err_stack.contains ("column")) - c = err_stack.contents ("column")(0).nint_value (); - } - } + if (err.contains ("stack")) + { + err_stack = err.contents ("stack").map_value (); - // Ugh. - char *tmp_msg = strsave (msg.c_str ()); - if (tmp_msg[len-1] == '\n') + if (err_stack.numel () > 0) { - if (len > 1) - { - tmp_msg[len - 1] = '\0'; - rethrow_error (id.c_str (), "%s\n", tmp_msg); - } + if (err_stack.contains ("file")) + file = err_stack.contents ("file")(0).string_value (); + + if (err_stack.contains ("name")) + nm = err_stack.contents ("name")(0).string_value (); + + if (err_stack.contains ("line")) + l = err_stack.contents ("line")(0).nint_value (); + + if (err_stack.contains ("column")) + c = err_stack.contents ("column")(0).nint_value (); } - else - rethrow_error (id.c_str (), "%s", tmp_msg); - delete [] tmp_msg; + } - // FIXME: is this the right thing to do for Vlast_error_stack? - // Should it be saved and restored with unwind_protect? - - Vlast_error_stack = err_stack; + // Ugh. + char *tmp_msg = strsave (msg.c_str ()); + if (tmp_msg[len-1] == '\n') + { + if (len > 1) + { + tmp_msg[len - 1] = '\0'; + rethrow_error (id.c_str (), "%s\n", tmp_msg); + } + } + else + rethrow_error (id.c_str (), "%s", tmp_msg); + delete [] tmp_msg; - if (err.contains ("stack")) + // FIXME: is this the right thing to do for Vlast_error_stack? + // Should it be saved and restored with unwind_protect? + + Vlast_error_stack = err_stack; + + if (err.contains ("stack")) + { + if (file.empty ()) { - if (file.empty ()) + if (nm.empty ()) { - if (nm.empty ()) + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: near line %d, column %d", - l, c); - else - pr_where_1 ("error: near line %d", l); - } - } - else - { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: called from '%s' near line %d, column %d", - nm.c_str (), l, c); - else - pr_where_1 ("error: called from '%d' near line %d", - nm.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: near line %d, column %d", + l, c); + else + pr_where_1 ("error: near line %d", l); } } else { - if (nm.empty ()) + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: in file %s near line %d, column %d", - file.c_str (), l, c); - else - pr_where_1 ("error: in file %s near line %d", - file.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: called from '%s' near line %d, column %d", + nm.c_str (), l, c); + else + pr_where_1 ("error: called from '%d' near line %d", + nm.c_str (), l); } - else + } + } + else + { + if (nm.empty ()) + { + if (l > 0) { - if (l > 0) - { - if (c > 0) - pr_where_1 ("error: called from '%s' in file %s near line %d, column %d", - nm.c_str (), file.c_str (), l, c); - else - pr_where_1 ("error: called from '%d' in file %s near line %d", - nm.c_str (), file.c_str (), l); - } + if (c > 0) + pr_where_1 ("error: in file %s near line %d, column %d", + file.c_str (), l, c); + else + pr_where_1 ("error: in file %s near line %d", + file.c_str (), l); + } + } + else + { + if (l > 0) + { + if (c > 0) + pr_where_1 ("error: called from '%s' in file %s near line %d, column %d", + nm.c_str (), file.c_str (), l, c); + else + pr_where_1 ("error: called from '%d' in file %s near line %d", + nm.c_str (), file.c_str (), l); } } } } - else - error ("rethrow: ERR structure must contain the fields 'message and 'identifier'"); } + else + error ("rethrow: ERR structure must contain the fields 'message and 'identifier'"); } return retval; } @@ -998,31 +970,28 @@ { std::string arg1 = args(0).string_value (); - if (! error_state) + // For compatibility with Matlab, an identifier must contain + // ':', but not at the beginning or the end, and it must not + // contain '%' (even if it is not a valid conversion + // operator) or whitespace. + + if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos + && arg1.find (':') != std::string::npos + && arg1[0] != ':' + && arg1[arg1.length ()-1] != ':') { - // For compatibility with Matlab, an identifier must contain - // ':', but not at the beginning or the end, and it must not - // contain '%' (even if it is not a valid conversion - // operator) or whitespace. - - if (arg1.find_first_of ("% \f\n\r\t\v") == std::string::npos - && arg1.find (':') != std::string::npos - && arg1[0] != ':' - && arg1[arg1.length ()-1] != ':') + if (nargin > 1) { - if (nargin > 1) - { - id = arg1; + id = arg1; - nargs.resize (nargin-1); + nargs.resize (nargin-1); - for (int i = 1; i < nargin; i++) - nargs(i-1) = args(i); - } - else - nargs(0) = "call to " + caller - + " with message identifier requires message"; + for (int i = 1; i < nargin; i++) + nargs(i-1) = args(i); } + else + nargs(0) = "call to " + caller + + " with message identifier requires message"; } } @@ -1167,12 +1136,7 @@ // handle_message, error_with_id, etc. } else - { - have_fmt = maybe_extract_message_id ("error", args, nargs, id); - - if (error_state) - return retval; - } + have_fmt = maybe_extract_message_id ("error", args, nargs, id); handle_message (error_with_id, id.c_str (), "unspecified error", nargs, have_fmt); @@ -1196,6 +1160,8 @@ octave_idx_type nel = ident.numel (); + assert (nel != 0); + bool found = false; std::string val; @@ -1223,13 +1189,14 @@ } } - if (found) - { - retval.assign ("identifier", id); - retval.assign ("state", val); - } - else - error ("warning: unable to find default warning state!"); + // The warning state "all" is always supposed to remain in the list, + // so we should always find a state, either explicitly or by using the + // state for "all". + + assert (found); + + retval.assign ("identifier", id); + retval.assign ("state", val); return retval; } @@ -1814,11 +1781,6 @@ octave_value retval; int nargin = args.length (); - unwind_protect frame; - - frame.protect_var (error_state); - error_state = 0; - if (nargin < 2) { octave_scalar_map err; @@ -1853,47 +1815,47 @@ int new_error_line = -1; int new_error_column = -1; - if (! error_state && new_err.contains ("message")) + if (new_err.contains ("message")) { const std::string tmp = new_err.getfield ("message").string_value (); new_error_message = tmp; } - if (! error_state && new_err.contains ("identifier")) + if (new_err.contains ("identifier")) { const std::string tmp = new_err.getfield ("identifier").string_value (); new_error_id = tmp; } - if (! error_state && new_err.contains ("stack")) + if (new_err.contains ("stack")) { new_err_stack = new_err.getfield ("stack").scalar_map_value (); - if (! error_state && new_err_stack.contains ("file")) + if (new_err_stack.contains ("file")) { const std::string tmp = new_err_stack.getfield ("file").string_value (); new_error_file = tmp; } - if (! error_state && new_err_stack.contains ("name")) + if (new_err_stack.contains ("name")) { const std::string tmp = new_err_stack.getfield ("name").string_value (); new_error_name = tmp; } - if (! error_state && new_err_stack.contains ("line")) + if (new_err_stack.contains ("line")) { const int tmp = new_err_stack.getfield ("line").nint_value (); new_error_line = tmp; } - if (! error_state && new_err_stack.contains ("column")) + if (new_err_stack.contains ("column")) { const int tmp = new_err_stack.getfield ("column").nint_value (); @@ -1901,35 +1863,31 @@ } } - if (! error_state) - { - Vlast_error_message = new_error_message; - Vlast_error_id = new_error_id; + Vlast_error_message = new_error_message; + Vlast_error_id = new_error_id; - if (new_err.contains ("stack")) - { - new_err_stack.setfield ("file", new_error_file); - new_err_stack.setfield ("name", new_error_name); - new_err_stack.setfield ("line", new_error_line); - new_err_stack.setfield ("column", new_error_column); - Vlast_error_stack = new_err_stack; - } - else - { - // No stack field. Fill it in with backtrace info. - octave_idx_type curr_frame = -1; + if (new_err.contains ("stack")) + { + new_err_stack.setfield ("file", new_error_file); + new_err_stack.setfield ("name", new_error_name); + new_err_stack.setfield ("line", new_error_line); + new_err_stack.setfield ("column", new_error_column); + Vlast_error_stack = new_err_stack; + } + else + { + // No stack field. Fill it in with backtrace info. + octave_idx_type curr_frame = -1; - Vlast_error_stack - = octave_call_stack::backtrace (0, curr_frame); - } + Vlast_error_stack + = octave_call_stack::backtrace (0, curr_frame); } } else error ("lasterror: argument must be a structure or a string"); } - if (! error_state) - retval = err; + retval = err; } else print_usage (); @@ -1955,36 +1913,26 @@ { octave_value_list retval; - unwind_protect frame; - - frame.protect_var (error_state); - error_state = 0; - int argc = args.length () + 1; if (argc < 4) { string_vector argv = args.make_argv ("lasterr"); - if (! error_state) - { - std::string prev_error_id = Vlast_error_id; - std::string prev_error_message = Vlast_error_message; + std::string prev_error_id = Vlast_error_id; + std::string prev_error_message = Vlast_error_message; - if (argc > 2) - Vlast_error_id = argv(2); + if (argc > 2) + Vlast_error_id = argv(2); - if (argc > 1) - Vlast_error_message = argv(1); + if (argc > 1) + Vlast_error_message = argv(1); - if (argc == 1 || nargout > 0) - { - retval(1) = prev_error_id; - retval(0) = prev_error_message; - } + if (argc == 1 || nargout > 0) + { + retval(1) = prev_error_id; + retval(0) = prev_error_message; } - else - error ("lasterr: all arguments must be strings"); } else print_usage (); @@ -2016,26 +1964,20 @@ { string_vector argv = args.make_argv ("lastwarn"); - if (! error_state) - { - std::string prev_warning_id = Vlast_warning_id; - std::string prev_warning_message = Vlast_warning_message; + std::string prev_warning_id = Vlast_warning_id; + std::string prev_warning_message = Vlast_warning_message; - if (argc > 2) - Vlast_warning_id = argv(2); + if (argc > 2) + Vlast_warning_id = argv(2); - if (argc > 1) - Vlast_warning_message = argv(1); + if (argc > 1) + Vlast_warning_message = argv(1); - if (argc == 1 || nargout > 0) - { - warning_state = 0; - retval(1) = prev_warning_id; - retval(0) = prev_warning_message; - } + if (argc == 1 || nargout > 0) + { + retval(1) = prev_warning_id; + retval(0) = prev_warning_message; } - else - error ("lastwarn: all arguments must be strings"); } else print_usage (); @@ -2164,7 +2106,6 @@ void interpreter_try (unwind_protect& frame) { - frame.protect_var (error_state); frame.protect_var (buffer_error_messages); frame.protect_var (Vdebug_on_error); frame.protect_var (Vdebug_on_warning); diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/gripes.cc --- a/libinterp/corefcn/gripes.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/gripes.cc Thu Oct 01 16:18:19 2015 -0400 @@ -205,15 +205,6 @@ } void -gripe_library_execution_error (void) -{ - octave_exception_state = octave_no_exception; - - if (! error_state) - error ("caught execution error in library function"); -} - -void gripe_invalid_inquiry_subscript (void) { error ("invalid dimension inquiry of a non-existent value"); diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/gripes.h --- a/libinterp/corefcn/gripes.h Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/gripes.h Thu Oct 01 16:18:19 2015 -0400 @@ -114,9 +114,6 @@ gripe_logical_conversion (void); extern OCTINTERP_API void -gripe_library_execution_error (void); - -extern OCTINTERP_API void gripe_invalid_inquiry_subscript (void); extern OCTINTERP_API void diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/jit-typeinfo.cc --- a/libinterp/corefcn/jit-typeinfo.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/jit-typeinfo.cc Thu Oct 01 16:18:19 2015 -0400 @@ -215,41 +215,20 @@ extern "C" void octave_jit_gripe_nan_to_logical_conversion (void) { - try - { - gripe_nan_to_logical_conversion (); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_nan_to_logical_conversion (); } extern "C" void octave_jit_ginvalid_index (void) { - try - { - gripe_invalid_index (); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_invalid_index (); } extern "C" void octave_jit_gindex_range (int nd, int dim, octave_idx_type iext, octave_idx_type ext) { - try - { - gripe_index_out_of_range (nd, dim, iext, ext); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + gripe_index_out_of_range (nd, dim, iext, ext); } extern "C" jit_matrix @@ -281,19 +260,12 @@ octave_idx_type idx_count) { // FIXME: Replace this with a more optimal version - try - { - Array idx; - make_indices (indicies, idx_count, idx); + Array idx; + make_indices (indicies, idx_count, idx); - Array ret = mat->array->index (idx); - return ret.xelem (0); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - return 0; - } + Array ret = mat->array->index (idx); + + return ret.xelem (0); } extern "C" jit_matrix @@ -302,20 +274,14 @@ { // FIXME: Replace this with a more optimal version jit_matrix ret; - try - { - Array idx; - make_indices (indices, idx_count, idx); + + Array idx; + make_indices (indices, idx_count, idx); - Matrix temp (1, 1); - temp.xelem(0) = value; - mat->array->assign (idx, temp); - ret.update (mat->array); - } - catch (const octave_execution_exception&) - { - gripe_library_execution_error (); - } + Matrix temp (1, 1); + temp.xelem(0) = value; + mat->array->assign (idx, temp); + ret.update (mat->array); return ret; } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/load-path.cc --- a/libinterp/corefcn/load-path.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/load-path.cc Thu Oct 01 16:18:19 2015 -0400 @@ -91,12 +91,10 @@ initialize (); } } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { // Skip updating if we don't know where we are, but // don't treat it as an error. - - error_state = 0; } } else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked) @@ -159,7 +157,7 @@ abs_dir_cache[abs_name] = *this; } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { // Skip updating if we don't know where we are. } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/ls-mat-ascii.cc --- a/libinterp/corefcn/ls-mat-ascii.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/ls-mat-ascii.cc Thu Oct 01 16:18:19 2015 -0400 @@ -369,15 +369,18 @@ if (val.is_complex_type ()) warning ("save: omitting imaginary part for ASCII file"); - Matrix m = val.matrix_value (true); + Matrix m; - if (error_state) + try + { + m = val.matrix_value (true); + } + catch (const octave_execution_exception&) { success = false; + } - error_state = 0; - } - else + if (success) { long old_precision = os.precision (); diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/mex.cc --- a/libinterp/corefcn/mex.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/mex.cc Thu Oct 01 16:18:19 2015 -0400 @@ -3105,9 +3105,20 @@ for (int i = 0; i < nargin; i++) args(i) = mxArray::as_octave_value (argin[i]); - octave_value_list retval = feval (fname, args, nargout); - - if (error_state && mex_context->trap_feval_error == 0) + bool execution_error = false; + + octave_value_list retval; + + try + { + retval = feval (fname, args, nargout); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (execution_error && mex_context->trap_feval_error == 0) { // FIXME: is this the correct way to clean up? abort() is // going to trigger a long jump, so the normal class destructors @@ -3138,13 +3149,7 @@ while (num_to_copy < nargout) argout[num_to_copy++] = 0; - if (error_state) - { - error_state = 0; - return 1; - } - else - return 0; + return execution_error ? 1 : 0; } void @@ -3163,14 +3168,19 @@ octave_value_list ret; - ret = eval_string (s, false, parse_status, 0); - - if (parse_status || error_state) + bool execution_error = false; + + try { - error_state = 0; - - retval = 1; + ret = eval_string (s, false, parse_status, 0); } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (parse_status || execution_error) + retval = 1; return retval; } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/rand.cc --- a/libinterp/corefcn/rand.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/rand.cc Thu Oct 01 16:18:19 2015 -0400 @@ -1181,7 +1181,7 @@ { idx = Array (dim_vector (1, idx_len)); } - catch (std::bad_alloc) + catch (const std::bad_alloc&) { // Looks like n is too big and short_shuffle is false. // Let's try again, but this time with the alternative. diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/svd.cc --- a/libinterp/corefcn/svd.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/svd.cc Thu Oct 01 16:18:19 2015 -0400 @@ -129,10 +129,7 @@ int nargin = args.length (); if (nargin < 1 || nargin > 2 || nargout == 2 || nargout > 3) - { - print_usage (); - return retval; - } + print_usage (); octave_value arg = args(0); @@ -140,10 +137,7 @@ octave_idx_type nc = arg.columns (); if (arg.ndims () != 2) - { - error ("svd: A must be a 2-D matrix"); - return retval; - } + error ("svd: A must be a 2-D matrix"); bool isfloat = arg.is_single_type (); @@ -164,12 +158,14 @@ retval(1) = FloatMatrix (nr, nc); retval(0) = FloatDiagMatrix (nr, nr, 1.0f); break; + case SVD::economy: retval(2) = FloatDiagMatrix (0, nc, 1.0f); retval(1) = FloatMatrix (0, 0); retval(0) = FloatDiagMatrix (nr, 0, 1.0f); break; - case SVD::sigma_only: default: + + case SVD::sigma_only: default: retval(0) = FloatMatrix (0, 1); break; } @@ -183,12 +179,14 @@ retval(1) = Matrix (nr, nc); retval(0) = DiagMatrix (nr, nr, 1.0); break; + case SVD::economy: retval(2) = DiagMatrix (0, nc, 1.0); retval(1) = Matrix (0, 0); retval(0) = DiagMatrix (nr, 0, 1.0); break; - case SVD::sigma_only: default: + + case SVD::sigma_only: default: retval(0) = Matrix (0, 1); break; } @@ -202,56 +200,40 @@ { FloatMatrix tmp = arg.float_matrix_value (); - if (! error_state) - { - if (tmp.any_element_is_inf_or_nan ()) - { - error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - return retval; - } + if (tmp.any_element_is_inf_or_nan ()) + error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - FloatSVD result (tmp, type, driver); + FloatSVD result (tmp, type, driver); + + FloatDiagMatrix sigma = result.singular_values (); - FloatDiagMatrix sigma = result.singular_values (); - - if (nargout == 0 || nargout == 1) - { - retval(0) = sigma.extract_diag (); - } - else - { - retval(2) = result.right_singular_matrix (); - retval(1) = sigma; - retval(0) = result.left_singular_matrix (); - } + if (nargout == 0 || nargout == 1) + retval(0) = sigma.extract_diag (); + else + { + retval(2) = result.right_singular_matrix (); + retval(1) = sigma; + retval(0) = result.left_singular_matrix (); } } else if (arg.is_complex_type ()) { FloatComplexMatrix ctmp = arg.float_complex_matrix_value (); - if (! error_state) - { - if (ctmp.any_element_is_inf_or_nan ()) - { - error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - return retval; - } + if (ctmp.any_element_is_inf_or_nan ()) + error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - FloatComplexSVD result (ctmp, type, driver); + FloatComplexSVD result (ctmp, type, driver); + + FloatDiagMatrix sigma = result.singular_values (); - FloatDiagMatrix sigma = result.singular_values (); - - if (nargout == 0 || nargout == 1) - { - retval(0) = sigma.extract_diag (); - } - else - { - retval(2) = result.right_singular_matrix (); - retval(1) = sigma; - retval(0) = result.left_singular_matrix (); - } + if (nargout == 0 || nargout == 1) + retval(0) = sigma.extract_diag (); + else + { + retval(2) = result.right_singular_matrix (); + retval(1) = sigma; + retval(0) = result.left_singular_matrix (); } } } @@ -261,63 +243,44 @@ { Matrix tmp = arg.matrix_value (); - if (! error_state) - { - if (tmp.any_element_is_inf_or_nan ()) - { - error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - return retval; - } + if (tmp.any_element_is_inf_or_nan ()) + error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - SVD result (tmp, type, driver); + SVD result (tmp, type, driver); + + DiagMatrix sigma = result.singular_values (); - DiagMatrix sigma = result.singular_values (); - - if (nargout == 0 || nargout == 1) - { - retval(0) = sigma.extract_diag (); - } - else - { - retval(2) = result.right_singular_matrix (); - retval(1) = sigma; - retval(0) = result.left_singular_matrix (); - } + if (nargout == 0 || nargout == 1) + retval(0) = sigma.extract_diag (); + else + { + retval(2) = result.right_singular_matrix (); + retval(1) = sigma; + retval(0) = result.left_singular_matrix (); } } else if (arg.is_complex_type ()) { ComplexMatrix ctmp = arg.complex_matrix_value (); - if (! error_state) - { - if (ctmp.any_element_is_inf_or_nan ()) - { - error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - return retval; - } + if (ctmp.any_element_is_inf_or_nan ()) + error ("svd: cannot take SVD of matrix containing Inf or NaN values"); - ComplexSVD result (ctmp, type, driver); + ComplexSVD result (ctmp, type, driver); + + DiagMatrix sigma = result.singular_values (); - DiagMatrix sigma = result.singular_values (); - - if (nargout == 0 || nargout == 1) - { - retval(0) = sigma.extract_diag (); - } - else - { - retval(2) = result.right_singular_matrix (); - retval(1) = sigma; - retval(0) = result.left_singular_matrix (); - } + if (nargout == 0 || nargout == 1) + retval(0) = sigma.extract_diag (); + else + { + retval(2) = result.right_singular_matrix (); + retval(1) = sigma; + retval(0) = result.left_singular_matrix (); } } else - { - gripe_wrong_type_arg ("svd", arg); - return retval; - } + gripe_wrong_type_arg ("svd", arg); } } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/toplev.cc --- a/libinterp/corefcn/toplev.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/toplev.cc Thu Oct 01 16:18:19 2015 -0400 @@ -651,20 +651,18 @@ break; } } - catch (octave_interrupt_exception) + catch (const octave_interrupt_exception&) { recover_from_exception (); octave_stdout << "\n"; if (quitting_gracefully) return exit_status; } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { recover_from_exception (); - std::cerr << "error: unhandled execution exception -- trying to return to prompt" - << std::endl; } - catch (std::bad_alloc) + catch (const std::bad_alloc&) { recover_from_exception (); std::cerr << "error: out of memory -- trying to return to prompt" diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/toplev.h --- a/libinterp/corefcn/toplev.h Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/toplev.h Thu Oct 01 16:18:19 2015 -0400 @@ -517,12 +517,9 @@ \ F ARGS; \ } \ - OCTAVE_IGNORE_EXCEPTION (octave_interrupt_exception) \ - OCTAVE_IGNORE_EXCEPTION (octave_execution_exception) \ - OCTAVE_IGNORE_EXCEPTION (std::bad_alloc) \ - \ - if (error_state) \ - error_state = 0; \ + OCTAVE_IGNORE_EXCEPTION (const octave_interrupt_exception&) \ + OCTAVE_IGNORE_EXCEPTION (const octave_execution_exception&) \ + OCTAVE_IGNORE_EXCEPTION (const std::bad_alloc&) \ } \ while (0) diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/utils.cc --- a/libinterp/corefcn/utils.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/utils.cc Thu Oct 01 16:18:19 2015 -0400 @@ -1473,7 +1473,7 @@ else retval = false; } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { retval = false; } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/corefcn/variables.cc --- a/libinterp/corefcn/variables.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/corefcn/variables.cc Thu Oct 01 16:18:19 2015 -0400 @@ -268,7 +268,6 @@ unwind_protect frame; frame.protect_var (error_state); - frame.protect_var (warning_state); frame.protect_var (discard_error_messages); frame.protect_var (discard_warning_messages); @@ -377,9 +376,14 @@ unwind_protect frame; interpreter_try (frame); - retval = symbol_table::find (symbol_name); - - error_state = 0; + try + { + retval = symbol_table::find (symbol_name); + } + catch (const octave_execution_exception&) + { + // Ignore errors. + } return retval; } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/dldfcn/__magick_read__.cc --- a/libinterp/dldfcn/__magick_read__.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/dldfcn/__magick_read__.cc Thu Oct 01 16:18:19 2015 -0400 @@ -691,7 +691,6 @@ catch (Magick::Exception& e) { error ("Magick++ exception: %s", e.what ()); - error_state = 1; } } @@ -1382,7 +1381,6 @@ catch (Magick::Exception& e) { error ("Magick++ exception: %s", e.what ()); - error_state = 1; } } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov-builtin.cc --- a/libinterp/octave-value/ov-builtin.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov-builtin.cc Thu Oct 01 16:18:19 2015 -0400 @@ -124,29 +124,22 @@ curr_lvalue_list = lvalue_list; } - try - { - BEGIN_PROFILER_BLOCK (octave_builtin) + BEGIN_PROFILER_BLOCK (octave_builtin) - retval = (*f) (args, nargout); - // Do not allow null values to be returned from functions. - // FIXME: perhaps true builtins should be allowed? - retval.make_storable_values (); - // Fix the case of a single undefined value. - // This happens when a compiled function uses - // octave_value retval; - // instead of - // octave_value_list retval; - // the idiom is very common, so we solve that here. - if (retval.length () == 1 && retval.xelem (0).is_undefined ()) - retval.clear (); + retval = (*f) (args, nargout); + // Do not allow null values to be returned from functions. + // FIXME: perhaps true builtins should be allowed? + retval.make_storable_values (); + // Fix the case of a single undefined value. + // This happens when a compiled function uses + // octave_value retval; + // instead of + // octave_value_list retval; + // the idiom is very common, so we solve that here. + if (retval.length () == 1 && retval.xelem (0).is_undefined ()) + retval.clear (); - END_PROFILER_BLOCK - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + END_PROFILER_BLOCK } return retval; diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov-class.cc Thu Oct 01 16:18:19 2015 -0400 @@ -1172,13 +1172,21 @@ interpreter_try (frame); - octave_value_list result - = ctor.do_multi_index_op (1, octave_value_list ()); + bool execution_error = false; + + octave_value_list result; - if (! error_state && result.length () == 1) + try + { + result = ctor.do_multi_index_op (1, octave_value_list ()); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (! execution_error && result.length () == 1) retval = true; - - error_state = false; } else warning ("no constructor for class %s", c_name.c_str ()); diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov-fcn-handle.cc Thu Oct 01 16:18:19 2015 -0400 @@ -2083,8 +2083,18 @@ unwind_protect frame; interpreter_try (frame); - root_val = make_fcn_handle (head_name); - if (error_state) + bool execution_error = false; + + try + { + root_val = make_fcn_handle (head_name); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (execution_error) bad = true; } } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov-mex-fcn.cc --- a/libinterp/octave-value/ov-mex-fcn.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov-mex-fcn.cc Thu Oct 01 16:18:19 2015 -0400 @@ -145,18 +145,11 @@ frame.add_fcn (octave_call_stack::pop); - try - { - BEGIN_PROFILER_BLOCK (octave_mex_function) - - retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this); + BEGIN_PROFILER_BLOCK (octave_mex_function) - END_PROFILER_BLOCK - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + retval = call_mex (have_fmex, mex_fcn_ptr, args, nargout, this); + + END_PROFILER_BLOCK } return retval; diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov-oncleanup.cc --- a/libinterp/octave-value/ov-oncleanup.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov-oncleanup.cc Thu Oct 01 16:18:19 2015 -0400 @@ -78,29 +78,26 @@ frame.protect_var (quit_allowed); quit_allowed = false; - // Clear errors. - frame.protect_var (error_state); - error_state = 0; - try { // Run the actual code. fcn.do_multi_index_op (0, octave_value_list ()); } - catch (octave_interrupt_exception) + catch (const octave_interrupt_exception&) { // Swallow the interrupt. warning ("onCleanup: interrupt occured in cleanup action"); } + catch (const octave_execution_exception&) + { + // Propagate the error. + throw; + } catch (...) // Yes, the black hole. We're in a d-tor. { // This shouldn't happen, in theory. error ("onCleanup: internal error: unhandled exception in cleanup action"); } - - // FIXME: can this happen now? - if (error_state) - frame.discard_first (); } octave_scalar_map diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave-value/ov.cc Thu Oct 01 16:18:19 2015 -0400 @@ -1490,16 +1490,9 @@ if (f) { - try - { - f (*rep, octave_value_list (), *rhs.rep); - // Usually unnecessary, but may be needed (complex arrays). - maybe_mutate (); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + f (*rep, octave_value_list (), *rhs.rep); + // Usually unnecessary, but may be needed (complex arrays). + maybe_mutate (); } else { @@ -1993,14 +1986,7 @@ if (f) { - try - { - retval = f (v1, v2); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + retval = f (v1, v2); } else gripe_binary_op (octave_value::binary_op_as_string (op), @@ -2015,16 +2001,7 @@ = octave_value_typeinfo::lookup_binary_op (op, t1, t2); if (f) - { - try - { - retval = f (*v1.rep, *v2.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (*v1.rep, *v2.rep); else { octave_value tv1; @@ -2143,16 +2120,7 @@ f = octave_value_typeinfo::lookup_binary_op (op, t1, t2); if (f) - { - try - { - retval = f (*tv1.rep, *tv2.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (*tv1.rep, *tv2.rep); else gripe_binary_op (octave_value::binary_op_as_string (op), v1.type_name (), v2.type_name ()); @@ -2251,16 +2219,7 @@ = octave_value_typeinfo::lookup_binary_class_op (op); if (f) - { - try - { - retval = f (v1, v2); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (v1, v2); else retval = decompose_binary_op (op, v1, v2); } @@ -2270,16 +2229,7 @@ = octave_value_typeinfo::lookup_binary_op (op, t1, t2); if (f) - { - try - { - retval = f (*v1.rep, *v2.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (*v1.rep, *v2.rep); else retval = decompose_binary_op (op, v1, v2); } @@ -2316,16 +2266,7 @@ = octave_value_typeinfo::lookup_cat_op (t1, t2); if (f) - { - try - { - retval = f (*v1.rep, *v2.rep, ra_idx); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (*v1.rep, *v2.rep, ra_idx); else { octave_value tv1; @@ -2521,16 +2462,7 @@ = octave_value_typeinfo::lookup_unary_class_op (op); if (f) - { - try - { - retval = f (v); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (v); else gripe_unary_op (octave_value::unary_op_as_string (op), v.class_name ()); @@ -2544,16 +2476,7 @@ = octave_value_typeinfo::lookup_unary_op (op, t); if (f) - { - try - { - retval = f (*v.rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + retval = f (*v.rep); else { octave_value tv; @@ -2615,14 +2538,7 @@ { make_unique (); - try - { - f (*rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + f (*rep); } else { @@ -2643,14 +2559,7 @@ if (f) { - try - { - f (*rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } + f (*rep); if (old_rep && --old_rep->count == 0) delete old_rep; @@ -2690,16 +2599,7 @@ f = octave_value_typeinfo::lookup_non_const_unary_op (op, t); if (f) - { - try - { - f (*rep); - } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - } + f (*rep); else *this = do_unary_op (op, *this); } diff -r fcb792acab9b -r b70cc4bd8109 libinterp/octave.cc --- a/libinterp/octave.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/octave.cc Thu Oct 01 16:18:19 2015 -0400 @@ -279,14 +279,14 @@ { source_file (file_name, context, verbose, require_file, warn_for); } - catch (octave_interrupt_exception) + catch (const octave_interrupt_exception&) { recover_from_exception (); octave_stdout << "\n"; if (quitting_gracefully) clean_up_and_exit (exit_status); } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { recover_from_exception (); gripe_safe_source_exception (file_name, "unhandled execution exception"); @@ -394,14 +394,14 @@ { eval_string (code, false, parse_status, 0); } - catch (octave_interrupt_exception) + catch (const octave_interrupt_exception&) { recover_from_exception (); octave_stdout << "\n"; if (quitting_gracefully) clean_up_and_exit (exit_status); } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { recover_from_exception (); std::cerr << "error: unhandled execution exception -- eval failed" diff -r fcb792acab9b -r b70cc4bd8109 libinterp/parse-tree/oct-parse.in.yy --- a/libinterp/parse-tree/oct-parse.in.yy Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/parse-tree/oct-parse.in.yy Thu Oct 01 16:18:19 2015 -0400 @@ -2247,7 +2247,6 @@ unwind_protect frame; frame.protect_var (error_state); - frame.protect_var (warning_state); frame.protect_var (discard_error_messages); frame.protect_var (discard_warning_messages); @@ -2268,7 +2267,7 @@ { octave_value tmp = e->rvalue1 (); - if (! (error_state || warning_state)) + if (! error_state) { tree_constant *tc_retval = new tree_constant (tmp, base->line (), base->column ()); @@ -3800,7 +3799,6 @@ unwind_protect frame; frame.protect_var (error_state); - frame.protect_var (warning_state); frame.protect_var (discard_error_messages); frame.protect_var (discard_warning_messages); @@ -3812,7 +3810,7 @@ { octave_value tmp = array_list->rvalue1 (); - if (! (error_state || warning_state)) + if (! error_state) { tree_constant *tc_retval = new tree_constant (tmp, array_list->line (), @@ -4999,13 +4997,21 @@ int parse_status = 0; - octave_value_list tmp = eval_string (args(0), nargout > 0, - parse_status, nargout); - - if (nargin > 1 && (parse_status != 0 || error_state)) + bool execution_error = false; + + octave_value_list tmp; + + try { - error_state = 0; - + tmp = eval_string (args(0), nargout > 0, parse_status, nargout); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (nargin > 1 && (parse_status != 0 || execution_error)) + { // Set up for letting the user print any messages from // errors that occurred in the first part of this eval(). @@ -5016,8 +5022,16 @@ if (nargout > 0) retval = tmp; } - else if (nargout > 0) - retval = tmp; + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever exception occurred, + // not just throwing an execution exception. + if (execution_error) + octave_throw_execution_exception (); + } } else print_usage (); @@ -5156,16 +5170,22 @@ int parse_status = 0; - octave_value_list tmp = eval_string (args(1), nargout > 0, - parse_status, nargout); - - if (nargout > 0) - retval = tmp; - - if (nargin > 2 && (parse_status != 0 || error_state)) + bool execution_error = false; + + octave_value_list tmp; + + try { - error_state = 0; - + tmp = eval_string (args(1), nargout > 0, + parse_status, nargout); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } + + if (nargin > 2 && (parse_status != 0 || execution_error)) + { // Set up for letting the user print any messages from // errors that occurred in the first part of this eval(). @@ -5176,6 +5196,17 @@ retval = (nargout > 0) ? tmp : octave_value_list (); } + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever + // exception occurred, not just throwing an + // execution exception. + if (execution_error) + octave_throw_execution_exception (); + } } } else diff -r fcb792acab9b -r b70cc4bd8109 libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/parse-tree/pt-eval.cc Thu Oct 01 16:18:19 2015 -0400 @@ -59,6 +59,8 @@ bool tree_evaluator::quiet_breakpoint_flag = false; +bool tree_evaluator::unwind_protect_exception = false; + tree_evaluator::stmt_list_type tree_evaluator::statement_context = tree_evaluator::other; @@ -751,11 +753,7 @@ // result_values(0) = tmp_result; } } - catch (octave_execution_exception) - { - gripe_library_execution_error (); - } - catch (std::bad_alloc) + catch (const std::bad_alloc&) { // FIXME: We want to use error_with_id here so that we set // the error state, give users control over this error @@ -902,15 +900,22 @@ tree_statement_list *try_code = cmd.body (); + bool execution_error = false; + if (try_code) { - try_code->accept (*this); + try + { + try_code->accept (*this); + } + catch (const octave_execution_exception&) + { + execution_error = true; + } } - if (error_state) + if (execution_error) { - error_state = 0; - if (catch_code) { // Set up for letting the user print any messages from errors that @@ -923,21 +928,15 @@ if (expr_id) { + ult = expr_id->lvalue (); octave_scalar_map err; - ult = expr_id->lvalue (); - - if (error_state) - return; - err.assign ("message", last_error_message ()); err.assign ("identifier", last_error_id ()); err.assign ("stack", last_error_stack ()); - if (! error_state) - ult.assign (octave_value::op_asn_eq, err); - + ult.assign (octave_value::op_asn_eq, err); } if (catch_code) @@ -954,14 +953,6 @@ frame.protect_var (octave_interrupt_state); octave_interrupt_state = 0; - // We want to run the cleanup code without error_state being set, - // but we need to restore its value, so that any errors encountered - // in the first part of the unwind_protect are not completely - // ignored. - - frame.protect_var (error_state); - error_state = 0; - // We want to preserve the last location info for possible // backtracking. frame.add_fcn (octave_call_stack::set_line, @@ -980,8 +971,17 @@ frame.protect_var (tree_break_command::breaking); tree_break_command::breaking = 0; - if (list) - list->accept (*this); + bool execution_error_in_cleanup = false; + + try + { + if (list) + list->accept (*this); + } + catch (const octave_execution_exception&) + { + execution_error_in_cleanup = true; + } // The unwind_protects are popped off the stack in the reverse of // the order they are pushed on. @@ -1011,24 +1011,30 @@ // whatever they were when the cleanup block was entered. if (tree_break_command::breaking || tree_return_command::returning) - { - frame.discard (2); - } + frame.discard (2); else - { - frame.run (2); - } + frame.run (2); - // We don't want to ignore errors that occur in the cleanup code, so - // if an error is encountered there, leave error_state alone. - // Otherwise, set it back to what it was before. + // We don't want to ignore errors that occur in the cleanup code, + // so if an error is encountered there, rethrow the exception. + // Otherwise, rethrow any exception that might have occurred in the + // unwind_protect block. - if (error_state) + if (execution_error_in_cleanup) frame.discard (2); else frame.run (2); frame.run (); + + // FIXME: we should really be rethrowing whatever exception occurred, + // not just throwing an execution exception. + if (unwind_protect_exception || execution_error_in_cleanup) + { + unwind_protect_exception = false; + + octave_throw_execution_exception (); + } } void @@ -1040,15 +1046,20 @@ if (unwind_protect_code) { + unwind_protect_exception = false; + try { unwind_protect_code->accept (*this); } - catch (...) + catch (const octave_execution_exception&) { + unwind_protect_exception = true; + // Run the cleanup code on exceptions, so that it is run even in case // of interrupt or out-of-memory. do_unwind_protect_cleanup_code (cleanup_code); + // FIXME: should error_state be checked here? // We want to rethrow the exception, even if error_state is set, so // that interrupts continue. diff -r fcb792acab9b -r b70cc4bd8109 libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h Thu Sep 24 12:58:46 2015 +0200 +++ b/libinterp/parse-tree/pt-eval.h Thu Oct 01 16:18:19 2015 -0400 @@ -153,6 +153,8 @@ static bool quiet_breakpoint_flag; + static bool unwind_protect_exception; + // Possible types of evaluation contexts. enum stmt_list_type { diff -r fcb792acab9b -r b70cc4bd8109 liboctave/cruft/misc/quit.h --- a/liboctave/cruft/misc/quit.h Thu Sep 24 12:58:46 2015 +0200 +++ b/liboctave/cruft/misc/quit.h Thu Oct 01 16:18:19 2015 -0400 @@ -195,18 +195,18 @@ #define END_INTERRUPT_WITH_EXCEPTIONS \ } \ - catch (octave_interrupt_exception) \ + catch (const octave_interrupt_exception&) \ { \ octave_interrupt_immediately = saved_octave_interrupt_immediately; \ octave_jump_to_enclosing_context (); \ } \ - catch (octave_execution_exception) \ + catch (const octave_execution_exception&) \ { \ octave_interrupt_immediately = saved_octave_interrupt_immediately; \ octave_exception_state = octave_exec_exception; \ octave_jump_to_enclosing_context (); \ } \ - catch (std::bad_alloc) \ + catch (const std::bad_alloc&) \ { \ octave_interrupt_immediately = saved_octave_interrupt_immediately; \ octave_exception_state = octave_alloc_exception; \ diff -r fcb792acab9b -r b70cc4bd8109 liboctave/util/cmd-edit.cc --- a/liboctave/util/cmd-edit.cc Thu Sep 24 12:58:46 2015 +0200 +++ b/liboctave/util/cmd-edit.cc Thu Oct 01 16:18:19 2015 -0400 @@ -1668,7 +1668,7 @@ { temp = octave_env::get_current_directory (); } - catch (octave_execution_exception) + catch (const octave_execution_exception&) { temp = ""; }