]> git.eshelyaron.com Git - emacs.git/commitdiff
Don’t ignore -Wclobbered in eval.c
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 17 Aug 2024 00:08:36 +0000 (17:08 -0700)
committerEshel Yaron <me@eshelyaron.com>
Tue, 20 Aug 2024 14:08:51 +0000 (16:08 +0200)
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.

(cherry picked from commit 1282714da55cd4bbc1c7f2e49edeb43503427e5e)

src/eval.c

index b4103acd28f8b172764a7f5b323bdd869873c472..ce7b08e894a897f1e1c70209c94f16e22f8d8720 100644 (file)
@@ -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;
-
-         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);