changeset 20569:b70cc4bd8109

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.
author John W. Eaton <jwe@octave.org>
date Thu, 01 Oct 2015 16:18:19 -0400
parents fcb792acab9b
children 6256f6e366ac
files NEWS doc/interpreter/external.txi libinterp/corefcn/cellfun.cc libinterp/corefcn/error.cc libinterp/corefcn/gripes.cc libinterp/corefcn/gripes.h libinterp/corefcn/jit-typeinfo.cc libinterp/corefcn/load-path.cc libinterp/corefcn/ls-mat-ascii.cc libinterp/corefcn/mex.cc libinterp/corefcn/rand.cc libinterp/corefcn/svd.cc libinterp/corefcn/toplev.cc libinterp/corefcn/toplev.h libinterp/corefcn/utils.cc libinterp/corefcn/variables.cc libinterp/dldfcn/__magick_read__.cc libinterp/octave-value/ov-builtin.cc libinterp/octave-value/ov-class.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/octave-value/ov-mex-fcn.cc libinterp/octave-value/ov-oncleanup.cc libinterp/octave-value/ov.cc libinterp/octave.cc libinterp/parse-tree/oct-parse.in.yy libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-eval.h liboctave/cruft/misc/quit.h liboctave/util/cmd-edit.cc
diffstat 29 files changed, 538 insertions(+), 720 deletions(-) [+]
line wrap: on
line diff
--- 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:
 ---------------------------------------------------------
--- 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
--- 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 ();
--- 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);
--- 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");
--- 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
--- 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_vector> idx;
-      make_indices (indicies, idx_count, idx);
+  Array<idx_vector> idx;
+  make_indices (indicies, idx_count, idx);
 
-      Array<double> ret = mat->array->index (idx);
-      return ret.xelem (0);
-    }
-  catch (const octave_execution_exception&)
-    {
-      gripe_library_execution_error ();
-      return 0;
-    }
+  Array<double> 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_vector> idx;
-      make_indices (indices, idx_count, idx);
+
+  Array<idx_vector> 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;
 }
--- 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.
         }
--- 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 ();
 
--- 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;
 }
--- 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<octave_idx_type> (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.
--- 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);
         }
     }
 
--- 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"
--- 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)
 
--- 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;
         }
--- 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;
 }
--- 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;
     }
 }
 
--- 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;
--- 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 ());
--- 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;
                         }
                     }
--- 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;
--- 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
--- 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);
     }
--- 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"
--- 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
--- 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.
--- 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
   {
--- 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; \
--- 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 = "";
                   }