From 3810901175523c6a15b83b33e2718443bb886d9f Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Thu, 26 Sep 2024 14:03:42 +0200 Subject: [PATCH] Warn about unreachable code * lisp/emacs-lisp/byte-opt.el (byte-opt--every) (byte-opt--return-p): New functions. (byte-optimize-body): Emit warning for unreachable code. --- lisp/emacs-lisp/byte-opt.el | 40 ++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index d8dbfa62bf9..dc97080fbc2 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -674,6 +674,42 @@ There can be multiple entries for the same NAME if it has several aliases.") (car form)) (byte-optimize-body (cdr form) for-effect))))) +(defun byte-opt--every (pred seq) + "Check whether PRED holds for every element of SEQ." + (while (and seq (funcall pred (car seq))) + (setq seq (cdr seq))) + (null seq)) + +(defun byte-opt--return-p (form) + "Check whether evaluating FORM may return. +If this function returns nil, then FORM never returns." + (unless (memq (car-safe form) '(throw signal error user-error)) + (pcase form + (`(,(or 'let 'let*) ,bindings . ,body) + (and (byte-opt--every (lambda (binding) + (byte-opt--return-p + (if (cdr binding) (cadr binding) (car binding)))) + bindings) + (byte-opt--every #'byte-opt--return-p body))) + (`(,(or 'progn 'prog1 'save-excursion 'save-restriction 'save-current-buffer) . ,exps) + (byte-opt--every #'byte-opt--return-p exps)) + (`(if ,test ,then . ,else) + (and (byte-opt--return-p test) + (or (byte-opt--return-p then) + (byte-opt--every #'byte-opt--return-p else)))) + (`(,(or 'and 'or) . ,exps) + (not (byte-opt--every (lambda (exp) (not (byte-opt--return-p exp))) exps))) + (`(while ,exp . ,exps) + (and (not (byte-compile-trueconstp exp)) + (byte-opt--every #'byte-opt--return-p exps))) + ;; (`(cond . ,clauses) ...) + ;; (`(condition-case ,var ,exp . ,clauses) ...) + ;; (`(unwind-protect ,protected-expr :fun-body ,unwind-fun) ...) + ;; (`(catch ,tag . ,exps) ...) + ;; (`(internal-make-closure ,vars ,env . ,rest) ...) + ;; (`(setq ,var ,expr . ,more) ...) + ;; (`(defvar ,var . ,rest) ...) + (_ t)))) (defun byte-optimize-body (forms all-for-effect) ;; Optimize the cdr of a progn or implicit progn; all forms is a list of @@ -692,7 +728,9 @@ There can be multiple entries for the same NAME if it has several aliases.") (setq new (pop result))) (when (or new (not fe)) (setq result (cons new result))) - (setq rest (cdr rest))) + (setq rest (cdr rest)) + (when (and rest (not (byte-opt--return-p new))) + (byte-compile-warn-x rest "Unreachable code"))) (nreverse result))) -- 2.39.5