aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorPaul Eggert2024-08-16 17:08:36 -0700
committerPaul Eggert2024-08-16 21:16:35 -0700
commit1282714da55cd4bbc1c7f2e49edeb43503427e5e (patch)
tree70d13308ef9e0892ca49067738b2803013dd74dd /src/eval.c
parentcfa5a634e91f5c232a71ec212679165074dc480b (diff)
downloademacs-1282714da55cd4bbc1c7f2e49edeb43503427e5e.tar.gz
emacs-1282714da55cd4bbc1c7f2e49edeb43503427e5e.zip
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.
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c109
1 files 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 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
31#include "pdumper.h" 31#include "pdumper.h"
32#include "atimer.h" 32#include "atimer.h"
33 33
34/* CACHEABLE is ordinarily nothing, except it is 'volatile' if
35 necessary to cajole GCC into not warning incorrectly that a
36 variable should be volatile. */
37#if defined GCC_LINT || defined lint
38# define CACHEABLE volatile
39#else
40# define CACHEABLE /* empty */
41#endif
42
43/* Non-nil means record all fset's and provide's, to be undone 34/* Non-nil means record all fset's and provide's, to be undone
44 if the file being autoloaded is not fully loaded. 35 if the file being autoloaded is not fully loaded.
45 They are recorded by being consed onto the front of Vautoload_queue: 36 They are recorded by being consed onto the front of Vautoload_queue:
@@ -430,7 +421,7 @@ DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0,
430usage: (progn BODY...) */) 421usage: (progn BODY...) */)
431 (Lisp_Object body) 422 (Lisp_Object body)
432{ 423{
433 Lisp_Object CACHEABLE val = Qnil; 424 Lisp_Object val = Qnil;
434 425
435 while (CONSP (body)) 426 while (CONSP (body))
436 { 427 {
@@ -1257,12 +1248,6 @@ usage: (catch TAG BODY...) */)
1257 return internal_catch (tag, Fprogn, XCDR (args)); 1248 return internal_catch (tag, Fprogn, XCDR (args));
1258} 1249}
1259 1250
1260/* Work around GCC bug 61118
1261 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61118>. */
1262#if GNUC_PREREQ (4, 9, 0)
1263# pragma GCC diagnostic ignored "-Wclobbered"
1264#endif
1265
1266/* Assert that E is true, but do not evaluate E. Use this instead of 1251/* Assert that E is true, but do not evaluate E. Use this instead of
1267 eassert (E) when E contains variables that might be clobbered by a 1252 eassert (E) when E contains variables that might be clobbered by a
1268 longjmp. */ 1253 longjmp. */
@@ -1488,8 +1473,10 @@ Lisp_Object
1488internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, 1473internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1489 Lisp_Object handlers) 1474 Lisp_Object handlers)
1490{ 1475{
1491 struct handler *oldhandlerlist = handlerlist; 1476 struct handler *volatile oldhandlerlist = handlerlist;
1492 ptrdiff_t CACHEABLE clausenb = 0; 1477
1478 /* The number of non-success handlers, plus 1 for a sentinel. */
1479 ptrdiff_t clausenb = 1;
1493 1480
1494 var = maybe_remove_pos_from_symbol (var); 1481 var = maybe_remove_pos_from_symbol (var);
1495 CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var); 1482 CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var);
@@ -1521,69 +1508,67 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1521 memory_full (SIZE_MAX); 1508 memory_full (SIZE_MAX);
1522 Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses); 1509 Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses);
1523 clauses += clausenb; 1510 clauses += clausenb;
1511 *--clauses = make_fixnum (0);
1524 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail)) 1512 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
1525 { 1513 {
1526 Lisp_Object tem = XCAR (tail); 1514 Lisp_Object tem = XCAR (tail);
1527 if (!(CONSP (tem) && EQ (XCAR (tem), QCsuccess))) 1515 if (!(CONSP (tem) && EQ (XCAR (tem), QCsuccess)))
1528 *--clauses = tem; 1516 *--clauses = tem;
1529 } 1517 }
1530 for (ptrdiff_t i = 0; i < clausenb; i++) 1518 Lisp_Object volatile var_volatile = var;
1519 Lisp_Object val, handler_body;
1520 for (Lisp_Object volatile *pcl = clauses; ; pcl++)
1531 { 1521 {
1532 Lisp_Object clause = clauses[i]; 1522 if (BASE_EQ (*pcl, make_fixnum (0)))
1523 {
1524 val = eval_sub (bodyform);
1525 handlerlist = oldhandlerlist;
1526 if (NILP (success_handler))
1527 return val;
1528#if GCC_LINT && __GNUC__ && !__clang__
1529 /* This useless assignment pacifies GCC 14.2.1 x86-64
1530 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161>. */
1531 var = var_volatile;
1532#endif
1533 handler_body = XCDR (success_handler);
1534 break;
1535 }
1536 Lisp_Object clause = *pcl;
1533 Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil; 1537 Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil;
1534 if (!CONSP (condition)) 1538 if (!CONSP (condition))
1535 condition = list1 (condition); 1539 condition = list1 (condition);
1536 struct handler *c = push_handler (condition, CONDITION_CASE); 1540 struct handler *c = push_handler (condition, CONDITION_CASE);
1541 Lisp_Object volatile *clauses_volatile = clauses;
1537 if (sys_setjmp (c->jmp)) 1542 if (sys_setjmp (c->jmp))
1538 { 1543 {
1539 Lisp_Object val = handlerlist->val; 1544 var = var_volatile;
1540 Lisp_Object volatile *chosen_clause = clauses; 1545 val = handlerlist->val;
1541 for (struct handler *h = handlerlist->next; h != oldhandlerlist; 1546 Lisp_Object volatile *chosen_clause = clauses_volatile;
1542 h = h->next) 1547 struct handler *oldh = oldhandlerlist;
1548 for (struct handler *h = handlerlist->next; h != oldh; h = h->next)
1543 chosen_clause++; 1549 chosen_clause++;
1544 Lisp_Object handler_body = XCDR (*chosen_clause); 1550 handler_body = XCDR (*chosen_clause);
1545 handlerlist = oldhandlerlist; 1551 handlerlist = oldh;
1546
1547 if (NILP (var))
1548 return Fprogn (handler_body);
1549 1552
1550 Lisp_Object handler_var = var; 1553 /* Whoever longjumped to us unwound the stack to C->pdlcount before
1551 if (!NILP (Vinternal_interpreter_environment)) 1554 throwing, so the unbind_to will undo just this binding. */
1552 { 1555 break;
1553 val = Fcons (Fcons (var, val),
1554 Vinternal_interpreter_environment);
1555 handler_var = Qinternal_interpreter_environment;
1556 }
1557
1558 /* Bind HANDLER_VAR to VAL while evaluating HANDLER_BODY.
1559 The unbind_to undoes just this binding; whoever longjumped
1560 to us unwound the stack to C->pdlcount before throwing. */
1561 specpdl_ref count = SPECPDL_INDEX ();
1562 specbind (handler_var, val);
1563 return unbind_to (count, Fprogn (handler_body));
1564 } 1556 }
1565 } 1557 }
1566 1558
1567 Lisp_Object CACHEABLE result = eval_sub (bodyform); 1559 if (NILP (var))
1568 handlerlist = oldhandlerlist; 1560 return Fprogn (handler_body);
1569 if (!NILP (success_handler))
1570 {
1571 if (NILP (var))
1572 return Fprogn (XCDR (success_handler));
1573 1561
1574 Lisp_Object handler_var = var; 1562 if (!NILP (Vinternal_interpreter_environment))
1575 if (!NILP (Vinternal_interpreter_environment)) 1563 {
1576 { 1564 val = Fcons (Fcons (var, val),
1577 result = Fcons (Fcons (var, result), 1565 Vinternal_interpreter_environment);
1578 Vinternal_interpreter_environment); 1566 var = Qinternal_interpreter_environment;
1579 handler_var = Qinternal_interpreter_environment;
1580 }
1581
1582 specpdl_ref count = SPECPDL_INDEX ();
1583 specbind (handler_var, result);
1584 return unbind_to (count, Fprogn (XCDR (success_handler)));
1585 } 1567 }
1586 return result; 1568
1569 specpdl_ref count = SPECPDL_INDEX ();
1570 specbind (var, val);
1571 return unbind_to (count, Fprogn (handler_body));
1587} 1572}
1588 1573
1589/* Call the function BFUN with no arguments, catching errors within it 1574/* 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)
1740struct handler * 1725struct handler *
1741push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) 1726push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype)
1742{ 1727{
1743 struct handler *CACHEABLE c = handlerlist->nextfree; 1728 struct handler *c = handlerlist->nextfree;
1744 if (!c) 1729 if (!c)
1745 { 1730 {
1746 c = malloc (sizeof *c); 1731 c = malloc (sizeof *c);