From 1282714da55cd4bbc1c7f2e49edeb43503427e5e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 16 Aug 2024 17:08:36 -0700 Subject: [PATCH 3/6] =?UTF-8?q?Don=E2=80=99t=20ignore=20-Wclobbered=20in?= =?UTF-8?q?=20eval.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/eval.c | 109 +++++++++++++++++++++++------------------------------ 1 file changed, 47 insertions(+), 62 deletions(-) diff --git a/src/eval.c b/src/eval.c index b4103acd28f..ce7b08e894a 100644 --- a/src/eval.c +++ b/src/eval.c @@ -31,15 +31,6 @@ Copyright (C) 1985-1987, 1993-1995, 1999-2024 Free Software Foundation, #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 @@ DEFUN ("catch", Fcatch, Scatch, 1, UNEVALLED, 0, return internal_catch (tag, Fprogn, XCDR (args)); } -/* Work around GCC bug 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 @@ DEFUN ("handler-bind-1", Fhandler_bind_1, Shandler_bind_1, 1, MANY, 0, 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 + . */ + 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; - - if (NILP (var)) - return Fprogn (handler_body); + handler_body = XCDR (*chosen_clause); + handlerlist = oldh; - 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 (XCDR (success_handler)); + if (NILP (var)) + return Fprogn (handler_body); - 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))); + if (!NILP (Vinternal_interpreter_environment)) + { + 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); -- 2.43.0