Package: emacs;
Reported by: Damien <dam <at> cosinux.org>
Date: Tue, 16 Mar 2021 15:25:01 UTC
Severity: normal
Found in version 28.0.50
Done: Alan Mackenzie <acm <at> muc.de>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Alan Mackenzie <acm <at> muc.de> To: Eli Zaretskii <eliz <at> gnu.org> Cc: acm <at> muc.de, 47191 <at> debbugs.gnu.org, Damien <dam <at> cosinux.org> Subject: bug#47191: File as attachment Date: Sat, 20 Mar 2021 20:30:54 +0000
Hello, Eli and Damien. On Fri, Mar 19, 2021 at 17:28:03 +0200, Eli Zaretskii wrote: > > From: Damien <dam <at> cosinux.org> > > Date: Wed, 17 Mar 2021 07:48:39 +0000 > > Also here is the file as attachment to make sure it was not a copy/paste error > Thanks. > Emacs infloops in redisplay when visiting this file, because > fontification of this file infloops, and that happens on the master > branch as well, so it has nothing to do with native-compilation > branch. The infloop seems to be in c-forward-name, I attach the > backtrace below. > Alan, could you please look into this? [ .... ] > Lisp Backtrace: > "c-forward-name" (0x8234a0) > "c-forward-type" (0x823e30) > "c-forward-decl-or-cast-1" (0x825240) > 0x6d7e6e0 PVEC_COMPILED > "c-find-decl-spots" (0x826d30) > "c-font-lock-declarations" (0x8273c8) > "font-lock-fontify-keywords-region" (0x827b40) > "font-lock-default-fontify-region" (0x828190) > "c-font-lock-fontify-region" (0x828808) > "font-lock-fontify-region" (0x828dc8) > 0x6fdbd30 PVEC_COMPILED > "run-hook-wrapped" (0x829690) > "jit-lock--run-functions" (0x829cc0) > "jit-lock-fontify-now" (0x82a3e8) > "jit-lock-function" (0x82aa68) > "redisplay_internal (C function)" (0x0) The trigger for the bug was a CC Mode "name" (the return type) which was longer than 500 characters. This 500 was a search limit introduced for performance reasons around the turn of the year. Part of the bug was that when a forward scanning macro (c-forward-syntactic-ws) was given a limit less than point, point was set back to that limit, causing the loop. The fix involves not ever moving point backwards in c-forward-syntactic-ws, and recalculating the 500 character limit after scanning a template construct; template expressions can easily be very long. Damien, would you please try out the following patch (the files are in ..../emacs/lisp/progmodes) on your real C++ source code, and either confirm to us that the bug is fixed, or tell us what still needs fixing. After applying the patch, please recompile _all_ of CC Mode (the files ..../emacs/progmodes/cc-*.el), since two macros have been amended. If you want any help with the patching or byte compiling, feel free to send me private mail. Thanks! Here's the patch: diff -r 11350de71bc6 cc-defs.el --- a/cc-defs.el Sat Mar 06 15:11:24 2021 +0000 +++ b/cc-defs.el Sat Mar 20 20:08:58 2021 +0000 @@ -656,14 +656,16 @@ 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) @@ -675,14 +677,16 @@ 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 -r 11350de71bc6 cc-engine.el --- a/cc-engine.el Sat Mar 06 15:11:24 2021 +0000 +++ b/cc-engine.el Sat Mar 20 20:08:58 2021 +0000 @@ -8318,7 +8318,7 @@ ;; 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 @@ -8338,6 +8338,7 @@ (lim+ (c-determine-+ve-limit 500))) (while (and + (< (point) lim+) (looking-at c-identifier-key) (progn @@ -8387,23 +8388,28 @@ ;; '*', '&' 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) @@ -8449,6 +8455,9 @@ ;; 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) ?\() -- Alan Mackenzie (Nuremberg, Germany).
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.