From: Alan Mackenzie Date: Mon, 29 Mar 2021 15:32:40 +0000 (+0000) Subject: Fix an infinite loop in C++ Mode redisplay. This was bug #47191. X-Git-Tag: emacs-28.0.90~3095 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1440dbed544a76ee3b876cb573b5110211e798bb;p=emacs.git Fix an infinite loop in C++ Mode redisplay. This was bug #47191. * lisp/progmodes/cc-defs.el (c-forward-syntactic-ws, c-backward-syntactic-ws): When point is on the wrong side of a supplied search limit, leave point unmoved rather than setting it to that limit. * lisp/progmodes/cc-engine.el (c-forward-name): After scanning a template argument list (which is not itself subject to a search limit) recalculate the search limit starting from the end point, since these argument lists can legitimately be long. At each of the scanning loops, check point hasn't gone past the limit. --- diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 38fe23b0eaf..536e6766261 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el @@ -691,14 +691,16 @@ whitespace. LIMIT sets an upper limit of the forward movement, if specified. If LIMIT or the end of the buffer is reached inside a comment or -preprocessor directive, the point will be left there. +preprocessor directive, the point will be left there. If point starts +on the wrong side of LIMIT, it stays unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." (if limit - `(save-restriction - (narrow-to-region (point-min) (or ,limit (point-max))) - (c-forward-sws)) + `(when (< (point) (or ,limit (point-max))) + (save-restriction + (narrow-to-region (point-min) (or ,limit (point-max))) + (c-forward-sws))) '(c-forward-sws))) (defmacro c-backward-syntactic-ws (&optional limit) @@ -710,14 +712,16 @@ whitespace. LIMIT sets a lower limit of the backward movement, if specified. If LIMIT is reached inside a line comment or preprocessor directive then -the point is moved into it past the whitespace at the end. +the point is moved into it past the whitespace at the end. If point +starts on the wrong side of LIMIT, it stays unchanged. Note that this function might do hidden buffer changes. See the comment at the start of cc-engine.el for more info." (if limit - `(save-restriction - (narrow-to-region (or ,limit (point-min)) (point-max)) - (c-backward-sws)) + `(when (> (point) (or ,limit (point-min))) + (save-restriction + (narrow-to-region (or ,limit (point-min)) (point-max)) + (c-backward-sws))) '(c-backward-sws))) (defmacro c-forward-sexp (&optional count) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index b7ad02cf0cd..cc9833a434e 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -8300,7 +8300,7 @@ comment at the start of cc-engine.el for more info." ;; o - nil if no name is found; ;; o - 'template if it's an identifier ending with an angle bracket ;; arglist; - ;; o - 'operator of it's an operator identifier; + ;; o - 'operator if it's an operator identifier; ;; o - t if it's some other kind of name. ;; ;; This function records identifier ranges on @@ -8320,6 +8320,7 @@ comment at the start of cc-engine.el for more info." (lim+ (c-determine-+ve-limit 500))) (while (and + (< (point) lim+) (looking-at c-identifier-key) (progn @@ -8369,23 +8370,28 @@ comment at the start of cc-engine.el for more info." ;; '*', '&' or a name followed by ":: *", ;; where each can be followed by a sequence ;; of `c-opt-type-modifier-key'. - (while (cond ((looking-at "[*&]") - (goto-char (match-end 0)) - t) - ((looking-at c-identifier-start) - (and (c-forward-name) - (looking-at "::") - (progn - (goto-char (match-end 0)) - (c-forward-syntactic-ws lim+) - (eq (char-after) ?*)) - (progn - (forward-char) - t)))) + (while + (and + (< (point) lim+) + (cond ((looking-at "[*&]") + (goto-char (match-end 0)) + t) + ((looking-at c-identifier-start) + (and (c-forward-name) + (looking-at "::") + (progn + (goto-char (match-end 0)) + (c-forward-syntactic-ws lim+) + (eq (char-after) ?*)) + (progn + (forward-char) + t))))) (while (progn (c-forward-syntactic-ws lim+) (setq pos (point)) - (looking-at c-opt-type-modifier-key)) + (and + (<= (point) lim+) + (looking-at c-opt-type-modifier-key))) (goto-char (match-end 1)))))) ((looking-at c-overloadable-operators-regexp) @@ -8431,6 +8437,9 @@ comment at the start of cc-engine.el for more info." ;; Maybe an angle bracket arglist. (when (let (c-last-identifier-range) (c-forward-<>-arglist nil)) + ;; <> arglists can legitimately be very long, so recalculate + ;; `lim+'. + (setq lim+ (c-determine-+ve-limit 500)) (c-forward-syntactic-ws lim+) (unless (eq (char-after) ?\()