Allow compilation during loading of Modes derived from a CC Mode mode.
Fixes debbugs#19206. cc-bytecomp.el (cc-bytecomp-compiling-or-loading): new function which walks the stack to discover whether we're compiling or loading. (cc-bytecomp-is-compiling): Reformulate, and move towards beginning. (cc-bytecomp-is-loading): New defsubst. (cc-bytecomp-setup-environment, cc-bytecomp-restore-environment): Use the above defsubsts. (cc-require-when-compile, cc-bytecomp-defvar) (cc-bytecomp-defun): Simplify conditionals. cc-defs.el (cc-bytecomp-compiling-or-loading): "Borrow" this function from cc-bytecomp.el. (c-get-current-file): Reformulate using the above. (c-lang-defconst): Prevent duplicate entries of file names in a symbol's 'source property. (c-lang-const): Use cc-bytecomp-is-compiling. cc-langs.el (c-make-init-lang-vars-fun): Use cc-bytecomp-is-compiling.
This commit is contained in:
parent
c302473913
commit
30c5f5cdef
4 changed files with 108 additions and 38 deletions
|
@ -1,3 +1,29 @@
|
|||
2015-01-13 Alan Mackenzie <acm@muc.de>
|
||||
|
||||
Allow compilation during loading of Modes derived from a CC Mode mode.
|
||||
Fixes debbugs#19206.
|
||||
|
||||
* progmodes/cc-bytecomp.el (cc-bytecomp-compiling-or-loading): new
|
||||
function which walks the stack to discover whether we're compiling
|
||||
or loading.
|
||||
(cc-bytecomp-is-compiling): Reformulate, and move towards
|
||||
beginning.
|
||||
(cc-bytecomp-is-loading): New defsubst.
|
||||
(cc-bytecomp-setup-environment, cc-bytecomp-restore-environment):
|
||||
Use the above defsubsts.
|
||||
(cc-require-when-compile, cc-bytecomp-defvar)
|
||||
(cc-bytecomp-defun): Simplify conditionals.
|
||||
|
||||
* progmodes/cc-defs.el (cc-bytecomp-compiling-or-loading):
|
||||
"Borrow" this function from cc-bytecomp.el.
|
||||
(c-get-current-file): Reformulate using the above.
|
||||
(c-lang-defconst): Prevent duplicate entries of file names in a
|
||||
symbol's 'source property.
|
||||
(c-lang-const): Use cc-bytecomp-is-compiling.
|
||||
|
||||
* progmodes/cc-langs.el (c-make-init-lang-vars-fun): Use
|
||||
cc-bytecomp-is-compiling.
|
||||
|
||||
2015-01-13 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/eieio-core.el (eieio-defclass): Fix call to `defclass'
|
||||
|
|
|
@ -89,13 +89,60 @@
|
|||
;;`(message ,@args)
|
||||
)
|
||||
|
||||
(defun cc-bytecomp-compiling-or-loading ()
|
||||
;; Determine whether byte-compilation or loading is currently active,
|
||||
;; returning 'compiling, '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 require
|
||||
byte-compile-file byte-recompile-directory
|
||||
batch-byte-compile)))))
|
||||
(setq n (1+ n)))
|
||||
(cond
|
||||
((memq (cadr elt) '(load require))
|
||||
'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 - \
|
||||
|
@ -143,7 +190,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
|
||||
|
@ -287,8 +334,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)))
|
||||
(if (not (featurep ,cc-part))
|
||||
(cc-bytecomp-load (symbol-name ,cc-part)))
|
||||
(require ,cc-part))))
|
||||
|
||||
|
@ -301,12 +347,6 @@ afterwards. Don't use within `eval-when-compile'."
|
|||
(require ,feature)
|
||||
(eval-when-compile (cc-bytecomp-setup-environment))))
|
||||
|
||||
(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'."
|
||||
|
@ -320,8 +360,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:"
|
||||
|
@ -349,8 +388,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))))
|
||||
|
|
|
@ -1983,19 +1983,22 @@ system."
|
|||
|
||||
(defvar c-lang-const-expansion nil)
|
||||
|
||||
;; 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)))))
|
||||
|
@ -2062,6 +2065,9 @@ constant. A file is identified by its base name."
|
|||
;; language constant source definitions.)
|
||||
(c-lang-const-expansion 'call)
|
||||
(c-langs-are-parametric t)
|
||||
(file (intern
|
||||
(or (c-get-current-file)
|
||||
(error "`c-lang-defconst' can only be used in a file"))))
|
||||
bindings
|
||||
pre-files)
|
||||
|
||||
|
@ -2121,9 +2127,14 @@ constant. A file is identified by its base name."
|
|||
;; definitions for this symbol, to make sure the order in the
|
||||
;; `source' property is correct even when files are loaded out of
|
||||
;; order.
|
||||
(setq pre-files (nreverse
|
||||
;; Reverse to get the right load order.
|
||||
(mapcar 'car (get sym 'source))))
|
||||
(setq pre-files (mapcar 'car (get sym 'source)))
|
||||
(if (memq file pre-files)
|
||||
;; This can happen when the source file (e.g. cc-langs.el) is first
|
||||
;; loaded as source, setting a 'source property entry, and then itself
|
||||
;; being compiled.
|
||||
(setq pre-files (cdr (memq file pre-files))))
|
||||
;; Reverse to get the right load order.
|
||||
(setq pre-files (nreverse pre-files))
|
||||
|
||||
`(eval-and-compile
|
||||
(c-define-lang-constant ',name ,bindings
|
||||
|
@ -2233,9 +2244,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
|
||||
|
|
|
@ -3260,10 +3260,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."
|
||||
|
||||
(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
|
||||
|
|
Loading…
Add table
Reference in a new issue