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

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

bug#11749: Acknowledgement (24.1; C-mode indentation gives wrong-type-ar


From: Alan Mackenzie
Subject: bug#11749: Acknowledgement (24.1; C-mode indentation gives wrong-type-argument error.)
Date: Wed, 23 Jan 2013 14:16:45 +0000
User-agent: Mutt/1.5.21 (2010-09-15)

Hi, Michael.

On Thu, Jan 17, 2013 at 11:27:04AM -0500, Michael Welsh Duggan wrote:
> Alan Mackenzie <acm@muc.de> writes:

> [This] fixes this case, indeed.  Unfortunately, here's another.

> emacs -Q rwtransfer.c
>   M-x c-toggle-parse-state-debug
>   M->
> Then type M-v until the parse failure happens.  For me it happens at 
> 32% point in the file.  Please not that this particular problem only
> happens when paging through the file in reverse order.

> c-parse-state inconsistency at 15885: using cache: (15636 15181 (13849 . 
> 15141)), from scratch: (15636 (15303 . 15493) 15181 (13849 . 15141))
> Old state:
> (setq c-state-cache '(16334 16271 16248 (16059 . 16193) 15181 (13849 . 
> 15141))  c-state-cache-good-pos 16335  c-state-nonlit-pos-cache '(48473 45473 
> 42473 39473 36473 33473 30473 27378 24378 21260 18015 15015 12015 9015 6015 
> 3015)  c-state-nonlit-pos-cache-limit 48473  c-state-semi-nonlit-pos-cache 
> '(48323 45323 42323 39323 36323 33260 30260 27260 24260 21260 18001 15001 
> 12001 9001 6001 3001)  c-state-semi-nonlit-pos-cache-limit 48323  
> c-state-brace-pair-desert '(15181 . 17388)  c-state-point-min 1  
> c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  
> c-state-min-scan-pos 1  c-state-old-cpp-beg nil  c-state-old-cpp-end nil  
> c-parse-state-point 16335)
> c-parse-state inconsistency at 15885: using cache: (15636 15181 (13849 . 
> 15141)), from scratch: (15636 (15303 . 15493) 15181 (13849 . 15141))

I think the following patch should fix that glitch.  I've also taken the
opportunity to simplify things a little (part of the global state was
being passed needlessly as a parameter) and to rename some variables for
more consistency.

Would you try this out and confirm it works, as usual, please.

However, this isn't the end of the story - 

(i) Start your test case in rwtransfer.c, and M-v until the top of the
  file.  (This shouldn't display any inconsistency messages)
(ii) M-x goto-char <ret> 20001 <ret>.  This should go to EOL 671, just
  after a "}".
(iii) Type <space> }.  (Two characters)
(iv) C-v, possibly twice.

This displays a message something like:
    c-parse-state inconsistency at 21070: using cache: ((20458 . 20935)),
    from scratch: ((20838 . 20877))
, together with a state dump.

This bug isn't a new one, but I've just come across it.  I'll be working
on it in the meantime.

Here's the patch, based on the savannah emacs-24 branch (which should be
identical to the trunk):



=== modified file 'lisp/progmodes/cc-engine.el'
*** lisp/progmodes/cc-engine.el 2013-01-09 21:33:00 +0000
--- lisp/progmodes/cc-engine.el 2013-01-23 13:36:33 +0000
***************
*** 2545,2558 ****
    ;;
    ;; The return value is a list, one of the following:
    ;;
