[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).
- bug#7722: 24.0.50; Finding this C++ header file drops emacs into a infinite loop,
Alan Mackenzie <=