Byte compiler: on setq with an odd number of arguments, generate a `signal'
* lisp/emacs-lisp/cconv.el (cconv-convert): Don't transform `setq' form when it has an odd number of arguments, to allow bytecomp to handle the error. * lisp/emacs-lisp/bytecomp.el (byte-compile-setq): In a `setq' form with an odd number of arguments, generate a `signal' instead of the normal code.
This commit is contained in:
parent
768b6f6774
commit
5d93a89e80
2 changed files with 40 additions and 35 deletions
|
@ -3741,20 +3741,24 @@ discarding."
|
|||
(byte-defop-compiler-1 quote)
|
||||
|
||||
(defun byte-compile-setq (form)
|
||||
(let ((args (cdr form)))
|
||||
(if args
|
||||
(while args
|
||||
(if (eq (length args) 1)
|
||||
(byte-compile-log-warning
|
||||
(format "missing value for `%S' at end of setq" (car args))
|
||||
nil :error))
|
||||
(byte-compile-form (car (cdr args)))
|
||||
(or byte-compile--for-effect (cdr (cdr args))
|
||||
(byte-compile-out 'byte-dup 0))
|
||||
(byte-compile-variable-set (car args))
|
||||
(setq args (cdr (cdr args))))
|
||||
;; (setq), with no arguments.
|
||||
(byte-compile-form nil byte-compile--for-effect))
|
||||
(let* ((args (cdr form))
|
||||
(len (length args)))
|
||||
(if (= (logand len 1) 1)
|
||||
(progn
|
||||
(byte-compile-log-warning
|
||||
(format "missing value for `%S' at end of setq" (car (last args)))
|
||||
nil :error)
|
||||
(byte-compile-form
|
||||
`(signal 'wrong-number-of-arguments '(setq ,len))))
|
||||
(if args
|
||||
(while args
|
||||
(byte-compile-form (car (cdr args)))
|
||||
(or byte-compile--for-effect (cdr (cdr args))
|
||||
(byte-compile-out 'byte-dup 0))
|
||||
(byte-compile-variable-set (car args))
|
||||
(setq args (cdr (cdr args))))
|
||||
;; (setq), with no arguments.
|
||||
(byte-compile-form nil byte-compile--for-effect)))
|
||||
(setq byte-compile--for-effect nil)))
|
||||
|
||||
(defun byte-compile-setq-default (form)
|
||||
|
|
|
@ -473,27 +473,28 @@ places where they originally did not directly appear."
|
|||
:fun-body ,(cconv--convert-function () body env form)))
|
||||
|
||||
(`(setq . ,forms) ; setq special form
|
||||
(let ((prognlist ()))
|
||||
(while forms
|
||||
(let* ((sym (pop forms))
|
||||
(sym-new (or (cdr (assq sym env)) sym))
|
||||
(value-in-list
|
||||
(and forms
|
||||
(list (cconv-convert (pop forms) env extend)))))
|
||||
(push (pcase sym-new
|
||||
((pred symbolp) `(setq ,sym-new ,@value-in-list))
|
||||
(`(car-safe ,iexp) `(setcar ,iexp ,@value-in-list))
|
||||
;; This "should never happen", but for variables which are
|
||||
;; mutated+captured+unused, we may end up trying to `setq'
|
||||
;; on a closed-over variable, so just drop the setq.
|
||||
(_ ;; (byte-compile-report-error
|
||||
;; (format "Internal error in cconv of (setq %s ..)"
|
||||
;; sym-new))
|
||||
(car value-in-list)))
|
||||
prognlist)))
|
||||
(if (cdr prognlist)
|
||||
`(progn . ,(nreverse prognlist))
|
||||
(car prognlist))))
|
||||
(if (= (logand (length forms) 1) 1)
|
||||
;; With an odd number of args, let bytecomp.el handle the error.
|
||||
form
|
||||
(let ((prognlist ()))
|
||||
(while forms
|
||||
(let* ((sym (pop forms))
|
||||
(sym-new (or (cdr (assq sym env)) sym))
|
||||
(value (cconv-convert (pop forms) env extend)))
|
||||
(push (pcase sym-new
|
||||
((pred symbolp) `(setq ,sym-new ,value))
|
||||
(`(car-safe ,iexp) `(setcar ,iexp ,value))
|
||||
;; This "should never happen", but for variables which are
|
||||
;; mutated+captured+unused, we may end up trying to `setq'
|
||||
;; on a closed-over variable, so just drop the setq.
|
||||
(_ ;; (byte-compile-report-error
|
||||
;; (format "Internal error in cconv of (setq %s ..)"
|
||||
;; sym-new))
|
||||
value))
|
||||
prognlist)))
|
||||
(if (cdr prognlist)
|
||||
`(progn . ,(nreverse prognlist))
|
||||
(car prognlist)))))
|
||||
|
||||
(`(,(and (or `funcall `apply) callsym) ,fun . ,args)
|
||||
;; These are not special forms but we treat them separately for the needs
|
||||
|
|
Loading…
Add table
Reference in a new issue