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

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

bug#7722: 24.0.50; Finding this C++ header file drops emacs into a infin


From: Alan Mackenzie
Subject: bug#7722: 24.0.50; Finding this C++ header file drops emacs into a infinite loop
Date: Fri, 4 Feb 2011 22:22:07 +0000
User-agent: Mutt/1.5.9i

Hi there, Yidong, Tassilo,

On Sat, Jan 22, 2011 at 03:37:24PM -0500, Chong Yidong wrote:
> Tassilo Horn <tassilo@member.fsf.org> writes:

> > Originally reported by Caligo <iteronvexor@gmail.com>

> > He uses GNU Emacs 23.2.1 (x86_64-pc-linux-gnu, GTK+ Version 2.20.1),
> > but the bug in still in the current bzr trunk.

> > 1. emacs -Q bug.hpp
> > 2. emacs loops infinitely using 100% CPU resources

> > The offending file is that (according to the original reporter, the
> > spaces and empty lines are needed):

> I can reproduce this (file attached for convenience).  Alan, could you
> take a look?  Looks like a loop in c-forward-<>-arglist-recur:

It was indeed such a loop.  It was caused by a 500n jit-lock boundary
falling in the middle of a template construct, hence the "necessity" of
all the whitespace to reproduce the failure.

Here's a putative patch for the problem.  I've refactored the offending
function by replacing obscenely nested `if'-forms with a simple `cond'.
I've also removed some narrowing (to the 500n limit) which should help
jit-lock, hopefully without hurting too much elsewhere.

Tassilo, would you try out the patch, please, and let me know how it
goes.  Thanks!



=== modified file 'lisp/progmodes/cc-engine.el'
*** lisp/progmodes/cc-engine.el 2011-01-31 23:54:50 +0000
--- lisp/progmodes/cc-engine.el 2011-02-04 22:12:46 +0000
***************
*** 5455,5463 ****
            (goto-char start)
            nil))
  
!       (forward-char)
  
        (unless (looking-at c-<-op-cont-regexp)
        (while (and
                (progn
                  (c-forward-syntactic-ws)
--- 5455,5465 ----
            (goto-char start)
            nil))
  
!       (forward-char) ; Forward over the opening '<'.
  
        (unless (looking-at c-<-op-cont-regexp)
+       ;; go forward one non-alphanumeric character (group) per iteration of
+       ;; this loop.
        (while (and
                (progn
                  (c-forward-syntactic-ws)
***************
*** 5486,5492 ****
                            (c-forward-type)
                            (c-forward-syntactic-ws))))))
  
!                 (setq pos (point))
  
                  ;; Note: These regexps exploit the match order in \| so
                  ;; that "<>" is matched by "<" rather than "[^>:-]>".
--- 5488,5494 ----
                            (c-forward-type)
                            (c-forward-syntactic-ws))))))
  
!                 (setq pos (point))    ; e.g. first token inside the '<'
  
                  ;; Note: These regexps exploit the match order in \| so
                  ;; that "<>" is matched by "<" rather than "[^>:-]>".
