emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs-25 4765d24: De-pessimize detection of C++ member ini


From: Alan Mackenzie
Subject: [Emacs-diffs] emacs-25 4765d24: De-pessimize detection of C++ member initialization lists.
Date: Sun, 15 Nov 2015 22:00:47 +0000

branch: emacs-25
commit 4765d24e18a947678bfa63b0351f68931484273c
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>

    De-pessimize detection of C++ member initialization lists.
    
    list/progmodes/cc-engine.el (c-back-over-list-of-member-inits): New macro.
    (c-back-over-member-initializers): Reformulate such that c-at-toplevel-p
    is only called when a construct "looks right" rather than continually.
    (c-guess-basic-syntax, CASE 5R): Add a check for the mode being C++ Mode.
---
 lisp/progmodes/cc-engine.el |   89 ++++++++++++++++++++++++++-----------------
 1 files changed, 54 insertions(+), 35 deletions(-)

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 6572cee..9e9bee8 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -6666,49 +6666,65 @@ comment at the start of cc-engine.el for more info."
     (or res (goto-char here))
     res))
 
+(defmacro c-back-over-list-of-member-inits ()
+  ;; Go back over a list of elements, each looking like:
+  ;; <symbol> (<expression>) ,
+  ;; or <symbol> {<expression>} ,
+  ;; when we are putatively immediately after a comma.  Stop when we don't see
+  ;; a comma.  If either of <symbol> or bracketed <expression> is missing,
+  ;; throw nil to 'level.  If the terminating } or ) is unmatched, throw nil
+  ;; to 'done.  This is not a general purpose macro!
+  `(while (eq (char-before) ?,)
+     (backward-char)
+     (c-backward-syntactic-ws)
+     (when (not (memq (char-before) '(?\) ?})))
+       (throw 'level nil))
+     (when (not (c-go-list-backward))
+       (throw 'done nil))
+     (c-backward-syntactic-ws)
+     (when (not (c-simple-skip-symbol-backward))
+       (throw 'level nil))
+     (c-backward-syntactic-ws)))
+
 (defun c-back-over-member-initializers ()
   ;; Test whether we are in a C++ member initializer list, and if so, go back
   ;; to the introducing ":", returning the position of the opening paren of
   ;; the function's arglist.  Otherwise return nil, leaving point unchanged.
   (let ((here (point))
        (paren-state (c-parse-state))
-       res)
-
+       pos level-plausible at-top-level res)
+    ;; Assume tentatively that we're at the top level.  Try to go back to the
+    ;; colon we seek.
     (setq res
          (catch 'done
-           (if (not (c-at-toplevel-p))
-               (progn
-                 (while (not (c-at-toplevel-p))
-                   (goto-char (c-pull-open-brace paren-state)))
-                 (c-backward-syntactic-ws)
-                 (when (not (c-simple-skip-symbol-backward))
-                   (throw 'done nil))
-                 (c-backward-syntactic-ws))
-             (c-backward-syntactic-ws)
-             (when (memq (char-before) '(?\) ?}))
-               (when (not (c-go-list-backward))
-                 (throw 'done nil))
-               (c-backward-syntactic-ws))
-             (when (c-simple-skip-symbol-backward)
-               (c-backward-syntactic-ws)))
-
-           (while (eq (char-before) ?,)
-             (backward-char)
-             (c-backward-syntactic-ws)
-
-             (when (not (memq (char-before) '(?\) ?})))
-               (throw 'done nil))
-             (when (not (c-go-list-backward))
-               (throw 'done nil))
-             (c-backward-syntactic-ws)
-             (when (not (c-simple-skip-symbol-backward))
-               (throw 'done nil))
-             (c-backward-syntactic-ws))
-
-           (and
-            (eq (char-before) ?:)
-            (c-just-after-func-arglist-p))))
+           (setq level-plausible
+                 (catch 'level
+                   (c-backward-syntactic-ws)
+                   (when (memq (char-before) '(?\) ?}))
+                     (when (not (c-go-list-backward))
+                       (throw 'done nil))
+                     (c-backward-syntactic-ws))
+                   (when (c-simple-skip-symbol-backward)
+                     (c-backward-syntactic-ws))
+                   (c-back-over-list-of-member-inits)
+                   (and (eq (char-before) ?:)
+                        (c-just-after-func-arglist-p))))
+
+           (while (and (not (and level-plausible
+                                 (setq at-top-level (c-at-toplevel-p))))
+                       (setq pos (c-pull-open-brace paren-state))) ; might be 
a paren.
+             (setq level-plausible
+                   (catch 'level
+                     (goto-char pos)
+                     (c-backward-syntactic-ws)
+                     (when (not (c-simple-skip-symbol-backward))
+                       (throw 'level nil))
+                     (c-backward-syntactic-ws)
+                     (c-back-over-list-of-member-inits)
+                     (and (eq (char-before) ?:)
+                          (c-just-after-func-arglist-p)))))
 
+           (and at-top-level level-plausible)))
     (or res (goto-char here))
     res))
 
@@ -8048,6 +8064,8 @@ brace.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
+  ;; Note to maintainers: this function consumes a great mass of CPU cycles.
+  ;; It's use should thus be minimised as far as possible.
   (let ((paren-state (c-parse-state)))
     (or (not (c-most-enclosing-brace paren-state))
        (c-search-uplist-for-classkey paren-state))))
@@ -10052,7 +10070,8 @@ comment at the start of cc-engine.el for more info."
         ;; Note there is no limit on the backward search here, since member
         ;; init lists can, in practice, be very large.
         ((save-excursion
-           (when (setq placeholder (c-back-over-member-initializers))
+           (when (and (c-major-mode-is 'c++-mode)
+                      (setq placeholder (c-back-over-member-initializers)))
              (setq tmp-pos (point))))
          (if (= (c-point 'bosws) (1+ tmp-pos))
                (progn



reply via email to

[Prev in Thread] Current Thread [Next in Thread]