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:
Alan Mackenzie 2015-11-26 10:36:32 +00:00
parent 768b6f6774
commit 5d93a89e80
2 changed files with 40 additions and 35 deletions

View file

@ -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)

View file

@ -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