]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow compilation during loading of Modes derived from a CC Mode mode.
authorAlan Mackenzie <acm@muc.de>
Tue, 13 Jan 2015 15:39:36 +0000 (15:39 +0000)
committerAlan Mackenzie <acm@muc.de>
Tue, 13 Jan 2015 15:47:26 +0000 (15:47 +0000)
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.

lisp/ChangeLog
lisp/progmodes/cc-bytecomp.el
lisp/progmodes/cc-defs.el
lisp/progmodes/cc-langs.el

index 532a10a1b713f49f745ed1351ef129f8a7ed1662..072af5b1b9102d0e3030b9b585b0ac0c549e8503 100644 (file)
@@ -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'
index bf7803c85ca243e6946c1725b578fc902cba86a1..b63eeb4c7a6a76b6b2290f99ba76699c956bd30d 100644 (file)
   ;;`(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))))
index 2ea566a7a258954c2697008b56bf8294282e5f59..d0beab1d48555e6696a2fc05f32fe579e51b77b7 100644 (file)
@@ -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
index 17d717e740f4fae443bc807d6a63e0eb1cb7c404..4d16a9b9d33a48761eb877dcbce1aedf20279c2c 100644 (file)
@@ -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