Commit 30c5f5cd authored by Alan Mackenzie's avatar Alan Mackenzie

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.
parent c3024739
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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment