bug-gnu-emacs
[Top][All Lists]
Advanced

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

bug#47191: File as attachment


From: Alan Mackenzie
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@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).





reply via email to

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