From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Glenn Morris Newsgroups: gmane.emacs.devel Subject: Re: suppressing byte-compiler warnings about undefined functions Date: Sat, 10 Nov 2007 20:11:10 -0500 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1194743487 31452 80.91.229.12 (11 Nov 2007 01:11:27 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sun, 11 Nov 2007 01:11:27 +0000 (UTC) Cc: Stefan Monnier , emacs-devel@gnu.org To: rms@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Nov 11 02:11:30 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1Ir1MH-00037p-9k for ged-emacs-devel@m.gmane.org; Sun, 11 Nov 2007 02:11:29 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ir1M5-0003xG-Be for ged-emacs-devel@m.gmane.org; Sat, 10 Nov 2007 20:11:17 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Ir1M1-0003vR-7q for emacs-devel@gnu.org; Sat, 10 Nov 2007 20:11:13 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Ir1M0-0003uj-Q7 for emacs-devel@gnu.org; Sat, 10 Nov 2007 20:11:12 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ir1M0-0003uU-Dy for emacs-devel@gnu.org; Sat, 10 Nov 2007 20:11:12 -0500 Original-Received: from fencepost.gnu.org ([140.186.70.10]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Ir1M0-0002T9-AU for emacs-devel@gnu.org; Sat, 10 Nov 2007 20:11:12 -0500 Original-Received: from rgm by fencepost.gnu.org with local (Exim 4.60) (envelope-from ) id 1Ir1Ly-0007dD-At; Sat, 10 Nov 2007 20:11:10 -0500 X-Spook: cypherpunk keyhole Blowfish quarter Mole argus Fortezza X-Ran: *Tv>4nG^q8`N%4DwELzq25H>evVW5vf(Fz+P]~\y2!hvrEJU4Lsf3'=%0Wkibyq}"EH X-Hue: magenta X-Attribution: GM In-Reply-To: (Richard Stallman's message of "Sat, 10 Nov 2007 12:54:54 -0500") User-Agent: Gnus (www.gnus.org), GNU Emacs (www.gnu.org/software/emacs/) X-detected-kernel: by monty-python.gnu.org: Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:82925 Archived-At: Richard Stallman wrote: > It is probably nontrivial to arrange to find all the > `declare-function' calls in Emacs and check them. I doubt it > requires deep thought, but it should to be implemented before we > install this. See below: `check-declared-functions'. I haven't bothered to make it efficient/elegant (see how long it takes when all the necessary declare statements are added...). I'm thinking it could go in admin/admin.el (it uses process-lines from there). > Why clear byte-compile-declared-functions at the end of compilation? I'm using the existing variable `byte-compile-function-environment' now. This also allows for the optional argument checking Stefan asked for. *** byte-run.el 26 Jul 2007 05:26:44 -0000 1.22 --- byte-run.el 11 Nov 2007 00:35:08 -0000 *************** *** 103,108 **** --- 103,126 ---- (eval-and-compile (put ',name 'byte-optimizer 'byte-compile-inline-expand)))) + (defun declare-function (fn file &optional arglist) + "Tell the byte-compiler that function FN is defined, in FILE. + Optional ARGLIST is the argument list used by the function. The + FILE argument is not used by the byte-compiler, but by the + function `check-declared-functions', which checks that FILE + contains a definition for FN. FILE should be either absolute, or + relative to the location of the file containing the declaration. + ARGLIST is used by both the byte-compiler and + `check-declared-functions' to check for consistency. + + Note that for the purposes of `check-declared-functions', this + statement must be the first non-whitespace on a line, and + everything up to the end of FILE must be all on the same line. + For example: + + \(declare-function 'c-end-of-defun \"progmodes/cc-cmds.el\" '(&optional arg))" + nil) + (defun make-obsolete (obsolete-name current-name &optional when) "Make the byte-compiler warn that OBSOLETE-NAME is obsolete. The warning will say that CURRENT-NAME should be used instead. *** bytecomp.el 10 Nov 2007 08:05:15 -0000 2.217 --- bytecomp.el 11 Nov 2007 00:35:23 -0000 *************** *** 1258,1264 **** (byte-compile-fdefinition (car form) t))) (sig (if (and def (not (eq def t))) (byte-compile-arglist-signature ! (if (eq 'lambda (car-safe def)) (nth 1 def) (if (byte-code-function-p def) (aref def 0) --- 1258,1264 ---- (byte-compile-fdefinition (car form) t))) (sig (if (and def (not (eq def t))) (byte-compile-arglist-signature ! (if (memq (car-safe def) '(declared lambda)) (nth 1 def) (if (byte-code-function-p def) (aref def 0) *************** *** 2818,2823 **** --- 2818,2831 ---- (body (list body)))) + (put 'declare-function 'byte-hunk-handler 'byte-compile-declare-function) + (defun byte-compile-declare-function (form) + (push (cons (eval (nth 1 form)) + (list 'declared (eval (nth 3 form)))) + byte-compile-function-environment) + nil) + + ;; This is the recursive entry point for compiling each subform of an ;; expression. ;; If for-effect is non-nil, byte-compile-form will output a byte-discard ;; Adapted from authors.el. (defmacro checkdec-visit (file &rest body) "Execute the forms in BODY while visiting FILE. Re-uses an existing buffer visiting FILE if there is one. The value returned is the value of the last form in BODY." (declare (indent 1)) `(let ((existing-buffer (find-buffer-visiting ,file)) (enable-local-variables :safe) (enable-local-eval nil) (buffer (find-file-noselect ,file))) (prog1 (save-current-buffer (set-buffer buffer) (save-restriction (widen) (goto-char (point-min)) ,@body)) (unless existing-buffer (kill-buffer buffer))))) (defun checkdec-warn (file fn fnfile type) "Warn that FILE made a false claim about FN in FNFILE. TYPE is a string given the nature of the error." (display-warning 'checkdec (format "%s said `%s' was defined in %s: %s" (file-name-nondirectory file) fn (file-relative-name fnfile (file-name-directory file)) type) nil "*Check Declarations Warnings*")) (autoload 'byte-compile-arglist-signature "bytecomp.el") (defun checkdec-verify (file fn fnfile &optional arglist) "Check that FNFILE defines the function FN, as claimed in FILE. Optionally also check that the arglist matches ARGLIST. Returns non-nil if the claim was incorrect in some way." (unless (file-name-absolute-p fnfile) (setq fnfile (expand-file-name fnfile (file-name-directory file)))) (let (type defarglist) (if (file-exists-p fnfile) (checkdec-visit fnfile (if (re-search-forward (format "^(def\\(un\\|subst\\|macro\\)[ \t]+%s\\>" fn) nil t) (when arglist (skip-chars-forward " \t") (if (eolp) (forward-line 1)) (skip-chars-forward " \t") (if (looking-at "(") (setq defarglist (read (current-buffer)))) (or (equal (byte-compile-arglist-signature defarglist) (byte-compile-arglist-signature arglist)) (setq type "arglist mismatch"))) (setq type "function not found"))) (setq type "file not found")) (if type (checkdec-warn file fn fnfile type)))) (defun checkdec-scan (file) "Scan FILE for `declare-function' calls and check them. Returns non-nil if any checks fail." (let ((m (format "Checking %s..." file)) alist anyf e) (message "%s" m) (checkdec-visit file (while (re-search-forward "^[ \t]*(declare-function[ \t]+'\\(\\S-+\\)[ \t]+\ \"\\(\\S-+\\)\"" nil t) (setq e (list (match-string-no-properties 1) (match-string-no-properties 2))) (skip-chars-forward " \t") (if (eolp) (forward-line 1)) (skip-chars-forward " \t'") (if (looking-at "(") (setq e (append e (list (read (current-buffer)))))) (setq alist (cons e alist)))) (dolist (e alist) (setq anyf (or anyf (checkdec-verify file (car e) (nth 1 e) (nth 2 e))))) (message "%sdone" m) anyf)) (defun check-declared-functions (root) "Check veracity of all `declare-function' statements under directory ROOT. Returns non-nil if any false statements are found. For this to work correctly, the statements must adhere to the format described in the documentation of `declare-function'." (interactive "DEmacs lisp directory: ") (setq root (expand-file-name root)) (unless (file-exists-p (expand-file-name "emacs-lisp/bytecomp.el" root)) (error "Not the root lisp directory of Emacs: %s" root)) (let ((m "Checking `declare-function' statements...") anyf) (message "%s" m) (dolist (file (process-lines "find" root "-name" "*.el" "-exec" "grep" "-l" "^(declare-function" "{}" ";")) (setq anyf (or anyf (checkdec-scan file)))) (message "%s%s" m (if anyf "problems found" "OK")) anyf))