***************
*** 5522,5559 ****
                  ;; Either an operator starting with '<' or a nested arglist.
                  (setq pos (point))
                  (let (id-start id-end subres keyword-match)
!                   (if (if (looking-at c-<-op-cont-regexp)
!                           (setq tmp (match-end 0))
!                         (setq tmp pos)
!                         (backward-char)
!                         (not
!                          (and
! 
!                           (save-excursion
!                             ;; There's always an identifier before an angle
!                             ;; bracket arglist, or a keyword in
!                             ;; `c-<>-type-kwds' or `c-<>-arglist-kwds'.
!                             (c-backward-syntactic-ws)
!                             (setq id-end (point))
!                             (c-simple-skip-symbol-backward)
!                             (when (or (setq keyword-match
!                                             (looking-at c-opt-<>-sexp-key))
!                                       (not (looking-at c-keywords-regexp)))
!                               (setq id-start (point))))
! 
!                           (setq subres
!                                 (let ((c-promote-possible-types t)
!                                       (c-record-found-types t))
!                                   (c-forward-<>-arglist-recur
!                                    (and keyword-match
!                                         (c-keyword-member
!                                          (c-keyword-sym (match-string 1))
!                                          'c-<>-type-kwds)))))
!                           )))
! 
!                       ;; It was not an angle bracket arglist.
!                       (goto-char tmp)
! 
                      ;; It was an angle bracket arglist.
                      (setq c-record-found-types subres)
  
--- 5524,5558 ----
                  ;; Either an operator starting with '<' or a nested arglist.
                  (setq pos (point))
                  (let (id-start id-end subres keyword-match)
!                   (cond
!                    ;; The '<' begins a multi-char operator.
!                    ((looking-at c-<-op-cont-regexp)
!                     (setq tmp (match-end 0))
!                     (goto-char (match-end 0)))
!                    ;; We're at a nested <.....>
!                    ((progn
!                       (setq tmp pos)
!                       (backward-char) ; to the '<'
!                       (and
!                        (save-excursion
!                          ;; There's always an identifier before an angle
!                          ;; bracket arglist, or a keyword in `c-<>-type-kwds'
!                          ;; or `c-<>-arglist-kwds'.
!                          (c-backward-syntactic-ws)
!                          (setq id-end (point))
!                          (c-simple-skip-symbol-backward)
!                          (when (or (setq keyword-match
!                                          (looking-at c-opt-<>-sexp-key))
!                                    (not (looking-at c-keywords-regexp)))
!                            (setq id-start (point))))
!                        (setq subres
!                              (let ((c-promote-possible-types t)
!                                    (c-record-found-types t))
!                                (c-forward-<>-arglist-recur
!                                 (and keyword-match
!                                      (c-keyword-member
!                                       (c-keyword-sym (match-string 1))
!                                       'c-<>-type-kwds)))))))
                      ;; It was an angle bracket arglist.
                      (setq c-record-found-types subres)
  
***************
*** 5567,5574 ****
                                   (c-forward-syntactic-ws)
                                   (looking-at c-opt-identifier-concat-key)))
                            (c-record-ref-id (cons id-start id-end))
!                         (c-record-type-id (cons id-start id-end))))))
!                 t)
  
                 ((and (not c-restricted-<>-arglists)
                       (or (and (eq (char-before) ?&)
--- 5566,5578 ----
                                   (c-forward-syntactic-ws)
                                   (looking-at c-opt-identifier-concat-key)))
                            (c-record-ref-id (cons id-start id-end))
!                         (c-record-type-id (cons id-start id-end)))))
! 
!                    ;; At a "less than" operator.
!                    (t
!                     (forward-char)
!                     )))
!                 t)                    ; carry on looping.
  
                 ((and (not c-restricted-<>-arglists)
                       (or (and (eq (char-before) ?&)

=== modified file 'lisp/progmodes/cc-fonts.el'
*** lisp/progmodes/cc-fonts.el  2011-01-25 04:08:28 +0000
--- lisp/progmodes/cc-fonts.el  2011-02-04 22:10:01 +0000
***************
*** 1082,1088 ****
             (boundp 'parse-sexp-lookup-properties))))
  
        ;; Below we fontify a whole declaration even when it crosses the limit,
!       ;; to avoid gaps when lazy-lock fontifies the file a screenful at a
        ;; time.  That is however annoying during editing, e.g. the following is
        ;; a common situation while the first line is being written:
        ;;
--- 1082,1088 ----
             (boundp 'parse-sexp-lookup-properties))))
  
        ;; Below we fontify a whole declaration even when it crosses the limit,
!       ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
        ;; time.  That is however annoying during editing, e.g. the following is
        ;; a common situation while the first line is being written:
        ;;
***************
*** 1094,1102 ****
        ;; "some_other_variable" as an identifier, and the latter will not
        ;; correct itself until the second line is changed.  To avoid that we
        ;; narrow to the limit if the region to fontify is a single line.
!       (narrow-to-region
!        (point-min)
!        (if (<= limit (c-point 'bonl))
           (save-excursion
             ;; Narrow after any operator chars following the limit though,
             ;; since those characters can be useful in recognizing a
--- 1094,1102 ----
        ;; "some_other_variable" as an identifier, and the latter will not
        ;; correct itself until the second line is changed.  To avoid that we
        ;; narrow to the limit if the region to fontify is a single line.
!       (if (<= limit (c-point 'bonl))
!         (narrow-to-region
!          (point-min)
           (save-excursion
             ;; Narrow after any operator chars following the limit though,
             ;; since those characters can be useful in recognizing a
***************
*** 1104,1111 ****
             ;; after the header).
             (goto-char limit)
             (skip-chars-forward c-nonsymbol-chars)
!            (point))
!        limit))
  
        (c-find-decl-spots
         limit
--- 1104,1110 ----
             ;; after the header).
             (goto-char limit)
             (skip-chars-forward c-nonsymbol-chars)
!            (point))))
  
        (c-find-decl-spots
         limit




-- 
Alan Mackenzie (Nuremberg, Germany).





reply via email to

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