diff options
| author | Alan Mackenzie | 2015-01-13 15:39:36 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2015-01-13 15:47:26 +0000 |
| commit | 30c5f5cdef8db72c007efecfc8436479631b45d0 (patch) | |
| tree | 781d6e630b7efca6e0fef929a416bb79851949f5 | |
| parent | c3024739131467b607fa745daf52ca25a3fd3c4d (diff) | |
| download | emacs-30c5f5cdef8db72c007efecfc8436479631b45d0.tar.gz emacs-30c5f5cdef8db72c007efecfc8436479631b45d0.zip | |
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.
| -rw-r--r-- | lisp/ChangeLog | 26 | ||||
| -rw-r--r-- | lisp/progmodes/cc-bytecomp.el | 72 | ||||
| -rw-r--r-- | lisp/progmodes/cc-defs.el | 43 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 5 |
4 files changed, 108 insertions, 38 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 532a10a1b71..072af5b1b91 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,29 @@ | |||
| 1 | 2015-01-13 Alan Mackenzie <acm@muc.de> | ||
| 2 | |||
| 3 | Allow compilation during loading of Modes derived from a CC Mode mode. | ||
| 4 | Fixes debbugs#19206. | ||
| 5 | |||
| 6 | * progmodes/cc-bytecomp.el (cc-bytecomp-compiling-or-loading): new | ||
| 7 | function which walks the stack to discover whether we're compiling | ||
| 8 | or loading. | ||
| 9 | (cc-bytecomp-is-compiling): Reformulate, and move towards | ||
| 10 | beginning. | ||
| 11 | (cc-bytecomp-is-loading): New defsubst. | ||
| 12 | (cc-bytecomp-setup-environment, cc-bytecomp-restore-environment): | ||
| 13 | Use the above defsubsts. | ||
| 14 | (cc-require-when-compile, cc-bytecomp-defvar) | ||
| 15 | (cc-bytecomp-defun): Simplify conditionals. | ||
| 16 | |||
| 17 | * progmodes/cc-defs.el (cc-bytecomp-compiling-or-loading): | ||
| 18 | "Borrow" this function from cc-bytecomp.el. | ||
| 19 | (c-get-current-file): Reformulate using the above. | ||
| 20 | (c-lang-defconst): Prevent duplicate entries of file names in a | ||
| 21 | symbol's 'source property. | ||
| 22 | (c-lang-const): Use cc-bytecomp-is-compiling. | ||
| 23 | |||
| 24 | * progmodes/cc-langs.el (c-make-init-lang-vars-fun): Use | ||
| 25 | cc-bytecomp-is-compiling. | ||
| 26 | |||
| 1 | 2015-01-13 Stefan Monnier <monnier@iro.umontreal.ca> | 27 | 2015-01-13 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 28 | ||
| 3 | * emacs-lisp/eieio-core.el (eieio-defclass): Fix call to `defclass' | 29 | * emacs-lisp/eieio-core.el (eieio-defclass): Fix call to `defclass' |
diff --git a/lisp/progmodes/cc-bytecomp.el b/lisp/progmodes/cc-bytecomp.el index bf7803c85ca..b63eeb4c7a6 100644 --- a/lisp/progmodes/cc-bytecomp.el +++ b/lisp/progmodes/cc-bytecomp.el | |||
| @@ -89,13 +89,60 @@ | |||
| 89 | ;;`(message ,@args) | 89 | ;;`(message ,@args) |
| 90 | ) | 90 | ) |
| 91 | 91 | ||
| 92 | (defun cc-bytecomp-compiling-or-loading () | ||
| 93 | ;; Determine whether byte-compilation or loading is currently active, | ||
| 94 | ;; returning 'compiling, 'loading or nil. | ||
| 95 | ;; If both are active, the "innermost" activity counts. Note that | ||
| 96 | ;; compilation can trigger loading (various `require' type forms) | ||
| 97 | ;; and loading can trigger compilation (the package manager does | ||
| 98 | ;; this). We walk the lisp stack if necessary. | ||
| 99 | (cond | ||
| 100 | ((and load-in-progress | ||
| 101 | (boundp 'byte-compile-dest-file) | ||
| 102 | (stringp byte-compile-dest-file)) | ||
| 103 | (let ((n 0) elt) | ||
| 104 | (while (and | ||
| 105 | (setq elt (backtrace-frame n)) | ||
| 106 | (not (and (car elt) | ||
| 107 | (memq (cadr elt) | ||
| 108 | '(load require | ||
| 109 | byte-compile-file byte-recompile-directory | ||
| 110 | batch-byte-compile))))) | ||
| 111 | (setq n (1+ n))) | ||
| 112 | (cond | ||
| 113 | ((memq (cadr elt) '(load require)) | ||
| 114 | 'loading) | ||
| 115 | ((memq (cadr elt) '(byte-compile-file | ||
| 116 | byte-recompile-directory | ||
| 117 | batch-byte-compile)) | ||
| 118 | 'compiling) | ||
| 119 | (t ; Can't happen. | ||
| 120 | (message "cc-bytecomp-compiling-or-loading: System flags spuriously set") | ||
| 121 | nil)))) | ||
| 122 | (load-in-progress | ||
| 123 | ;; Being loaded. | ||
| 124 | 'loading) | ||
| 125 | ((and (boundp 'byte-compile-dest-file) | ||
| 126 | (stringp byte-compile-dest-file)) | ||
| 127 | ;; Being compiled. | ||
| 128 | 'compiling) | ||
| 129 | (t | ||
| 130 | ;; Being evaluated interactively. | ||
| 131 | nil))) | ||
| 132 | |||
| 133 | (defsubst cc-bytecomp-is-compiling () | ||
| 134 | "Return non-nil if eval'ed during compilation." | ||
| 135 | (eq (cc-bytecomp-compiling-or-loading) 'compiling)) | ||
| 136 | |||
| 137 | (defsubst cc-bytecomp-is-loading () | ||
| 138 | "Return non-nil if eval'ed during loading. | ||
| 139 | Nil will be returned if we're in a compilation triggered by the loading." | ||
| 140 | (eq (cc-bytecomp-compiling-or-loading) 'loading)) | ||
| 141 | |||
| 92 | (defun cc-bytecomp-setup-environment () | 142 | (defun cc-bytecomp-setup-environment () |
| 93 | ;; Eval'ed during compilation to setup variables, functions etc | 143 | ;; Eval'ed during compilation to setup variables, functions etc |
| 94 | ;; declared with `cc-bytecomp-defvar' et al. | 144 | ;; declared with `cc-bytecomp-defvar' et al. |
| 95 | (if (not load-in-progress) | 145 | (if (not (cc-bytecomp-is-loading)) |
| 96 | ;; Look at `load-in-progress' to tell whether we're called | ||
| 97 | ;; directly in the file being compiled or just from some file | ||
| 98 | ;; being loaded during compilation. | ||
| 99 | (let (p) | 146 | (let (p) |
| 100 | (if cc-bytecomp-environment-set | 147 | (if cc-bytecomp-environment-set |
| 101 | (error "Byte compilation environment already set - \ | 148 | (error "Byte compilation environment already set - \ |
| @@ -143,7 +190,7 @@ perhaps a `cc-bytecomp-restore-environment' is forgotten somewhere")) | |||
| 143 | (defun cc-bytecomp-restore-environment () | 190 | (defun cc-bytecomp-restore-environment () |
| 144 | ;; Eval'ed during compilation to restore variables, functions etc | 191 | ;; Eval'ed during compilation to restore variables, functions etc |
| 145 | ;; declared with `cc-bytecomp-defvar' et al. | 192 | ;; declared with `cc-bytecomp-defvar' et al. |
| 146 | (if (not load-in-progress) | 193 | (if (not (cc-bytecomp-is-loading)) |
| 147 | (let (p) | 194 | (let (p) |
| 148 | (setq p cc-bytecomp-unbound-variables) | 195 | (setq p cc-bytecomp-unbound-variables) |
| 149 | (while p | 196 | (while p |
| @@ -287,8 +334,7 @@ use within `eval-when-compile'." | |||
| 287 | `(eval-when-compile | 334 | `(eval-when-compile |
| 288 | (if (and (fboundp 'cc-bytecomp-is-compiling) | 335 | (if (and (fboundp 'cc-bytecomp-is-compiling) |
| 289 | (cc-bytecomp-is-compiling)) | 336 | (cc-bytecomp-is-compiling)) |
| 290 | (if (or (not load-in-progress) | 337 | (if (not (featurep ,cc-part)) |
| 291 | (not (featurep ,cc-part))) | ||
| 292 | (cc-bytecomp-load (symbol-name ,cc-part))) | 338 | (cc-bytecomp-load (symbol-name ,cc-part))) |
| 293 | (require ,cc-part)))) | 339 | (require ,cc-part)))) |
| 294 | 340 | ||
| @@ -301,12 +347,6 @@ afterwards. Don't use within `eval-when-compile'." | |||
| 301 | (require ,feature) | 347 | (require ,feature) |
| 302 | (eval-when-compile (cc-bytecomp-setup-environment)))) | 348 | (eval-when-compile (cc-bytecomp-setup-environment)))) |
| 303 | 349 | ||
| 304 | (defun cc-bytecomp-is-compiling () | ||
| 305 | "Return non-nil if eval'ed during compilation. Don't use outside | ||
| 306 | `eval-when-compile'." | ||
| 307 | (and (boundp 'byte-compile-dest-file) | ||
| 308 | (stringp byte-compile-dest-file))) | ||
| 309 | |||
| 310 | (defmacro cc-bytecomp-defvar (var) | 350 | (defmacro cc-bytecomp-defvar (var) |
| 311 | "Binds the symbol as a variable during compilation of the file, | 351 | "Binds the symbol as a variable during compilation of the file, |
| 312 | to silence the byte compiler. Don't use within `eval-when-compile'." | 352 | 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'." | |||
| 320 | "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) | 360 | "cc-bytecomp-defvar: Saving %s (as unbound)" ',var) |
| 321 | (setq cc-bytecomp-unbound-variables | 361 | (setq cc-bytecomp-unbound-variables |
| 322 | (cons ',var cc-bytecomp-unbound-variables)))) | 362 | (cons ',var cc-bytecomp-unbound-variables)))) |
| 323 | (if (and (cc-bytecomp-is-compiling) | 363 | (if (cc-bytecomp-is-compiling) |
| 324 | (not load-in-progress)) | ||
| 325 | (progn | 364 | (progn |
| 326 | (defvar ,var) | 365 | (defvar ,var) |
| 327 | (set ',var (intern (concat "cc-bytecomp-ignore-var:" | 366 | (set ',var (intern (concat "cc-bytecomp-ignore-var:" |
| @@ -349,8 +388,7 @@ at compile time, e.g. for macros and inline functions." | |||
| 349 | (setq cc-bytecomp-original-functions | 388 | (setq cc-bytecomp-original-functions |
| 350 | (cons (list ',fun nil 'unbound) | 389 | (cons (list ',fun nil 'unbound) |
| 351 | cc-bytecomp-original-functions)))) | 390 | cc-bytecomp-original-functions)))) |
| 352 | (if (and (cc-bytecomp-is-compiling) | 391 | (if (cc-bytecomp-is-compiling) |
| 353 | (not load-in-progress)) | ||
| 354 | (progn | 392 | (progn |
| 355 | (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" | 393 | (fset ',fun (intern (concat "cc-bytecomp-ignore-fun:" |
| 356 | (symbol-name ',fun)))) | 394 | (symbol-name ',fun)))) |
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 2ea566a7a25..d0beab1d485 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el | |||
| @@ -1983,19 +1983,22 @@ system." | |||
| 1983 | 1983 | ||
| 1984 | (defvar c-lang-const-expansion nil) | 1984 | (defvar c-lang-const-expansion nil) |
| 1985 | 1985 | ||
| 1986 | ;; Ugly hack to pull in the definition of `cc-bytecomp-compiling-or-loading` | ||
| 1987 | ;; from cc-bytecomp to make it available at loadtime. This is the same | ||
| 1988 | ;; mechanism used in cc-mode.el for `c-populate-syntax-table'. | ||
| 1989 | (defalias 'cc-bytecomp-compiling-or-loading | ||
| 1990 | (cc-eval-when-compile | ||
| 1991 | (let ((f (symbol-function 'cc-bytecomp-compiling-or-loading))) | ||
| 1992 | (if (byte-code-function-p f) f (byte-compile f))))) | ||
| 1993 | |||
| 1986 | (defsubst c-get-current-file () | 1994 | (defsubst c-get-current-file () |
| 1987 | ;; Return the base name of the current file. | 1995 | ;; Return the base name of the current file. |
| 1988 | (let ((file (cond | 1996 | (let* ((c-or-l (cc-bytecomp-compiling-or-loading)) |
| 1989 | (load-in-progress | 1997 | (file |
| 1990 | ;; Being loaded. | 1998 | (cond |
| 1991 | load-file-name) | 1999 | ((eq c-or-l 'loading) load-file-name) |
| 1992 | ((and (boundp 'byte-compile-dest-file) | 2000 | ((eq c-or-l 'compiling) byte-compile-dest-file) |
| 1993 | (stringp byte-compile-dest-file)) | 2001 | ((null c-or-l) (buffer-file-name))))) |
| 1994 | ;; Being compiled. | ||
| 1995 | byte-compile-dest-file) | ||
| 1996 | (t | ||
| 1997 | ;; Being evaluated interactively. | ||
| 1998 | (buffer-file-name))))) | ||
| 1999 | (and file | 2002 | (and file |
| 2000 | (file-name-sans-extension | 2003 | (file-name-sans-extension |
| 2001 | (file-name-nondirectory file))))) | 2004 | (file-name-nondirectory file))))) |
| @@ -2062,6 +2065,9 @@ constant. A file is identified by its base name." | |||
| 2062 | ;; language constant source definitions.) | 2065 | ;; language constant source definitions.) |
| 2063 | (c-lang-const-expansion 'call) | 2066 | (c-lang-const-expansion 'call) |
| 2064 | (c-langs-are-parametric t) | 2067 | (c-langs-are-parametric t) |
| 2068 | (file (intern | ||
| 2069 | (or (c-get-current-file) | ||
| 2070 | (error "`c-lang-defconst' can only be used in a file")))) | ||
| 2065 | bindings | 2071 | bindings |
| 2066 | pre-files) | 2072 | pre-files) |
| 2067 | 2073 | ||
| @@ -2121,9 +2127,14 @@ constant. A file is identified by its base name." | |||
| 2121 | ;; definitions for this symbol, to make sure the order in the | 2127 | ;; definitions for this symbol, to make sure the order in the |
| 2122 | ;; `source' property is correct even when files are loaded out of | 2128 | ;; `source' property is correct even when files are loaded out of |
| 2123 | ;; order. | 2129 | ;; order. |
| 2124 | (setq pre-files (nreverse | 2130 | (setq pre-files (mapcar 'car (get sym 'source))) |
| 2125 | ;; Reverse to get the right load order. | 2131 | (if (memq file pre-files) |
| 2126 | (mapcar 'car (get sym 'source)))) | 2132 | ;; This can happen when the source file (e.g. cc-langs.el) is first |
| 2133 | ;; loaded as source, setting a 'source property entry, and then itself | ||
| 2134 | ;; being compiled. | ||
| 2135 | (setq pre-files (cdr (memq file pre-files)))) | ||
| 2136 | ;; Reverse to get the right load order. | ||
| 2137 | (setq pre-files (nreverse pre-files)) | ||
| 2127 | 2138 | ||
| 2128 | `(eval-and-compile | 2139 | `(eval-and-compile |
| 2129 | (c-define-lang-constant ',name ,bindings | 2140 | (c-define-lang-constant ',name ,bindings |
| @@ -2233,9 +2244,7 @@ quoted." | |||
| 2233 | (if (or (eq c-lang-const-expansion 'call) | 2244 | (if (or (eq c-lang-const-expansion 'call) |
| 2234 | (and (not c-lang-const-expansion) | 2245 | (and (not c-lang-const-expansion) |
| 2235 | (not mode)) | 2246 | (not mode)) |
| 2236 | load-in-progress | 2247 | (not (cc-bytecomp-is-compiling))) |
| 2237 | (not (boundp 'byte-compile-dest-file)) | ||
| 2238 | (not (stringp byte-compile-dest-file))) | ||
| 2239 | ;; Either a straight call is requested in the context, or | 2248 | ;; Either a straight call is requested in the context, or |
| 2240 | ;; we're in an "uncontrolled" context and got no language, | 2249 | ;; we're in an "uncontrolled" context and got no language, |
| 2241 | ;; or we're not being byte compiled so the compile time | 2250 | ;; 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 17d717e740f..4d16a9b9d33 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -3260,10 +3260,7 @@ function it returns is byte compiled with all the evaluated results | |||
| 3260 | from the language constants. Use the `c-init-language-vars' macro to | 3260 | from the language constants. Use the `c-init-language-vars' macro to |
| 3261 | accomplish that conveniently." | 3261 | accomplish that conveniently." |
| 3262 | 3262 | ||
| 3263 | (if (and (not load-in-progress) | 3263 | (if (cc-bytecomp-is-compiling) |
| 3264 | (boundp 'byte-compile-dest-file) | ||
| 3265 | (stringp byte-compile-dest-file)) | ||
| 3266 | |||
| 3267 | ;; No need to byte compile this lambda since the byte compiler is | 3264 | ;; No need to byte compile this lambda since the byte compiler is |
| 3268 | ;; smart enough to detect the `funcall' construct in the | 3265 | ;; smart enough to detect the `funcall' construct in the |
| 3269 | ;; `c-init-language-vars' macro below and compile it all straight | 3266 | ;; `c-init-language-vars' macro below and compile it all straight |