!   ;; o - ('forward CACHE-POS START-POINT) - scan forward from START-POINT,
!   ;;                                        which is not less than CACHE-POS.
!   ;; o - ('backward CACHE-POS nil) - scan backwards (from HERE).
!   ;; o - ('BOD nil START-POINT) - scan forwards from START-POINT, which is at 
the
    ;;   top level.
!   ;; o - ('IN-LIT nil nil) - point is inside the literal containing point-min.
!   ;; , where CACHE-POS is the highest position recorded in `c-state-cache' at
!   ;; or below HERE.
    (let ((cache-pos (c-get-cache-scan-pos here))       ; highest position 
below HERE in cache (or 1)
        BOD-pos             ; position of 2nd BOD before HERE.
        strategy            ; 'forward, 'backward, 'BOD, or 'IN-LIT.
--- 2545,2556 ----
    ;;
    ;; The return value is a list, one of the following:
    ;;
!   ;; o - ('forward START-POINT) - scan forward from START-POINT,
!   ;;   which is not less than the highest position in `c-state-cache' below 
here.
!   ;; o - ('backward nil) - scan backwards (from HERE).
!   ;; o - ('BOD START-POINT) - scan forwards from START-POINT, which is at the
    ;;   top level.
!   ;; o - ('IN-LIT nil) - point is inside the literal containing point-min.
    (let ((cache-pos (c-get-cache-scan-pos here))       ; highest position 
below HERE in cache (or 1)
        BOD-pos             ; position of 2nd BOD before HERE.
        strategy            ; 'forward, 'backward, 'BOD, or 'IN-LIT.
***************
*** 2590,2596 ****
  
      (list
       strategy
-      (and (memq strategy '(forward backward)) cache-pos)
       (and (memq strategy '(forward BOD)) start-point))))
  
  
--- 2588,2593 ----
***************
*** 2657,2663 ****
    ;; reduce the time wasted in repeated fruitless searches in brace deserts.
    (save-excursion
      (save-restriction
!       (let* (new-cons
             (cache-pos (c-state-cache-top-lparen)) ; might be nil.
             (macro-start-or-from
              (progn (goto-char from)
--- 2654,2661 ----
    ;; reduce the time wasted in repeated fruitless searches in brace deserts.
    (save-excursion
      (save-restriction
!       (let* ((here (point-max))
!            new-cons
             (cache-pos (c-state-cache-top-lparen)) ; might be nil.
             (macro-start-or-from
              (progn (goto-char from)
***************
*** 2692,2697 ****
--- 2690,2696 ----
                ;; search bound, even though the algorithm below would skip
                ;; over the new paren pair.
                (cache-lim (and cache-pos (< cache-pos from) cache-pos)))
+           (widen)
            (narrow-to-region
                (cond
                 ((and desert-lim cache-lim)
***************
*** 2711,2726 ****
                  (while
                      (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; 
might signal
                           (setq bra (scan-lists ce -1 1)) ; back past (/[/{; 
might signal
!                          (or (> ce upper-lim)
!                              (not (eq (char-after bra) ?\{))
!                              (and (goto-char bra)
!                                   (c-beginning-of-macro)
!                                   (< (point) macro-start-or-from))))))
                (and ce (< ce bra)))
            (setq bra ce))      ; If we just backed over an unbalanced closing
                                        ; brace, ignore it.
  
!         (if (and ce (< bra ce) (eq (char-after bra) ?\{))
              ;; We've found the desired brace-pair.
              (progn
                (setq new-cons (cons bra (1+ ce)))
--- 2710,2727 ----
                  (while
                      (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; 
might signal
                           (setq bra (scan-lists ce -1 1)) ; back past (/[/{; 
might signal
!                          (or (> bra here) ;(> ce here)
!                              (and
!                               (< ce here)
!                               (or (not (eq (char-after bra) ?\{))
!                                   (and (goto-char bra)
!                                        (c-beginning-of-macro)
!                                        (< (point) macro-start-or-from))))))))
                (and ce (< ce bra)))
            (setq bra ce))      ; If we just backed over an unbalanced closing
                                        ; brace, ignore it.
  
!         (if (and ce (< ce here) (< bra ce) (eq (char-after bra) ?\{))
              ;; We've found the desired brace-pair.
              (progn
                (setq new-cons (cons bra (1+ ce)))
***************
*** 2734,2740 ****
                 (t (setq c-state-cache (cons new-cons c-state-cache)))))
  
            ;; We haven't found a brace pair.  Record this in the cache.
!           (setq c-state-brace-pair-desert (cons cache-pos from))))))))
  
  (defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here)
    ;; If BRA+1 is nil, do nothing.  Otherwise, BRA+1 is the buffer position
--- 2735,2745 ----
                 (t (setq c-state-cache (cons new-cons c-state-cache)))))
  
            ;; We haven't found a brace pair.  Record this in the cache.
!           (setq c-state-brace-pair-desert
!                 (cons (if (and ce (< bra ce) (> ce here)) ; {..} straddling 
HERE?
!                           bra
!                         (point-min))
!                       (min here from)))))))))
  
  (defsubst c-state-push-any-brace-pair (bra+1 macro-start-or-here)
    ;; If BRA+1 is nil, do nothing.  Otherwise, BRA+1 is the buffer position
***************
*** 2852,2870 ****
         (paren+1)
         (t from)))))
  
! (defun c-remove-stale-state-cache (good-pos pps-point)
    ;; Remove stale entries from the `c-cache-state', i.e. those which will
    ;; not be in it when it is amended for position (point-max).
    ;; Additionally, the "outermost" open-brace entry before (point-max)
    ;; will be converted to a cons if the matching close-brace is scanned.
    ;;
!   ;; GOOD-POS is a "maximal" "safe position" - there must be no open
!   ;; parens/braces/brackets between GOOD-POS and (point-max).
    ;;
    ;; As a second thing, calculate the result of parse-partial-sexp at
!   ;; PPS-POINT, w.r.t. GOOD-POS.  The motivation here is that
    ;; `c-state-cache-good-pos' may become PPS-POINT, but the caller may need to
!   ;; adjust it to get outside a string/comment.  (Sorry about this!  The code
    ;; needs to be FAST).
    ;;
    ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where
--- 2857,2875 ----
         (paren+1)
         (t from)))))
  
! (defun c-remove-stale-state-cache (start-point pps-point)
    ;; Remove stale entries from the `c-cache-state', i.e. those which will
    ;; not be in it when it is amended for position (point-max).
    ;; Additionally, the "outermost" open-brace entry before (point-max)
    ;; will be converted to a cons if the matching close-brace is scanned.
    ;;
!   ;; START-POINT is a "maximal" "safe position" - there must be no open
!   ;; parens/braces/brackets between START-POINT and (point-max).
    ;;
    ;; As a second thing, calculate the result of parse-partial-sexp at
!   ;; PPS-POINT, w.r.t. START-POINT.  The motivation here is that
    ;; `c-state-cache-good-pos' may become PPS-POINT, but the caller may need to
!   ;; adjust it to get outside a string/comment.        (Sorry about this!  
The code
    ;; needs to be FAST).
    ;;
    ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where
***************
*** 2872,2878 ****
    ;;   to be good (we aim for this to be as high as possible);
    ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
    ;;   preceding POS which needs to be recorded in `c-state-cache'.  It is a
!   ;;   position to scan backwards from.
    ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
    (save-restriction
      (narrow-to-region 1 (point-max))
--- 2877,2885 ----
    ;;   to be good (we aim for this to be as high as possible);
    ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
    ;;   preceding POS which needs to be recorded in `c-state-cache'.  It is a
!   ;;   position to scan backwards from.  It is the position of the "{" of the
!   ;;   last element to be removed from `c-state-cache', when that elt is a
!   ;;   cons, otherwise nil.
    ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
    (save-restriction
      (narrow-to-region 1 (point-max))
***************
*** 2882,2902 ****
                (goto-char (point-max))
                (and (c-beginning-of-macro)
                     (point))))
!            (good-pos-actual-macro-start ; Start of macro containing good-pos
!                                       ; or nil
!             (and (< good-pos (point-max))
                   (save-excursion
!                    (goto-char good-pos)
                     (and (c-beginning-of-macro)
                          (point)))))
!            (good-pos-actual-macro-end ; End of this macro, (maybe
                                        ; (point-max)), or nil.
!             (and good-pos-actual-macro-start
                   (save-excursion
!                    (goto-char good-pos-actual-macro-start)
                     (c-end-of-macro)
                     (point))))
!            pps-state                  ; Will be 9 or 10 elements long.
             pos
             upper-lim     ; ,beyond which `c-state-cache' entries are removed
             scan-back-pos
--- 2889,2909 ----
                (goto-char (point-max))
                (and (c-beginning-of-macro)
                     (point))))
!            (start-point-actual-macro-start ; Start of macro containing
!                                            ; start-point or nil
!             (and (< start-point (point-max))
                   (save-excursion
!                    (goto-char start-point)
                     (and (c-beginning-of-macro)
                          (point)))))
!            (start-point-actual-macro-end ; End of this macro, (maybe
                                        ; (point-max)), or nil.
!             (and start-point-actual-macro-start
                   (save-excursion
!                    (goto-char start-point-actual-macro-start)
                     (c-end-of-macro)
                     (point))))
!            pps-state                  ; Will be 9 or 10 elements long.
             pos
             upper-lim     ; ,beyond which `c-state-cache' entries are removed
             scan-back-pos
***************
*** 2926,2940 ****
        ;; The next loop jumps forward out of a nested level of parens each
        ;; time round; the corresponding elements in `c-state-cache' are
        ;; removed.  `pos' is just after the brace-pair or the open paren at
!       ;; (car c-state-cache).  There can be no open parens/braces/brackets
!       ;; between `good-pos'/`good-pos-actual-macro-start' and (point-max),
        ;; due to the interface spec to this function.
!       (setq pos (if (and good-pos-actual-macro-end
!                          (not (eq good-pos-actual-macro-start
                                    in-macro-start)))
!                     (1+ good-pos-actual-macro-end) ; get outside the macro as
                                        ; marked by a `category' text property.
!                   good-pos))
        (goto-char pos)
        (while (and c-state-cache
                    (< (point) (point-max)))
--- 2933,2947 ----
        ;; The next loop jumps forward out of a nested level of parens each
        ;; time round; the corresponding elements in `c-state-cache' are
        ;; removed.  `pos' is just after the brace-pair or the open paren at
!       ;; (car c-state-cache).  There can be no open parens/braces/brackets
!       ;; between `start-point'/`start-point-actual-macro-start' and 
(point-max),
        ;; due to the interface spec to this function.
!       (setq pos (if (and start-point-actual-macro-end
!                          (not (eq start-point-actual-macro-start
                                    in-macro-start)))
!                     (1+ start-point-actual-macro-end) ; get outside the macro 
as
                                        ; marked by a `category' text property.
!                   start-point))
        (goto-char pos)
        (while (and c-state-cache
                    (< (point) (point-max)))
***************
*** 2993,3006 ****
  
        (list pos scan-back-pos pps-state)))))
  
! (defun c-remove-stale-state-cache-backwards (here cache-pos)
    ;; Strip stale elements of `c-state-cache' by moving backwards through the
    ;; buffer, and inform the caller of the scenario detected.
    ;;
    ;; HERE is the position we're setting `c-state-cache' for.
!   ;; CACHE-POS is just after the latest recorded position in `c-state-cache'
!   ;;   before HERE, or a position at or near point-min which isn't in a
!   ;;   literal.
    ;;
    ;; This function must only be called only when (> `c-state-cache-good-pos'
    ;; HERE).  Usually the gap between CACHE-POS and HERE is large.  It is thus
--- 3000,3013 ----
  
        (list pos scan-back-pos pps-state)))))
  
! (defun c-remove-stale-state-cache-backwards (here)
    ;; Strip stale elements of `c-state-cache' by moving backwards through the
    ;; buffer, and inform the caller of the scenario detected.
    ;;
    ;; HERE is the position we're setting `c-state-cache' for.
!   ;; CACHE-POS (a locally bound variable) is just after the latest recorded
!   ;;   position in `c-state-cache' before HERE, or a position at or near
!   ;;   point-min which isn't in a literal.
    ;;
    ;; This function must only be called only when (> `c-state-cache-good-pos'
    ;; HERE).  Usually the gap between CACHE-POS and HERE is large.  It is thus
***************
*** 3023,3032 ****
    ;; The comments in this defun use "paren" to mean parenthesis or square
    ;; bracket (as contrasted with a brace), and "(" and ")" likewise.
    ;;
!   ;;    .   {..} (..) (..)  ( .. {   }  ) (...)    ( ....          .  ..)
!   ;;    |                   |       |   |     |                    |
!   ;;    CP                  E      here D     C                   good
!   (let ((pos c-state-cache-good-pos)
        pa ren         ; positions of "(" and ")"
        dropped-cons ; whether the last element dropped from `c-state-cache'
                     ; was a cons (representing a brace-pair)
--- 3030,3040 ----
    ;; The comments in this defun use "paren" to mean parenthesis or square
    ;; bracket (as contrasted with a brace), and "(" and ")" likewise.
    ;;
!   ;;  .   {..} (..) (..)  ( .. {   }  ) (...)    ( ....          .  ..)
!   ;;  |                   |       |   |     |                    |
!   ;;  CP                  E      here D     C                   good
!   (let ((cache-pos (c-get-cache-scan-pos here))       ; highest position 
below HERE in cache (or 1)
!       (pos c-state-cache-good-pos)
        pa ren         ; positions of "(" and ")"
        dropped-cons ; whether the last element dropped from `c-state-cache'
                     ; was a cons (representing a brace-pair)
***************
*** 3263,3269 ****
         cache-pos           ; highest position below HERE already existing in
                             ; cache (or 1).
         good-pos
!        start-point
         bopl-state
         res
         scan-backward-pos scan-forward-p) ; used for 'backward.
--- 3271,3278 ----
         cache-pos           ; highest position below HERE already existing in
                             ; cache (or 1).
         good-pos
!        start-point ; (when scanning forward) a place below HERE where there
!                    ; are no open parens/braces between it and HERE.
         bopl-state
         res
         scan-backward-pos scan-forward-p) ; used for 'backward.
***************
*** 3274,3281 ****
      ;; Strategy?
      (setq res (c-parse-state-get-strategy here c-state-cache-good-pos)
          strategy (car res)
!         cache-pos (cadr res)
!         start-point (nth 2 res))
  
      (when (eq strategy 'BOD)
        (setq c-state-cache nil
--- 3283,3289 ----
      ;; Strategy?
      (setq res (c-parse-state-get-strategy here c-state-cache-good-pos)
          strategy (car res)
!         start-point (cadr res))
  
      (when (eq strategy 'BOD)
        (setq c-state-cache nil
***************
*** 3302,3308 ****
                good-pos)))
  
         ((eq strategy 'backward)
!       (setq res (c-remove-stale-state-cache-backwards here cache-pos)
              good-pos (car res)
              scan-backward-pos (cadr res)
              scan-forward-p (car (cddr res)))
--- 3310,3316 ----
                good-pos)))
  
         ((eq strategy 'backward)
!       (setq res (c-remove-stale-state-cache-backwards here)
              good-pos (car res)
              scan-backward-pos (cadr res)
              scan-forward-p (car (cddr res)))



> -- 
> Michael Welsh Duggan
> (mwd@cert.org)

-- 
Alan Mackenzie (Nuremberg, Germany).





reply via email to

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