Subject: Re: bug#47191: File as attachment

From: Damien <[email-masked]>
Date: Mon, 29 Mar 2021 09:12:32 +0000

The patch fixes the problem for me. Also, before the patch emacs would freeze regularly due to eglot formatting the cpp function definintions when moving past one, and everything seems ok now.

Thanks a lot for helping me and fixing this !

"Alan Mackenzie" [email-masked] – 20 mars 2021 20:30
> Hello, Eli and Damien.
>
> On Fri, Mar 19, 2021 at 17:28:03 +0200, Eli Zaretskii wrote:
> > > From: Damien <[email-masked]>
> > > 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) ?\()
>
>
>