From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Sebastian Wiesner Newsgroups: gmane.emacs.bugs Subject: bug#19206: 25.0.50; CC Mode tracks wrong source files Date: Tue, 2 Dec 2014 12:03:21 +0100 Message-ID: <9C8C5538-BC19-4094-832C-3F3259DE37A5@lunaryorn.com> References: <20141128222542.60510.qmail@mail.muc.de> <20141130184221.GA12974@acm.acm> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 (Mac OS X Mail 8.1 \(1993\)) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1417519202 28354 80.91.229.3 (2 Dec 2014 11:20:02 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 2 Dec 2014 11:20:02 +0000 (UTC) Cc: 19206@debbugs.gnu.org To: Alan Mackenzie Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Tue Dec 02 12:19:57 2014 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XvlUo-0004xt-Lw for geb-bug-gnu-emacs@m.gmane.org; Tue, 02 Dec 2014 12:19:54 +0100 Original-Received: from localhost ([::1]:36177 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XvlUn-0005kD-NW for geb-bug-gnu-emacs@m.gmane.org; Tue, 02 Dec 2014 06:19:53 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:41296) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XvlUf-0005e3-IF for bug-gnu-emacs@gnu.org; Tue, 02 Dec 2014 06:19:49 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XvlUb-0007gh-5X for bug-gnu-emacs@gnu.org; Tue, 02 Dec 2014 06:19:45 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:54233) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XvlFS-0002l1-Bm; Tue, 02 Dec 2014 06:04:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1XvlFS-00031L-1t; Tue, 02 Dec 2014 06:04:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Sebastian Wiesner Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org, bug-cc-mode@gnu.org Resent-Date: Tue, 02 Dec 2014 11:04:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 19206 X-GNU-PR-Package: emacs,cc-mode X-GNU-PR-Keywords: Original-Received: via spool by 19206-submit@debbugs.gnu.org id=B19206.141751820911565 (code B ref 19206); Tue, 02 Dec 2014 11:04:01 +0000 Original-Received: (at 19206) by debbugs.gnu.org; 2 Dec 2014 11:03:29 +0000 Original-Received: from localhost ([127.0.0.1]:51446 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XvlEu-00030S-8K for submit@debbugs.gnu.org; Tue, 02 Dec 2014 06:03:29 -0500 Original-Received: from vega.uberspace.de ([95.143.172.245]:41713) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XvlEr-00030I-4r for 19206@debbugs.gnu.org; Tue, 02 Dec 2014 06:03:26 -0500 Original-Received: (qmail 21172 invoked from network); 2 Dec 2014 11:03:23 -0000 Original-Received: from localhost (HELO lunaryorn-air.fritz.box) (127.0.0.1) by vega.uberspace.de with SMTP; 2 Dec 2014 11:03:23 -0000 In-Reply-To: <20141130184221.GA12974@acm.acm> X-Mailer: Apple Mail (2.1993) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:96795 Archived-At: > Am 30.11.2014 um 19:42 schrieb Alan Mackenzie : >=20 > Hello, again, Sebastian. >=20 > On Fri, Nov 28, 2014 at 10:25:42PM -0000, Alan Mackenzie wrote: >> Hello, Sebastian. >> In article you = wrote: >>> CC Mode tracks wrong source files when a CC Mode derived mode is >>> installed non-interactively. >=20 >>> To reproduce, save the following code as `cc-miscompile.el' >=20 >>> (require 'package) >>> (require 'cc-defs) >=20 >>> (defun main () >>> (add-to-list 'package-archives '("melpa" . = "http://melpa.org/packages/")) >=20 >>> (setq package-user-dir (make-temp-file "cc-miscompile" 'directory)) >=20 >>> (package-initialize) >>> (package-refresh-contents) >>> (package-install 'd-mode) >=20 >>> (require 'd-mode) >=20 >>> (let ((source (get (intern "c-typedef-decl-kwds" c-lang-constants) = 'source))) >>> (message "Sources: %S" (mapcar 'car source))) >=20 >>> (delete-directory package-user-dir 'recursive)) >=20 >>> (main) >=20 >>> and run it with `emacs -Q --script cc-miscompile.el'. The output is = as >>> follows (package.el output shortened for readility): >=20 >>> Contacting host: melpa.org:80 >>> Contacting host: elpa.gnu.org:80 >>> [?] >>> Sources: (d-mode cc-miscompile cc-langs) >=20 >>> Note that `cc-miscompile' ends up in the source list of >>> `c-typedef-decl-kwds', even though it never actually calls any `c-*' >>> functions at all. >=20 > OK. The problem was that CC Mode was using the flag = `load-in-progress' > to assume that a CC Mode file was being loaded, for example by a > `require' form inside a compilation of another CC Mode file. This > assumption breaks down when another file, such as cc-miscompile.el, > while loading, initiates compilation of a CC Mode derivative. >=20 >> The byte compilation of d-mode.el is being done during the loading of >> cc-miscompile.el. This somewhat unusual constellation, I think, is >> causing the problem. When CC Mode determines the file name to put = onto >> a c-lang-defconst's 'source property, it gives priority to the load = file >> name, and only when this is nil does it use the byte-compile file = name. >> (This is in defsubst c-get-current-file in cc-defs.el). It would = seem >> this is not the correct priority. >=20 >> I think swapping the first two arms of the `cond' form in >> c-get-current-file may solve the problem. It's a bit late to try = this >> tonight, I'll try it tomorrow. >=20 > No, that wouldn't work. What I've implemented is when both loading = and > byte-compilation are active at the same time, CC Mode walks down the > lisp stack to discover which one of them is actually active. Well, if you say=E2=80=A6 I find this =E2=80=9Csolution=E2=80=9D = horrifying, but I am probably just unable to appreciate the full = complexity of this issue. >>> Naturally, CC Mode will later try to load this file, and fail if it = is >>> not in the `load-path'. This effectively breaks installations of D >>> Mode from non-interactive Emacs sessions. >=20 > Please try the following patch, which seems to work in the test case = you > supplied, in the real situation, and let me know how well it works. = The > d-mode.elc produced can be successfully loaded into the Emacs that = built > it. Do I need to build a patched Emacs to try it? > diff --git a/lisp/progmodes/cc-bytecomp.el = b/lisp/progmodes/cc-bytecomp.el > index 1936627..bd2fd34 100644 > --- a/lisp/progmodes/cc-bytecomp.el > +++ b/lisp/progmodes/cc-bytecomp.el > @@ -84,13 +84,60 @@ > ;;`(message ,@args) > ) >=20 > +(defun cc-bytecomp-compiling-or-loading () > + ;; Return whether byte-compilation or loading is currently active, > + ;; returning 'compiling or 'loading or nil. > + ;; If both are active, the "innermost" activity counts. Note that > + ;; compilation can trigger loading (various `require' type forms) > + ;; and loading can trigger compilation (the package manager does > + ;; this). We walk the lisp stack if necessary. > + (cond > + ((and load-in-progress > + (boundp 'byte-compile-dest-file) > + (stringp byte-compile-dest-file)) > + (let ((n 0) elt) > + (while (and > + (setq elt (backtrace-frame n)) > + (not (and (car elt) > + (memq (cadr elt) > + '(load byte-compile-file > + byte-recompile-directory > + batch-byte-compile))))) > + (setq n (1+ n))) > + (cond > + ((eq (cadr elt) 'load) > + 'loading) > + ((memq (cadr elt) '(byte-compile-file > + byte-recompile-directory > + batch-byte-compile)) > + 'compiling) > + (t ; Can't happen. > + (message "cc-bytecomp-compiling-or-loading: System flags = spuriously set") > + nil)))) > + (load-in-progress > + ;; Being loaded. > + 'loading) > + ((and (boundp 'byte-compile-dest-file) > + (stringp byte-compile-dest-file)) > + ;; Being compiled. > + 'compiling) > + (t > + ;; Being evaluated interactively. > + nil))) > + > +(defsubst cc-bytecomp-is-compiling () > + "Return non-nil if eval'ed during compilation." > + (eq (cc-bytecomp-compiling-or-loading) 'compiling)) > + > +(defsubst cc-bytecomp-is-loading () > + "Return non-nil if eval'ed during loading. > +Nil will be returned if we're in a compilation triggered by the = loading." > + (eq (cc-bytecomp-compiling-or-loading) 'loading)) > + > (defun cc-bytecomp-setup-environment () > ;; Eval'ed during compilation to setup variables, functions etc > ;; declared with `cc-bytecomp-defvar' et al. > - (if (not load-in-progress) > - ;; Look at `load-in-progress' to tell whether we're called > - ;; directly in the file being compiled or just from some file > - ;; being loaded during compilation. > + (if (not (cc-bytecomp-is-loading)) > (let (p) > (if cc-bytecomp-environment-set > (error "Byte compilation environment already set - \ > @@ -138,7 +185,7 @@ perhaps a `cc-bytecomp-restore-environment' is = forgotten somewhere")) > (defun cc-bytecomp-restore-environment () > ;; Eval'ed during compilation to restore variables, functions etc > ;; declared with `cc-bytecomp-defvar' et al. > - (if (not load-in-progress) > + (if (not (cc-bytecomp-is-loading)) > (let (p) > (setq p cc-bytecomp-unbound-variables) > (while p > @@ -282,9 +329,7 @@ use within `eval-when-compile'." > `(eval-when-compile > (if (and (fboundp 'cc-bytecomp-is-compiling) > (cc-bytecomp-is-compiling)) > - (if (or (not load-in-progress) > - (not (featurep ,cc-part))) > - (cc-bytecomp-load (symbol-name ,cc-part))) > + (cc-bytecomp-load (symbol-name ,cc-part)) > (require ,cc-part)))) >=20 > (defmacro cc-external-require (feature) > @@ -296,12 +341,6 @@ afterwards. Don't use within = `eval-when-compile'." > (require ,feature) > (eval-when-compile (cc-bytecomp-setup-environment)))) >=20 > -(defun cc-bytecomp-is-compiling () > - "Return non-nil if eval'ed during compilation. Don't use outside > -`eval-when-compile'." > - (and (boundp 'byte-compile-dest-file) > - (stringp byte-compile-dest-file))) > - > (defmacro cc-bytecomp-defvar (var) > "Binds the symbol as a variable during compilation of the file, > to silence the byte compiler. Don't use within `eval-when-compile'." > @@ -315,8 +354,7 @@ to silence the byte compiler. Don't use within = `eval-when-compile'." > "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) > (setq cc-bytecomp-unbound-variables > (cons ',var cc-bytecomp-unbound-variables)))) > - (if (and (cc-bytecomp-is-compiling) > - (not load-in-progress)) > + (if (cc-bytecomp-is-compiling) > (progn > (defvar ,var) > (set ',var (intern (concat "cc-bytecomp-ignore-var:" > @@ -344,8 +382,7 @@ at compile time, e.g. for macros and inline = functions." > (setq cc-bytecomp-original-functions > (cons (list ',fun nil 'unbound) > cc-bytecomp-original-functions)))) > - (if (and (cc-bytecomp-is-compiling) > - (not load-in-progress)) > + (if (cc-bytecomp-is-compiling) > (progn > (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" > (symbol-name ',fun)))) > diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el > index 1d8b8ab..b0e83f3 100644 > --- a/lisp/progmodes/cc-defs.el > +++ b/lisp/progmodes/cc-defs.el > @@ -1823,19 +1823,22 @@ system." >=20 > (defvar c-lang-const-expansion nil) >=20 > +;; Ugly hack to pull in the definition of = `cc-bytecomp-compiling-or-loading` > +;; from cc-bytecomp to make it available at loadtime. This is the = same > +;; mechanism used in cc-mode.el for `c-populate-syntax-table'. > +(defalias 'cc-bytecomp-compiling-or-loading > + (cc-eval-when-compile > + (let ((f (symbol-function 'cc-bytecomp-compiling-or-loading))) > + (if (byte-code-function-p f) f (byte-compile f))))) > + > (defsubst c-get-current-file () > ;; Return the base name of the current file. > - (let ((file (cond > - (load-in-progress > - ;; Being loaded. > - load-file-name) > - ((and (boundp 'byte-compile-dest-file) > - (stringp byte-compile-dest-file)) > - ;; Being compiled. > - byte-compile-dest-file) > - (t > - ;; Being evaluated interactively. > - (buffer-file-name))))) > + (let* ((c-or-l (cc-bytecomp-compiling-or-loading)) > + (file > + (cond > + ((eq c-or-l 'loading) load-file-name) > + ((eq c-or-l 'compiling) byte-compile-dest-file) > + ((null c-or-l) (buffer-file-name))))) > (and file > (file-name-sans-extension > (file-name-nondirectory file))))) > @@ -2073,9 +2076,7 @@ quoted." > (if (or (eq c-lang-const-expansion 'call) > (and (not c-lang-const-expansion) > (not mode)) > - load-in-progress > - (not (boundp 'byte-compile-dest-file)) > - (not (stringp byte-compile-dest-file))) > + (not (cc-bytecomp-is-compiling))) > ;; Either a straight call is requested in the context, or > ;; we're in an "uncontrolled" context and got no language, > ;; or we're not being byte compiled so the compile time > diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el > index 68b2d62..22d78b5 100644 > --- a/lisp/progmodes/cc-langs.el > +++ b/lisp/progmodes/cc-langs.el > @@ -3252,10 +3252,7 @@ function it returns is byte compiled with all = the evaluated results > from the language constants. Use the `c-init-language-vars' macro to > accomplish that conveniently." >=20 > - (if (and (not load-in-progress) > - (boundp 'byte-compile-dest-file) > - (stringp byte-compile-dest-file)) > - > + (if (cc-bytecomp-is-compiling) > ;; No need to byte compile this lambda since the byte compiler = is > ;; smart enough to detect the `funcall' construct in the > ;; `c-init-language-vars' macro below and compile it all = straight >=20 >=20 >=20 > --=20 > Alan Mackenzie (Nuremberg, Germany).