From 6b5388794b4d1118cb4443cfccc1bdebb4fb1af4 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 13 Jun 2019 14:07:06 +0000 Subject: [PATCH] Depessimize bits of CC Mode for long C macros. * lisp/progmodes/cc-engine.el (c-end-of-macro): Check for being in a degenerate zero length "macro", when setting the macro cache. (c-determine-+ve-limit): Add in a missing goto-char form for when start-pos is non-nil. (c-back-over-member-initializers): Add a search limit parameter. * lisp/progmodes/cc-fonts.el (c-get-fontification-context): Add a search limit to c-go-up-list-backward. (c-font-lock-cut-off-declarators): Add a search limit to c-back-over-member-initializers. * lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings): Don't set c-new-END to the end of logical line (which might be a long macro). (c-after-change-mark-abnormal-strings): Calculate end-hwm in place of the setting of c-new-END (above). Use this as a search limit rather than c-new-END. --- lisp/progmodes/cc-engine.el | 76 ++++++++++++++++++++----------------- lisp/progmodes/cc-fonts.el | 4 +- lisp/progmodes/cc-mode.el | 17 +++++++-- 3 files changed, 56 insertions(+), 41 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index b121529086a..eeb71002673 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -380,6 +380,8 @@ comment at the start of cc-engine.el for more info." nil))) (when (and (car c-macro-cache) + (> (point) (car c-macro-cache)) ; in case we have a + ; zero-sized region. (bolp) (not (eq (char-before (1- (point))) ?\\))) (setcdr c-macro-cache (point)) @@ -5646,6 +5648,7 @@ comment at the start of cc-engine.el for more info." (let ((pos (or start-pos (point))) (count how-far) (s (parse-partial-sexp (point) (point)))) ; null state + (goto-char pos) (while (and (not (eobp)) (> count 0)) ;; Scan over counted characters. @@ -8609,53 +8612,56 @@ comment at the start of cc-engine.el for more info." (throw 'level nil)) (c-backward-syntactic-ws))) -(defun c-back-over-member-initializers () +(defun c-back-over-member-initializers (&optional limit) ;; 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)) - 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 - (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-back-over-compound-identifier) - (c-backward-syntactic-ws)) - (c-back-over-list-of-member-inits) - (and (eq (char-before) ?:) - (save-excursion - (c-backward-token-2) - (not (looking-at c-:$-multichar-token-regexp))) - (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. + ;; LIMIT, if non-nil, is a limit for the backward search. + (save-restriction + (if limit (narrow-to-region limit (point))) + (let ((here (point)) + (paren-state (c-parse-state)) + 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 (setq level-plausible (catch 'level - (goto-char pos) - (c-backward-syntactic-ws) - (when (not (c-back-over-compound-identifier)) - (throw 'level nil)) (c-backward-syntactic-ws) + (when (memq (char-before) '(?\) ?})) + (when (not (c-go-list-backward)) + (throw 'done nil)) + (c-backward-syntactic-ws)) + (when (c-back-over-compound-identifier) + (c-backward-syntactic-ws)) (c-back-over-list-of-member-inits) (and (eq (char-before) ?:) (save-excursion (c-backward-token-2) (not (looking-at c-:$-multichar-token-regexp))) - (c-just-after-func-arglist-p))))) + (c-just-after-func-arglist-p)))) - (and at-top-level level-plausible))) - (or res (goto-char here)) - res)) + (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-back-over-compound-identifier)) + (throw 'level nil)) + (c-backward-syntactic-ws) + (c-back-over-list-of-member-inits) + (and (eq (char-before) ?:) + (save-excursion + (c-backward-token-2) + (not (looking-at c-:$-multichar-token-regexp))) + (c-just-after-func-arglist-p))))) + + (and at-top-level level-plausible))) + (or res (goto-char here)) + res))) (defun c-forward-class-decl () "From the beginning of a struct/union, etc. move forward to diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index c3dd8f85bdc..cef2015f430 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1204,7 +1204,7 @@ casts and declarations are fontified. Used on level 2 and higher." ((save-excursion (goto-char match-pos) (and (memq (char-before match-pos) '(?\( ?\,)) - (c-go-up-list-backward match-pos) + (c-go-up-list-backward match-pos (c-determine-limit 500)) (eq (char-after) ?\() (let ((type (c-get-char-property (point) 'c-type))) (or (memq type '(c-decl-arg-start c-decl-type-start)) @@ -1605,7 +1605,7 @@ casts and declarations are fontified. Used on level 2 and higher." c-recognize-knr-p) ; Strictly speaking, bogus, but it ; speeds up lisp.h tremendously. (save-excursion - (when (not (c-back-over-member-initializers)) + (when (not (c-back-over-member-initializers (c-determine-limit 2000))) (unless (or (eobp) (looking-at "\\s(\\|\\s)")) (forward-char)) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 83c0e36167d..830dfcae27d 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1256,7 +1256,6 @@ Note that the style variables are always made local to the buffer." (re-search-forward "[\n\r]?\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t) ;; We're at an EOLL or point-max. - (setq c-new-END (max c-new-END (min (1+ (point)) (point-max)))) (if (equal (c-get-char-property (point) 'syntax-table) '(15)) (if (memq (char-after) '(?\n ?\r)) ;; Normally terminated invalid string. @@ -1363,6 +1362,16 @@ Note that the style variables are always made local to the buffer." (cdr (assq (char-before) c-string-innards-re-alist)) nil t) (1+ (point))))) (cll))) + (end-hwm ; the highest position which could possibly be affected by + ; insertion/deletion of string delimiters. + (max + (progn + (goto-char (min (1+ end) ; 1+, in case a NL has become escaped. + (point-max))) + (re-search-forward "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\\\n\r]\\)*" + nil t) + (point)) + c-new-END)) s) (goto-char (cond ((null beg-literal-type) @@ -1374,13 +1383,13 @@ Note that the style variables are always made local to the buffer." ;; Handle one string each time around the next while loop. (while (and - (< (point) c-new-END) + (< (point) end-hwm) (progn ;; Skip over any comments before the next string. (while (progn - (setq s (parse-partial-sexp (point) c-new-END nil + (setq s (parse-partial-sexp (point) end-hwm nil nil s 'syntax-table)) - (and (< (point) c-new-END) + (and (< (point) end-hwm) (or (not (nth 3 s)) (not (memq (char-before) c-string-delims)))))) ;; We're at the start of a string.