]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/bytecomp.el
Merge branch 'emacs-25-merge'
[gnu-emacs] / lisp / emacs-lisp / bytecomp.el
index 2bd8d07851b35d2aca1ad9bee26d9b5af443aa15..b5b618e87d7a74d2daf4a04ad40485f1f4721963 100644 (file)
 ;; faster.  [`LAP' == `Lisp Assembly Program'.]
 ;; The user entry points are byte-compile-file and byte-recompile-directory.
 
+;;; Todo:
+
+;; - Turn "not bound at runtime" functions into autoloads.
+
 ;;; Code:
 
 ;; ========================================================================
@@ -261,8 +265,8 @@ This option is enabled by default because it reduces Emacs memory usage."
 
 (defcustom byte-optimize-log nil
   "If non-nil, the byte-compiler will log its optimizations.
-If this is 'source, then only source-level optimizations will be logged.
-If it is 'byte, then only byte-level optimizations will be logged.
+If this is `source', then only source-level optimizations will be logged.
+If it is `byte', then only byte-level optimizations will be logged.
 The information is logged to `byte-compile-log-buffer'."
   :group 'bytecomp
   :type '(choice (const :tag "none" nil)
@@ -344,7 +348,7 @@ else the global value will be modified."
 ;;;###autoload
 (defun byte-compile-enable-warning (warning)
   "Change `byte-compile-warnings' to enable WARNING.
-If `byte-compile-warnings' is `t', do nothing.  Otherwise, if the
+If `byte-compile-warnings' is t, do nothing.  Otherwise, if the
 first element is `not', remove WARNING, else add it.
 Normally you should let-bind `byte-compile-warnings' before calling this,
 else the global value will be modified."
@@ -393,7 +397,7 @@ invoked interactively are excluded from this list."
   "Alist of functions and their call tree.
 Each element looks like
 
-  \(FUNCTION CALLERS CALLS\)
+  (FUNCTION CALLERS CALLS)
 
 where CALLERS is a list of functions that call FUNCTION, and CALLS
 is a list of functions for which calls were generated while compiling
@@ -450,16 +454,26 @@ Return the compile-time value of FORM."
     (eval-when-compile . ,(lambda (&rest body)
                             (let ((result nil))
                               (byte-compile-recurse-toplevel
-                               (cons 'progn body)
+                               (macroexp-progn body)
                                (lambda (form)
-                                 (setf result
-                                       (byte-compile-eval
-                                        (byte-compile-top-level
-                                         (byte-compile-preprocess form))))))
+                                 ;; Insulate the following variables
+                                 ;; against changes made in the
+                                 ;; subsidiary compilation.  This
+                                 ;; prevents spurious warning
+                                 ;; messages: "not defined at runtime"
+                                 ;; etc.
+                                 (let ((byte-compile-unresolved-functions
+                                        byte-compile-unresolved-functions)
+                                       (byte-compile-new-defuns
+                                        byte-compile-new-defuns))
+                                   (setf result
+                                         (byte-compile-eval
+                                          (byte-compile-top-level
+                                           (byte-compile-preprocess form)))))))
                               (list 'quote result))))
     (eval-and-compile . ,(lambda (&rest body)
                            (byte-compile-recurse-toplevel
-                            (cons 'progn body)
+                            (macroexp-progn body)
                             (lambda (form)
                               ;; Don't compile here, since we don't know
                               ;; whether to compile as byte-compile-form
@@ -499,6 +513,11 @@ defined with incorrect args.")
 Used for warnings about calling a function that is defined during compilation
 but won't necessarily be defined when the compiled file is loaded.")
 
+(defvar byte-compile-new-defuns nil
+  "List of (runtime) functions defined in this compilation run.
+This variable is used to qualify `byte-compile-noruntime-functions' when
+outputting warnings about functions not being defined at runtime.")
+
 ;; Variables for lexical binding
 (defvar byte-compile--lexical-environment nil
   "The current lexical environment.")
@@ -969,7 +988,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
          (print-level 4)
          (print-length 4))
       (byte-compile-log-1
-       (format
+       (format-message
        ,format-string
        ,@(mapcar
           (lambda (x) (if (symbolp x) (list 'prin1-to-string x) x))
@@ -1116,7 +1135,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
                pt)
           (when dir
             (unless was-same
-              (insert (format "Leaving directory `%s'\n" default-directory))))
+              (insert (format-message "Leaving directory `%s'\n"
+                                       default-directory))))
           (unless (bolp)
             (insert "\n"))
           (setq pt (point-marker))
@@ -1131,8 +1151,8 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
           (when dir
             (setq default-directory dir)
             (unless was-same
-              (insert (format "Entering directory `%s'\n"
-                               default-directory))))
+              (insert (format-message "Entering directory `%s'\n"
+                                       default-directory))))
           (setq byte-compile-last-logged-file byte-compile-current-file
                 byte-compile-last-warned-form nil)
           ;; Do this after setting default-directory.
@@ -1150,7 +1170,7 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'."
 
 (defun byte-compile-warn (format &rest args)
   "Issue a byte compiler warning; use (format FORMAT ARGS...) for message."
-  (setq format (apply 'format format args))
+  (setq format (apply #'format-message format args))
   (if byte-compile-error-on-warn
       (error "%s" format)              ; byte-compile-file catches and logs it
     (byte-compile-log-warning format t :warning)))
@@ -1349,13 +1369,13 @@ extra args."
     (let ((keyword-args (cdr (cdr (cdr (cdr form)))))
           (name (cadr form)))
       (or (not (eq (car-safe name) 'quote))
-        (and (eq (car form) 'custom-declare-group)
-             (equal name ''emacs))
-        (plist-get keyword-args :group)
-        (not (and (consp name) (eq (car name) 'quote)))
-        (byte-compile-warn
-         "%s for `%s' fails to specify containing group"
-         (cdr (assq (car form)
+          (and (eq (car form) 'custom-declare-group)
+               (equal name ''emacs))
+          (plist-get keyword-args :group)
+          (not (and (consp name) (eq (car name) 'quote)))
+          (byte-compile-warn
+           "%s for `%s' fails to specify containing group"
+           (cdr (assq (car form)
                       '((custom-declare-group . defgroup)
                         (custom-declare-face . defface)
                         (custom-declare-variable . defcustom))))
@@ -1413,7 +1433,7 @@ extra args."
                      (`(lambda ,args . ,_) args)
                      (`(closure ,_ ,args . ,_) args)
                      ((pred byte-code-function-p) (aref old 0))
-                     (t '(&rest def)))))
+                     (_ '(&rest def)))))
             (sig2 (byte-compile-arglist-signature arglist)))
         (unless (byte-compile-arglist-signatures-congruent-p sig1 sig2)
           (byte-compile-set-symbol-position name)
@@ -1458,7 +1478,7 @@ extra args."
                          ;; These would sometimes be warned about
                          ;; but such warnings are never useful,
                          ;; so don't warn about them.
-                         macroexpand cl-macroexpand-all
+                         macroexpand
                          cl--compiling-file))))
        (byte-compile-warn "function `%s' from cl package called at runtime"
                           func)))
@@ -1498,8 +1518,9 @@ extra args."
       ;; Separate the functions that will not be available at runtime
       ;; from the truly unresolved ones.
       (dolist (f byte-compile-unresolved-functions)
-       (setq f (car f))
-       (if (fboundp f) (push f noruntime) (push f unresolved)))
+        (setq f (car f))
+        (when (not (memq f byte-compile-new-defuns))
+          (if (fboundp f) (push f noruntime) (push f unresolved))))
       ;; Complain about the no-run-time functions
       (byte-compile-print-syms
        "the function `%s' might not be defined at runtime."
@@ -1686,7 +1707,7 @@ Any other non-nil value of ARG means to ask the user.
 If optional argument LOAD is non-nil, loads the file after compiling.
 
 If compilation is needed, this functions returns the result of
-`byte-compile-file'; otherwise it returns 'no-byte-compile."
+`byte-compile-file'; otherwise it returns `no-byte-compile'."
   (interactive
    (let ((file buffer-file-name)
         (file-name nil)
@@ -1795,7 +1816,7 @@ The value is non-nil if there were no errors, nil if errors."
             (progn
               (setq-default major-mode 'emacs-lisp-mode)
               ;; Arg of t means don't alter enable-local-variables.
-              (normal-mode t))
+              (delay-mode-hooks (normal-mode t)))
           (setq-default major-mode dmm))
         ;; There may be a file local variable setting (bug#10419).
         (setq buffer-read-only nil
@@ -1896,7 +1917,10 @@ With argument ARG, insert value in current buffer after the form."
                   (let ((read-with-symbol-positions (current-buffer))
                         (read-symbol-positions-list nil))
                     (displaying-byte-compile-warnings
-                     (byte-compile-sexp (read (current-buffer)))))
+                     (byte-compile-sexp
+                       (eval-sexp-add-defvars
+                        (read (current-buffer))
+                        byte-compile-read-position))))
                    lexical-binding)))
       (cond (arg
             (message "Compiling from buffer... done.")
@@ -1953,6 +1977,8 @@ With argument ARG, insert value in current buffer after the form."
        ;; compiled.  A: Yes!  b-c-u-f might contain dross from a
        ;; previous byte-compile.
        (setq byte-compile-unresolved-functions nil)
+        (setq byte-compile-noruntime-functions nil)
+        (setq byte-compile-new-defuns nil)
 
        ;; Compile the forms from the input buffer.
        (while (progn
@@ -2279,8 +2305,7 @@ list that represents a doc string reference.
      ;; byte-compile-warn-about-unresolved-functions.
      (if (memq funsym byte-compile-noruntime-functions)
          (setq byte-compile-noruntime-functions
-               (delq funsym byte-compile-noruntime-functions)
-               byte-compile-noruntime-functions)
+               (delq funsym byte-compile-noruntime-functions))
        (setq byte-compile-unresolved-functions
              (delq (assq funsym byte-compile-unresolved-functions)
                    byte-compile-unresolved-functions)))))
@@ -2319,10 +2344,12 @@ list that represents a doc string reference.
     form))
 
 (put 'define-abbrev-table 'byte-hunk-handler
-     'byte-compile-file-form-define-abbrev-table)
-(defun byte-compile-file-form-define-abbrev-table (form)
-  (if (eq 'quote (car-safe (car-safe (cdr form))))
-      (byte-compile--declare-var (car-safe (cdr (cadr form)))))
+     'byte-compile-file-form-defvar-function)
+(put 'defvaralias 'byte-hunk-handler 'byte-compile-file-form-defvar-function)
+
+(defun byte-compile-file-form-defvar-function (form)
+  (pcase-let (((or `',name (let name nil)) (nth 1 form)))
+    (if name (byte-compile--declare-var name)))
   (byte-compile-keep-pending form))
 
 (put 'custom-declare-variable 'byte-hunk-handler
@@ -2330,15 +2357,27 @@ list that represents a doc string reference.
 (defun byte-compile-file-form-custom-declare-variable (form)
   (when (byte-compile-warning-enabled-p 'callargs)
     (byte-compile-nogroup-warn form))
-  (byte-compile--declare-var (nth 1 (nth 1 form)))
-  (byte-compile-keep-pending form))
+  (byte-compile-file-form-defvar-function form))
 
 (put 'require 'byte-hunk-handler 'byte-compile-file-form-require)
 (defun byte-compile-file-form-require (form)
   (let ((args (mapcar 'eval (cdr form)))
        (hist-orig load-history)
-       hist-new)
+       hist-new prov-cons)
     (apply 'require args)
+
+    ;; Record the functions defined by the require in `byte-compile-new-defuns'.
+    (setq hist-new load-history)
+    (setq prov-cons (cons 'provide (car args)))
+    (while (and hist-new
+                (not (member prov-cons (car hist-new))))
+      (setq hist-new (cdr hist-new)))
+    (when hist-new
+      (dolist (x (car hist-new))
+        (when (and (consp x)
+                   (memq (car x) '(defun t)))
+          (push (cdr x) byte-compile-new-defuns))))
+
     (when (byte-compile-warning-enabled-p 'cl-functions)
       ;; Detect (require 'cl) in a way that works even if cl is already loaded.
       (if (member (car args) '("cl" cl))
@@ -2394,6 +2433,7 @@ not to take responsibility for the actual compilation of the code."
          (byte-compile-current-form name)) ; For warnings.
 
     (byte-compile-set-symbol-position name)
+    (push name byte-compile-new-defuns)
     ;; When a function or macro is defined, add it to the call tree so that
     ;; we can tell when functions are not used.
     (if byte-compile-generate-call-tree
@@ -2579,18 +2619,14 @@ If FORM is a lambda or a macro, byte-compile it as a function."
                  (if (symbolp form) form "provided"))
         fun)
        (t
-        (when (symbolp form)
-          (unless (memq (car-safe fun) '(closure lambda))
-            (error "Don't know how to compile %S" fun))
+        (when (or (symbolp form) (eq (car-safe fun) 'closure))
+          ;; `fun' is a function *value*, so try to recover its corresponding
+          ;; source code.
           (setq lexical-binding (eq (car fun) 'closure))
           (setq fun (byte-compile--reify-function fun)))
-        (unless (eq (car-safe fun) 'lambda)
-          (error "Don't know how to compile %S" fun))
         ;; Expand macros.
         (setq fun (byte-compile-preprocess fun))
-        ;; Get rid of the `function' quote added by the `lambda' macro.
-        (if (eq (car-safe fun) 'function) (setq fun (cadr fun)))
-        (setq fun (byte-compile-lambda fun))
+        (setq fun (byte-compile-top-level fun nil 'eval))
         (if macro (push 'macro fun))
         (if (symbolp form)
             (fset form fun)
@@ -2921,11 +2957,17 @@ for symbols generated by the byte compiler itself."
 
 ;; Special macro-expander used during byte-compilation.
 (defun byte-compile-macroexpand-declare-function (fn file &rest args)
-  (push (cons fn
-              (if (and (consp args) (listp (car args)))
-                  (list 'declared (car args))
-                t))                     ; Arglist not specified.
-        byte-compile-function-environment)
+  (let ((gotargs (and (consp args) (listp (car args))))
+       (unresolved (assq fn byte-compile-unresolved-functions)))
+    (when unresolved         ; function was called before declaration
+      (if (and gotargs (byte-compile-warning-enabled-p 'callargs))
+         (byte-compile-arglist-warn fn (car args) nil)
+       (setq byte-compile-unresolved-functions
+             (delq unresolved byte-compile-unresolved-functions))))
+    (push (cons fn (if gotargs
+                      (list 'declared (car args))
+                    t))                     ; Arglist not specified.
+         byte-compile-function-environment))
   ;; We are stating that it _will_ be defined at runtime.
   (setq byte-compile-noruntime-functions
         (delq fn byte-compile-noruntime-functions))
@@ -2966,6 +3008,16 @@ for symbols generated by the byte compiler itself."
             (interactive-only
              (or (get fn 'interactive-only)
                  (memq fn byte-compile-interactive-only-functions))))
+        (when (memq fn '(set symbol-value run-hooks ;; add-to-list
+                             add-hook remove-hook run-hook-with-args
+                             run-hook-with-args-until-success
+                             run-hook-with-args-until-failure))
+          (pcase (cdr form)
+            (`(',var . ,_)
+             (when (assq var byte-compile-lexical-variables)
+               (byte-compile-log-warning
+                (format-message "%s cannot use lexical var `%s'" fn var)
+                nil :error)))))
         (when (macroexp--const-symbol-p fn)
           (byte-compile-warn "`%s' called as a function" fn))
        (when (and (byte-compile-warning-enabled-p 'interactive-only)
@@ -2973,11 +3025,13 @@ for symbols generated by the byte compiler itself."
          (byte-compile-warn "`%s' is for interactive use only%s"
                             fn
                             (cond ((stringp interactive-only)
-                                   (format "; %s" interactive-only))
+                                   (format "; %s"
+                                           (substitute-command-keys
+                                            interactive-only)))
                                   ((and (symbolp 'interactive-only)
                                         (not (eq interactive-only t)))
-                                   (format "; use `%s' instead."
-                                           interactive-only))
+                                   (format-message "; use `%s' instead."
+                                                    interactive-only))
                                   (t "."))))
         (if (eq (car-safe (symbol-function (car form))) 'macro)
             (byte-compile-log-warning
@@ -3079,8 +3133,9 @@ for symbols generated by the byte compiler itself."
       (dotimes (_ (- (/ (1+ fmax2) 2) alen))
         (byte-compile-push-constant nil)))
      ((zerop (logand fmax2 1))
-      (byte-compile-log-warning "Too many arguments for inlined function"
-                                nil :error)
+      (byte-compile-log-warning
+       (format "Too many arguments for inlined function %S" form)
+       nil :error)
       (byte-compile-discard (- alen (/ fmax2 2))))
      (t
       ;; Turn &rest args into a list.
@@ -3108,7 +3163,7 @@ for symbols generated by the byte compiler itself."
   (cond ((or (not (symbolp var)) (macroexp--const-symbol-p var))
         (when (byte-compile-warning-enabled-p 'constants)
           (byte-compile-warn (if (eq access-type 'let-bind)
-                                 "attempt to let-bind %s `%s`"
+                                 "attempt to let-bind %s `%s'"
                                "variable reference to %s `%s'")
                              (if (symbolp var) "constant" "nonvariable")
                              (prin1-to-string var))))
@@ -3453,15 +3508,22 @@ discarding."
   (if byte-compile--for-effect (setq byte-compile--for-effect nil)
     (let* ((vars (nth 1 form))
            (env (nth 2 form))
-           (body (nthcdr 3 form))
+           (docstring-exp (nth 3 form))
+           (body (nthcdr 4 form))
            (fun
             (byte-compile-lambda `(lambda ,vars . ,body) nil (length env))))
-      (cl-assert (> (length env) 0))       ;Otherwise, we don't need a closure.
+      (cl-assert (or (> (length env) 0)
+                    docstring-exp))    ;Otherwise, we don't need a closure.
       (cl-assert (byte-code-function-p fun))
       (byte-compile-form `(make-byte-code
                            ',(aref fun 0) ',(aref fun 1)
                            (vconcat (vector . ,env) ',(aref fun 2))
-                           ,@(nthcdr 3 (mapcar (lambda (x) `',x) fun)))))))
+                           ,@(let ((rest (nthcdr 3 (mapcar (lambda (x) `',x) fun))))
+                               (if docstring-exp
+                                   `(,(car rest)
+                                     ,docstring-exp
+                                     ,@(cddr rest))
+                                 rest)))))))
 
 (defun byte-compile-get-closed-var (form)
   "Byte-compile the special `internal-get-closed-var' form."
@@ -3589,8 +3651,8 @@ discarding."
 
 (defun byte-compile-quo (form)
   (let ((len (length form)))
-    (cond ((<= len 2)
-          (byte-compile-subr-wrong-args form "2 or more"))
+    (cond ((< len 2)
+          (byte-compile-subr-wrong-args form "1 or more"))
          ((= len 3)
           (byte-compile-two-args form))
          (t
@@ -3679,16 +3741,25 @@ discarding."
 (byte-defop-compiler-1 quote)
 
 (defun byte-compile-setq (form)
-  (let ((args (cdr form)))
-    (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))
+  (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))
+           byte-compile--for-effect))
+      (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)
@@ -3801,11 +3872,11 @@ discarding."
   "Execute forms in BODY, potentially guarded by CONDITION.
 CONDITION is a variable whose value is a test in an `if' or `cond'.
 BODY is the code to compile in the first arm of the if or the body of
-the cond clause.  If CONDITION's value is of the form (fboundp 'foo)
-or (boundp 'foo), the relevant warnings from BODY about foo's
+the cond clause.  If CONDITION's value is of the form (fboundp \\='foo)
+or (boundp \\='foo), the relevant warnings from BODY about foo's
 being undefined (or obsolete) will be suppressed.
 
-If CONDITION's value is (not (featurep 'emacs)) or (featurep 'xemacs),
+If CONDITION's value is (not (featurep \\='emacs)) or (featurep \\='xemacs),
 that suppresses all warnings during execution of BODY."
   (declare (indent 1) (debug t))
   `(let* ((fbound-list (byte-compile-find-bound-condition
@@ -3942,8 +4013,13 @@ that suppresses all warnings during execution of BODY."
     (setq byte-compile--for-effect nil)))
 
 (defun byte-compile-funcall (form)
-  (mapc 'byte-compile-form (cdr form))
-  (byte-compile-out 'byte-call (length (cdr (cdr form)))))
+  (if (cdr form)
+      (progn
+        (mapc 'byte-compile-form (cdr form))
+        (byte-compile-out 'byte-call (length (cdr (cdr form)))))
+    (byte-compile-log-warning "`funcall' called with no arguments" nil :error)
+    (byte-compile-form '(signal 'wrong-number-of-arguments '(funcall 0))
+                       byte-compile--for-effect)))
 
 \f
 ;; let binding
@@ -4393,7 +4469,7 @@ binding slots have been popped."
       ;; which is to call back byte-compile-file-form and then return nil.
       ;; Except that we can't just call byte-compile-file-form since it would
       ;; call us right back.
-      (t (byte-compile-keep-pending form)))))
+      (_ (byte-compile-keep-pending form)))))
 
 (byte-defop-compiler-1 with-no-warnings byte-compile-no-warnings)
 (defun byte-compile-no-warnings (form)
@@ -4501,11 +4577,11 @@ whose definitions have been compiled in this Emacs session, as well as
 all functions called by those functions.
 
 The call graph does not include macros, inline functions, or
-primitives that the byte-code interpreter knows about directly \(eq,
-cons, etc.\).
+primitives that the byte-code interpreter knows about directly
+\(`eq', `cons', etc.).
 
 The call tree also lists those functions which are not known to be called
-\(that is, to which no calls have been compiled\), and which cannot be
+\(that is, to which no calls have been compiled), and which cannot be
 invoked interactively."
   (interactive)
   (message "Generating call tree...")