mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
Don’t ignore -Wclobbered in eval.c
This fix is also prompted by Emacs bug#71744. * src/eval.c (CACHEABLE): Remove. All uses removed. Do not ignore -Wclobbered. (internal_lisp_condition_case): Fix violations of the C standard, where setjmp clobbered oldhandlerlist, var, and clauses. Rewrite to pacify GCC, by using a sentinel rather than a count, which GCC incorrectly complained about, and by coalescing some duplicate code. If GCC_LINT && __GNUC__ && !__clang__ add a useless assignment to pacify GCC.
This commit is contained in:
parent
cfa5a634e9
commit
1282714da5
1 changed files with 47 additions and 62 deletions
109
src/eval.c
109
src/eval.c
|
|
@ -31,15 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "pdumper.h"
|
||||
#include "atimer.h"
|
||||
|
||||
/* CACHEABLE is ordinarily nothing, except it is 'volatile' if
|
||||
necessary to cajole GCC into not warning incorrectly that a
|
||||
variable should be volatile. */
|
||||
#if defined GCC_LINT || defined lint
|
||||
# define CACHEABLE volatile
|
||||
#else
|
||||
# define CACHEABLE /* empty */
|
||||
#endif
|
||||
|
||||
/* Non-nil means record all fset's and provide's, to be undone
|
||||
if the file being autoloaded is not fully loaded.
|
||||
They are recorded by being consed onto the front of Vautoload_queue:
|
||||
|
|
@ -430,7 +421,7 @@ DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
|
|||
usage: (progn BODY...) */)
|
||||
(Lisp_Object body)
|
||||
{
|
||||
Lisp_Object CACHEABLE val = Qnil;
|
||||
Lisp_Object val = Qnil;
|
||||
|
||||
while (CONSP (body))
|
||||
{
|
||||
|
|
@ -1257,12 +1248,6 @@ usage: (catch TAG BODY...) */)
|
|||
return internal_catch (tag, Fprogn, XCDR (args));
|
||||
}
|
||||
|
||||
/* Work around GCC bug 61118
|
||||
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61118>. */
|
||||
#if GNUC_PREREQ (4, 9, 0)
|
||||
# pragma GCC diagnostic ignored "-Wclobbered"
|
||||
#endif
|
||||
|
||||
/* Assert that E is true, but do not evaluate E. Use this instead of
|
||||
eassert (E) when E contains variables that might be clobbered by a
|
||||
longjmp. */
|
||||
|
|
@ -1488,8 +1473,10 @@ Lisp_Object
|
|||
internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
|
||||
Lisp_Object handlers)
|
||||
{
|
||||
struct handler *oldhandlerlist = handlerlist;
|
||||
ptrdiff_t CACHEABLE clausenb = 0;
|
||||
struct handler *volatile oldhandlerlist = handlerlist;
|
||||
|
||||
/* The number of non-success handlers, plus 1 for a sentinel. */
|
||||
ptrdiff_t clausenb = 1;
|
||||
|
||||
var = maybe_remove_pos_from_symbol (var);
|
||||
CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var);
|
||||
|
|
@ -1521,69 +1508,67 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
|
|||
memory_full (SIZE_MAX);
|
||||
Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses);
|
||||
clauses += clausenb;
|
||||
*--clauses = make_fixnum (0);
|
||||
for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
|
||||
{
|
||||
Lisp_Object tem = XCAR (tail);
|
||||
if (!(CONSP (tem) && EQ (XCAR (tem), QCsuccess)))
|
||||
*--clauses = tem;
|
||||
}
|
||||
for (ptrdiff_t i = 0; i < clausenb; i++)
|
||||
Lisp_Object volatile var_volatile = var;
|
||||
Lisp_Object val, handler_body;
|
||||
for (Lisp_Object volatile *pcl = clauses; ; pcl++)
|
||||
{
|
||||
Lisp_Object clause = clauses[i];
|
||||
if (BASE_EQ (*pcl, make_fixnum (0)))
|
||||
{
|
||||
val = eval_sub (bodyform);
|
||||
handlerlist = oldhandlerlist;
|
||||
if (NILP (success_handler))
|
||||
return val;
|
||||
#if GCC_LINT && __GNUC__ && !__clang__
|
||||
/* This useless assignment pacifies GCC 14.2.1 x86-64
|
||||
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161>. */
|
||||
var = var_volatile;
|
||||
#endif
|
||||
handler_body = XCDR (success_handler);
|
||||
break;
|
||||
}
|
||||
Lisp_Object clause = *pcl;
|
||||
Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil;
|
||||
if (!CONSP (condition))
|
||||
condition = list1 (condition);
|
||||
struct handler *c = push_handler (condition, CONDITION_CASE);
|
||||
Lisp_Object volatile *clauses_volatile = clauses;
|
||||
if (sys_setjmp (c->jmp))
|
||||
{
|
||||
Lisp_Object val = handlerlist->val;
|
||||
Lisp_Object volatile *chosen_clause = clauses;
|
||||
for (struct handler *h = handlerlist->next; h != oldhandlerlist;
|
||||
h = h->next)
|
||||
var = var_volatile;
|
||||
val = handlerlist->val;
|
||||
Lisp_Object volatile *chosen_clause = clauses_volatile;
|
||||
struct handler *oldh = oldhandlerlist;
|
||||
for (struct handler *h = handlerlist->next; h != oldh; h = h->next)
|
||||
chosen_clause++;
|
||||
Lisp_Object handler_body = XCDR (*chosen_clause);
|
||||
handlerlist = oldhandlerlist;
|
||||
handler_body = XCDR (*chosen_clause);
|
||||
handlerlist = oldh;
|
||||
|
||||
if (NILP (var))
|
||||
return Fprogn (handler_body);
|
||||
|
||||
Lisp_Object handler_var = var;
|
||||
if (!NILP (Vinternal_interpreter_environment))
|
||||
{
|
||||
val = Fcons (Fcons (var, val),
|
||||
Vinternal_interpreter_environment);
|
||||
handler_var = Qinternal_interpreter_environment;
|
||||
}
|
||||
|
||||
/* Bind HANDLER_VAR to VAL while evaluating HANDLER_BODY.
|
||||
The unbind_to undoes just this binding; whoever longjumped
|
||||
to us unwound the stack to C->pdlcount before throwing. */
|
||||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
specbind (handler_var, val);
|
||||
return unbind_to (count, Fprogn (handler_body));
|
||||
/* Whoever longjumped to us unwound the stack to C->pdlcount before
|
||||
throwing, so the unbind_to will undo just this binding. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lisp_Object CACHEABLE result = eval_sub (bodyform);
|
||||
handlerlist = oldhandlerlist;
|
||||
if (!NILP (success_handler))
|
||||
if (NILP (var))
|
||||
return Fprogn (handler_body);
|
||||
|
||||
if (!NILP (Vinternal_interpreter_environment))
|
||||
{
|
||||
if (NILP (var))
|
||||
return Fprogn (XCDR (success_handler));
|
||||
|
||||
Lisp_Object handler_var = var;
|
||||
if (!NILP (Vinternal_interpreter_environment))
|
||||
{
|
||||
result = Fcons (Fcons (var, result),
|
||||
Vinternal_interpreter_environment);
|
||||
handler_var = Qinternal_interpreter_environment;
|
||||
}
|
||||
|
||||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
specbind (handler_var, result);
|
||||
return unbind_to (count, Fprogn (XCDR (success_handler)));
|
||||
val = Fcons (Fcons (var, val),
|
||||
Vinternal_interpreter_environment);
|
||||
var = Qinternal_interpreter_environment;
|
||||
}
|
||||
return result;
|
||||
|
||||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
specbind (var, val);
|
||||
return unbind_to (count, Fprogn (handler_body));
|
||||
}
|
||||
|
||||
/* Call the function BFUN with no arguments, catching errors within it
|
||||
|
|
@ -1740,7 +1725,7 @@ push_handler (Lisp_Object tag_ch_val, enum handlertype handlertype)
|
|||
struct handler *
|
||||
push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype)
|
||||
{
|
||||
struct handler *CACHEABLE c = handlerlist->nextfree;
|
||||
struct handler *c = handlerlist->nextfree;
|
||||
if (!c)
|
||||
{
|
||||
c = malloc (sizeof *c);
|
||||
|
|
|
|||
Loading…
Reference in a new issue