summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp')
-rw-r--r--lisp/emacs-lisp/byte-opt.el15
-rw-r--r--lisp/emacs-lisp/byte-run.el3
-rw-r--r--lisp/emacs-lisp/bytecomp.el77
-rw-r--r--lisp/emacs-lisp/cl-macs.el3
-rw-r--r--lisp/emacs-lisp/easy-mmode.el7
-rw-r--r--lisp/emacs-lisp/gv.el6
-rw-r--r--lisp/emacs-lisp/macroexp.el2
-rw-r--r--lisp/emacs-lisp/package.el1
8 files changed, 98 insertions, 16 deletions
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index a7e1df3622d..ab35b0dde8f 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -410,7 +410,10 @@ for speeding up processing.")
(`(condition-case ,var ,exp . ,clauses)
`(,fn ,var ;Not evaluated.
- ,(byte-optimize-form exp for-effect)
+ ,(byte-optimize-form exp
+ (if (assq :success clauses)
+ (null var)
+ for-effect))
,@(mapcar (lambda (clause)
(let ((byte-optimize--lexvars
(and lexical-binding
@@ -755,7 +758,8 @@ for speeding up processing.")
((eq head 'list) (cdr form))
((memq head
;; FIXME: Replace this list with a function property?
- '( length safe-length cons lambda
+ '( lambda internal-make-closure
+ length safe-length cons
string unibyte-string make-string concat
format format-message
substring substring-no-properties string-replace
@@ -1297,11 +1301,8 @@ See Info node `(elisp) Integer Basics'."
(if else
`(progn ,condition ,@else)
condition))
- ;; (if X nil t) -> (not X)
- ((and (eq then nil) (eq else '(t)))
- `(not ,condition))
- ;; (if X t [nil]) -> (not (not X))
- ((and (eq then t) (or (null else) (eq else '(nil))))
+ ;; (if X t) -> (not (not X))
+ ((and (eq then t) (null else))
`(not ,(byte-opt--negate condition)))
;; (if VAR VAR X...) -> (or VAR (progn X...))
((and (symbolp condition) (eq condition then))
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 1babf3ec2c4..b5e887db836 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -653,7 +653,8 @@ types. The types that can be suppressed with this macro are
`suspicious'.
For the `mapcar' case, only the `mapcar' function can be used in
-the symbol list. For `suspicious', only `set-buffer' and `lsh' can be used."
+the symbol list. For `suspicious', only `set-buffer', `lsh' and `eq'
+can be used."
;; Note: during compilation, this definition is overridden by the one in
;; byte-compile-initial-macro-environment.
(declare (debug (sexp body)) (indent 1))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index f176e769bf5..7571b4d409a 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -5487,6 +5487,83 @@ and corresponding effects."
(eval form)
form)))
+;; Check for (in)comparable constant values in calls to `eq', `memq' etc.
+
+(defun bytecomp--dodgy-eq-arg-p (x number-ok)
+ "Whether X is a bad argument to `eq' (or `eql' if NUMBER-OK is non-nil)."
+ (pcase x
+ ((or `(quote ,(pred consp)) `(function (lambda . ,_))) t)
+ ((or (pred consp) (pred symbolp)) nil)
+ ((pred integerp)
+ (not (or (<= -536870912 x 536870911) number-ok)))
+ ((pred floatp) (not number-ok))
+ (_ t)))
+
+(defun bytecomp--value-type-description (x)
+ (cond
+ ((proper-list-p x) "list")
+ ((recordp x) "record")
+ (t (symbol-name (type-of x)))))
+
+(defun bytecomp--arg-type-description (x)
+ (pcase x
+ (`(function (lambda . ,_)) "function")
+ (`(quote . ,val) (bytecomp--value-type-description val))
+ (_ (bytecomp--value-type-description x))))
+
+(defun bytecomp--warn-dodgy-eq-arg (form type parenthesis)
+ (macroexp-warn-and-return
+ (format "`%s' called with literal %s that may never match (%s)"
+ (car form) type parenthesis)
+ form '(suspicious eq) t))
+
+(defun bytecomp--check-eq-args (form &optional a b &rest _ignore)
+ (let* ((number-ok (eq (car form) 'eql))
+ (bad-arg (cond ((bytecomp--dodgy-eq-arg-p a number-ok) 1)
+ ((bytecomp--dodgy-eq-arg-p b number-ok) 2))))
+ (if bad-arg
+ (bytecomp--warn-dodgy-eq-arg
+ form
+ (bytecomp--arg-type-description (nth bad-arg form))
+ (format "arg %d" bad-arg))
+ form)))
+
+(put 'eq 'compiler-macro #'bytecomp--check-eq-args)
+(put 'eql 'compiler-macro #'bytecomp--check-eq-args)
+
+(defun bytecomp--check-memq-args (form &optional elem list &rest _ignore)
+ (let* ((fn (car form))
+ (number-ok (eq fn 'memql)))
+ (cond
+ ((bytecomp--dodgy-eq-arg-p elem number-ok)
+ (bytecomp--warn-dodgy-eq-arg
+ form (bytecomp--arg-type-description elem) "arg 1"))
+ ((and (consp list) (eq (car list) 'quote)
+ (proper-list-p (cadr list)))
+ (named-let loop ((elts (cadr list)) (i 1))
+ (if elts
+ (let* ((elt (car elts))
+ (x (cond ((eq fn 'assq) (car-safe elt))
+ ((eq fn 'rassq) (cdr-safe elt))
+ (t elt))))
+ (if (or (symbolp x)
+ (and (integerp x)
+ (or (<= -536870912 x 536870911) number-ok))
+ (and (floatp x) number-ok))
+ (loop (cdr elts) (1+ i))
+ (bytecomp--warn-dodgy-eq-arg
+ form (bytecomp--value-type-description x)
+ (format "element %d of arg 2" i))))
+ form)))
+ (t form))))
+
+(put 'memq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'memql 'compiler-macro #'bytecomp--check-memq-args)
+(put 'assq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'rassq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'remq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'delq 'compiler-macro #'bytecomp--check-memq-args)
+
(provide 'byte-compile)
(provide 'bytecomp)
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 43a2ed92059..95e78ceab6a 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2052,7 +2052,8 @@ info node `(cl) Function Bindings' for details.
(dolist (binding bindings)
(let ((var (make-symbol (format "--cl-%s--" (car binding))))
(args-and-body (cdr binding)))
- (if (and (= (length args-and-body) 1) (symbolp (car args-and-body)))
+ (if (and (= (length args-and-body) 1)
+ (macroexp-copyable-p (car args-and-body)))
;; Optimize (cl-flet ((fun var)) body).
(setq var (car args-and-body))
(push (list var (if (= (length args-and-body) 1)
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 2df390ecbeb..7d54a84687b 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -417,6 +417,8 @@ No problems result if this variable is not bound.
`(defvar ,keymap-sym
(let ((m ,keymap))
(cond ((keymapp m) m)
+ ;; FIXME: `easy-mmode-define-keymap' is obsolete,
+ ;; so this form should also be obsolete somehow.
((listp m)
(with-suppressed-warnings ((obsolete
easy-mmode-define-keymap))
@@ -682,6 +684,7 @@ Valid keywords and arguments are:
:group Ignored.
:suppress Non-nil to call `suppress-keymap' on keymap,
`nodigits' to suppress digits as prefix arguments."
+ (declare (obsolete define-keymap "29.1"))
(let (inherit dense suppress)
(while args
(let ((key (pop args))
@@ -722,9 +725,7 @@ The M, BS, and ARGS arguments are as per that function. DOC is
the constant's documentation.
This macro is deprecated; use `defvar-keymap' instead."
- ;; FIXME: Declare obsolete in favor of `defvar-keymap'. It is still
- ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first.
- (declare (doc-string 3) (indent 1))
+ (declare (doc-string 3) (indent 1) (obsolete defvar-keymap "29.1"))
`(defconst ,m
(easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
,doc))
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 11251d7a963..48bc0269f36 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -417,9 +417,9 @@ The return value is the last VAL in the list.
(lambda (do key alist &optional default remove testfn)
(macroexp-let2 macroexp-copyable-p k key
(gv-letplace (getter setter) alist
- (macroexp-let2 nil p `(if (and ,testfn (not (eq ,testfn 'eq)))
- (assoc ,k ,getter ,testfn)
- (assq ,k ,getter))
+ (macroexp-let2 nil p (if (member testfn '(nil 'eq #'eq))
+ `(assq ,k ,getter)
+ `(assoc ,k ,getter ,testfn))
(funcall do (if (null default) `(cdr ,p)
`(if ,p (cdr ,p) ,default))
(lambda (v)
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index f4df40249de..8953e5fd019 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -486,7 +486,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
(setq form (macroexp--compiler-macro handler newform))
(if (eq newform form)
newform
- (macroexp--expand-all newform)))
+ (macroexp--expand-all form)))
(macroexp--expand-all newform))))))
(_ form))))
(pop byte-compile-form-stack)))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 73c4f896a49..1ab70eb2fe9 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -4562,6 +4562,7 @@ will be signaled in that case."
(package--print-email-button maint)
(string-trim (substring-no-properties (buffer-string))))))))
+;;;###autoload
(defun package-report-bug (desc)
"Prepare a message to send to the maintainers of a package.
DESC must be a `package-desc' object."