diff options
author | Alan Mackenzie <acm@muc.de> | 2015-11-26 10:36:32 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2015-11-26 10:36:32 +0000 |
commit | 5d93a89e805baa2f29941fd801e48235f6c1a6b6 (patch) | |
tree | d8bb921b2d2a9185aab21ae0165518fd9f8f378c | |
parent | 768b6f67746d2ba8407eb264c4b2d5c8ca011f58 (diff) | |
download | emacs-5d93a89e805baa2f29941fd801e48235f6c1a6b6.tar.gz |
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.
-rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 32 | ||||
-rw-r--r-- | lisp/emacs-lisp/cconv.el | 43 |
2 files changed, 40 insertions, 35 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 58cce67598c..ffe73defcbb 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -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) diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 4a3c273bc84..355913acbed 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -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 |