(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)
"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
(byte-compile-recurse-toplevel
(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
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.")
(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))
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))
(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.
(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)))
(`(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)
;; 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."
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)
(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.")
;; 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
;; 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)))))
(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))
(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
(if (symbolp form) form "provided"))
fun)
(t
- (when (symbolp form)
+ (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)))
;; Expand macros.
(`(',var . ,_)
(when (assq var byte-compile-lexical-variables)
(byte-compile-log-warning
- (format "%s cannot use lexical var `%s'" fn var)
+ (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))
(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
(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))))
(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
(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)
"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
(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
;; 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)
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...")