X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/83b0af6e4fbf4407f0de26cf00b5823d79d58e91..5dd1c041c7fdb876b52bf33f41e8aeb119282cef:/lisp/emacs-lisp/bytecomp.el diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 21d7cd001c..02a88c1397 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1,7 +1,7 @@ ;;; bytecomp.el --- compilation of Lisp code into byte code ;; Copyright (C) 1985, 1986, 1987, 1992, 1994, 1998, 2000, 2001, 2002, -;; 2003, 2004, 2005 Free Software Foundation, Inc. +;; 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Author: Jamie Zawinski ;; Hallvard Furuseth @@ -293,6 +293,7 @@ For example, add -*-byte-compile-dynamic: t;-*- on the first line. When this option is true, if you load the compiled file and then move it, the functions you loaded will not be able to run.") +;;;###autoload(put 'byte-compile-dynamic 'safe-local-variable 'booleanp) (defcustom byte-compile-dynamic-docstrings t "*If non-nil, compile doc strings for lazy access. @@ -311,6 +312,7 @@ You can also set the variable globally. This option is enabled by default because it reduces Emacs memory usage." :group 'bytecomp :type 'boolean) +;;;###autoload(put 'byte-compile-dynamic-docstrings 'safe-local-variable 'booleanp) (defcustom byte-optimize-log nil "*If true, the byte-compiler will log its optimizations into *Compile-Log*. @@ -355,10 +357,24 @@ Elements of the list may be be: (const callargs) (const redefine) (const obsolete) (const noruntime) (const cl-functions) (const interactive-only)))) +(put 'byte-compile-warnings 'safe-local-variable 'byte-compile-warnings-safe-p) +;;;###autoload +(defun byte-compile-warnings-safe-p (x) + (or (booleanp x) + (and (listp x) + (equal (mapcar + (lambda (e) + (when (memq e '(free-vars unresolved + callargs redefine + obsolete noruntime + cl-functions interactive-only)) + e)) + x) + x)))) (defvar byte-compile-interactive-only-functions '(beginning-of-buffer end-of-buffer replace-string replace-regexp - insert-file) + insert-file insert-buffer insert-file-literally) "List of commands that are not meant to be called from Lisp.") (defvar byte-compile-not-obsolete-var nil @@ -908,6 +924,13 @@ Each function's symbol gets added to `byte-compile-noruntime-functions'." ;; list. If our current position is after the symbol's position, we ;; assume we've already passed that point, and look for the next ;; occurrence of the symbol. +;; +;; This function should not be called twice for the same occurrence of +;; a symbol, and it should not be called for symbols generated by the +;; byte compiler itself; because rather than just fail looking up the +;; symbol, we may find an occurrence of the symbol further ahead, and +;; then `byte-compile-last-position' as advanced too far. +;; ;; So your're probably asking yourself: Isn't this function a ;; gross hack? And the answer, of course, would be yes. (defun byte-compile-set-symbol-position (sym &optional allow-previous) @@ -1582,6 +1605,7 @@ recompile every `.el' file that already has a `.elc' file." This is normally set in local file variables at the end of the elisp file: ;; Local Variables:\n;; no-byte-compile: t\n;; End: ") +;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp) ;;;###autoload (defun byte-compile-file (filename &optional load) @@ -1643,8 +1667,12 @@ The value is non-nil if there were no errors, nil if errors." ;; If they change the file name, then change it for the output also. (let ((buffer-file-name filename) (default-major-mode 'emacs-lisp-mode) + ;; Ignore unsafe local variables. + ;; We only care about a few of them for our purposes. + (enable-local-variables :safe) (enable-local-eval nil)) - (normal-mode) + ;; Arg of t means don't alter enable-local-variables. + (normal-mode t) (setq filename buffer-file-name)) ;; Set the default directory, in case an eval-when-compile uses it. (setq default-directory (file-name-directory filename))) @@ -2304,7 +2332,7 @@ list that represents a doc string reference. ',name ',declaration)) outbuffer))))) - (let* ((new-one (byte-compile-lambda (cons 'lambda (nthcdr 2 form)))) + (let* ((new-one (byte-compile-lambda (nthcdr 2 form) t)) (code (byte-compile-byte-code-maker new-one))) (if this-one (setcdr this-one new-one) @@ -2500,10 +2528,16 @@ If FORM is a lambda or a macro, byte-compile it as a function." ;; Byte-compile a lambda-expression and return a valid function. ;; The value is usually a compiled function but may be the original ;; lambda-expression. -(defun byte-compile-lambda (fun) - (unless (eq 'lambda (car-safe fun)) - (error "Not a lambda list: %S" fun)) - (byte-compile-set-symbol-position 'lambda) +;; When ADD-LAMBDA is non-nil, the symbol `lambda' is added as head +;; of the list FUN and `byte-compile-set-symbol-position' is not called. +;; Use this feature to avoid calling `byte-compile-set-symbol-position' +;; for symbols generated by the byte compiler itself. +(defun byte-compile-lambda (fun &optional add-lambda) + (if add-lambda + (setq fun (cons 'lambda fun)) + (unless (eq 'lambda (car-safe fun)) + (error "Not a lambda list: %S" fun)) + (byte-compile-set-symbol-position 'lambda)) (byte-compile-check-lambda-list (nth 1 fun)) (let* ((arglist (nth 1 fun)) (byte-compile-bound-variables @@ -2752,12 +2786,16 @@ If FORM is a lambda or a macro, byte-compile it as a function." (byte-compile-warn "`%s' used from Lisp code\n\ That command is designed for interactive use only" fn)) (if (and handler - (or (not (byte-compile-version-cond - byte-compile-compatibility)) - (not (get (get fn 'byte-opcode) 'emacs19-opcode)))) - (progn - (byte-compile-set-symbol-position fn) - (funcall handler form)) + ;; Make sure that function exists. This is important + ;; for CL compiler macros since the symbol may be + ;; `cl-byte-compile-compiler-macro' but if CL isn't + ;; loaded, this function doesn't exist. + (or (not (memq handler '(cl-byte-compile-compiler-macro))) + (functionp handler)) + (not (and (byte-compile-version-cond + byte-compile-compatibility) + (get (get fn 'byte-opcode) 'emacs19-opcode)))) + (funcall handler form) (when (memq 'callargs byte-compile-warnings) (if (memq fn '(custom-declare-group custom-declare-variable custom-declare-face)) (byte-compile-nogroup-warn form)) @@ -3353,12 +3391,12 @@ That command is designed for interactive use only" fn)) "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 first arm of the if or the body of the -cond clause. If CONDITION's value is of the form `(foundp 'foo)' -or `(boundp 'foo)', the relevant warnings from BODY about foo +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 will be suppressed. -If CONDITION's value is `(featurep 'xemacs)', that suppresses all -warnings during execution of BODY." +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 (if (eq 'fboundp (car-safe ,condition)) @@ -3409,7 +3447,8 @@ warnings during execution of BODY." (byte-compile-form (nth 2 form) for-effect)) (byte-compile-goto 'byte-goto donetag) (byte-compile-out-tag elsetag) - (byte-compile-body (cdr (cdr (cdr form))) for-effect) + (byte-compile-maybe-guarded (list 'not clause) + (byte-compile-body (cdr (cdr (cdr form))) for-effect)) (byte-compile-out-tag donetag)))) (setq for-effect nil)) @@ -3670,7 +3709,7 @@ warnings during execution of BODY." (list 'fset (list 'quote (nth 1 form)) (byte-compile-byte-code-maker - (byte-compile-lambda (cons 'lambda (cdr (cdr form))))))) + (byte-compile-lambda (cdr (cdr form)) t)))) (byte-compile-discard)) ;; We prefer to generate a defalias form so it will record the function ;; definition just like interpreting a defun. @@ -3678,7 +3717,7 @@ warnings during execution of BODY." (list 'defalias (list 'quote (nth 1 form)) (byte-compile-byte-code-maker - (byte-compile-lambda (cons 'lambda (cdr (cdr form)))))) + (byte-compile-lambda (cdr (cdr form)) t))) t)) (byte-compile-constant (nth 1 form))) @@ -3687,8 +3726,7 @@ warnings during execution of BODY." (byte-compile-body-do-effect (list (list 'fset (list 'quote (nth 1 form)) (let ((code (byte-compile-byte-code-maker - (byte-compile-lambda - (cons 'lambda (cdr (cdr form))))))) + (byte-compile-lambda (cdr (cdr form)) t)))) (if (eq (car-safe code) 'make-byte-code) (list 'cons ''macro code) (list 'quote (cons 'macro (eval code)))))) @@ -3774,7 +3812,15 @@ warnings during execution of BODY." (push (cons (nth 1 (nth 1 form)) (if constant (nth 1 (nth 2 form)) t)) byte-compile-function-environment))) - (byte-compile-normal-call form)) + ;; We used to jus do: (byte-compile-normal-call form) + ;; But it turns out that this fails to optimize the code. + ;; So instead we now do the same as what other byte-hunk-handlers do, + ;; 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. + (byte-compile-keep-pending form) + ;; Return nil so the form is not output twice. + nil) ;; Turn off warnings about prior calls to the function being defalias'd. ;; This could be smarter and compare those calls with @@ -3789,6 +3835,19 @@ warnings during execution of BODY." (defun byte-compile-no-warnings (form) (let (byte-compile-warnings) (byte-compile-form (cons 'progn (cdr form))))) + +;; Warn about misuses of make-variable-buffer-local. +(byte-defop-compiler-1 make-variable-buffer-local byte-compile-make-variable-buffer-local) +(defun byte-compile-make-variable-buffer-local (form) + (if (eq (car-safe (car-safe (cdr-safe form))) 'quote) + (byte-compile-warn + "`make-variable-buffer-local' should be called at toplevel")) + (byte-compile-normal-call form)) +(put 'make-variable-buffer-local + 'byte-hunk-handler 'byte-compile-form-make-variable-buffer-local) +(defun byte-compile-form-make-variable-buffer-local (form) + (byte-compile-keep-pending form 'byte-compile-normal-call)) + ;;; tags @@ -4069,7 +4128,11 @@ already up-to-date." (defun batch-byte-recompile-directory (&optional arg) "Run `byte-recompile-directory' on the dirs remaining on the command line. Must be used only with `-batch', and kills Emacs on completion. -For example, invoke `emacs -batch -f batch-byte-recompile-directory .'." +For example, invoke `emacs -batch -f batch-byte-recompile-directory .'. + +Optional argument ARG is passed as second argument ARG to +`batch-recompile-directory'; see there for its possible values +and corresponding effects." ;; command-line-args-left is what is left of the command line (startup.el) (defvar command-line-args-left) ;Avoid 'free variable' warning (if (not noninteractive)