Don't signal during backtrace unrewind (Bug#40088)
backtrace_eval_unrewind is used to temporarily reverse let-bindings (it's called with a positive argument to reverse bindings, and then a negative argument to re-apply them) by backtrace--locals and backtrace-eval. For the SPECPDL_LET_DEFAULT and SPECPDL_LET_LOCAL cases (which occur for let-bindings on buffer-local variables), the code calls Fdefault_value and Fbuffer_local_value on the symbol. For symbols which are unbound at top-level, the first (with positive argument) call to backtrace_eval_unrewind will set the symbol's value to unbound (putting the current value in the specpdl's "old value" slot). On the second (with negative argument) call, backtrace_eval_unrewind attempts to retrieve the symbol's value with Fdefault_value or Fbuffer_local_value, but that raises a void-variable signal. This interrupts the restoration of the let-bindings, so any other variables more recent on the stack will now have the wrong value. * src/data.c (default_value): Make non-static. * src/lisp.h: Declare it. * src/eval.c (backtrace_eval_unrewind): Replace the calls to Fdefault_value and Fbuffer_local_value with default_value and buffer_local_value, respectively. The latter do exactly the same as the former, except if the symbol's value is Qunbound they just return it instead of signaling void-variable.
This commit is contained in:
parent
8709aaddd8
commit
8944310d7c
3 changed files with 4 additions and 3 deletions
|
@ -1573,7 +1573,7 @@ notify_variable_watchers (Lisp_Object symbol,
|
|||
/* Return the default value of SYMBOL, but don't check for voidness.
|
||||
Return Qunbound if it is void. */
|
||||
|
||||
static Lisp_Object
|
||||
Lisp_Object
|
||||
default_value (Lisp_Object symbol)
|
||||
{
|
||||
struct Lisp_Symbol *sym;
|
||||
|
|
|
@ -3816,7 +3816,7 @@ backtrace_eval_unrewind (int distance)
|
|||
{
|
||||
Lisp_Object sym = specpdl_symbol (tmp);
|
||||
Lisp_Object old_value = specpdl_old_value (tmp);
|
||||
set_specpdl_old_value (tmp, Fdefault_value (sym));
|
||||
set_specpdl_old_value (tmp, default_value (sym));
|
||||
Fset_default (sym, old_value);
|
||||
}
|
||||
break;
|
||||
|
@ -3832,7 +3832,7 @@ backtrace_eval_unrewind (int distance)
|
|||
if (!NILP (Flocal_variable_p (symbol, where)))
|
||||
{
|
||||
set_specpdl_old_value
|
||||
(tmp, Fbuffer_local_value (symbol, where));
|
||||
(tmp, buffer_local_value (symbol, where));
|
||||
set_internal (symbol, old_value, where, SET_INTERNAL_UNBIND);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -594,6 +594,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
|
|||
|
||||
/* Defined in data.c. */
|
||||
extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
|
||||
extern Lisp_Object default_value (Lisp_Object symbol);
|
||||
|
||||
|
||||
/* Defined in emacs.c. */
|
||||
|
|
Loading…
Add table
Reference in a new issue