diff options
| author | Alan Mackenzie | 2012-11-21 20:41:03 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2012-11-21 20:41:03 +0000 |
| commit | b03aabdac594c3c6fd587ad4927bc4187fa12c2d (patch) | |
| tree | abd267edc2b04a9ca859bc6bb5c160a5f4132316 | |
| parent | cb5867b1f8af39ffd70767fc06fd364bca67e968 (diff) | |
| download | emacs-b03aabdac594c3c6fd587ad4927bc4187fa12c2d.tar.gz emacs-b03aabdac594c3c6fd587ad4927bc4187fa12c2d.zip | |
Fix bugs in the CC Mode state cache. Enhance a debugging mechanism.
| -rw-r--r-- | lisp/ChangeLog | 17 | ||||
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 53 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 7 |
3 files changed, 65 insertions, 12 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8502cd477e9..e60e9b49043 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,20 @@ | |||
| 1 | 2012-11-21 Alan Mackenzie <acm@muc.de> | ||
| 2 | |||
| 3 | Fix bugs in the state cache. Enhance a debugging mechanism. | ||
| 4 | * progmodes/cc-engine.el (c-parse-state-get-strategy): Don't use | ||
| 5 | "brace at column zero" strategy for C++. | ||
| 6 | (c-append-lower-brace-pair-to-state-cache): Repair algorithm. | ||
| 7 | (c-parse-state-point): New variable. | ||
| 8 | (c-record-parse-state-state): Record old parse state with | ||
| 9 | `copy-tree'. Record previous value of point. | ||
| 10 | (c-debug-parse-state-double-cons): New debugging function. | ||
| 11 | (c-debug-parse-state): Call the above new function. | ||
| 12 | (c-toggle-parse-state-debug): Output a confirmatory message. | ||
| 13 | |||
| 14 | * progmodes/cc-mode.el (c-before-change, c-after-change): Call | ||
| 15 | c-invalidate-state-cache from `c-before-change' instead of | ||
| 16 | `c-after-change'. | ||
| 17 | |||
| 1 | 2012-11-20 Daniel Colascione <dancol@dancol.org> | 18 | 2012-11-20 Daniel Colascione <dancol@dancol.org> |
| 2 | 19 | ||
| 3 | * term/w32-win.el (cygwin-convert-path-from-windows): Accomodate | 20 | * term/w32-win.el (cygwin-convert-path-from-windows): Accomodate |
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 2aa04cb2b0b..10355451480 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -2561,8 +2561,11 @@ comment at the start of cc-engine.el for more info." | |||
| 2561 | start-point cache-pos))) | 2561 | start-point cache-pos))) |
| 2562 | 2562 | ||
| 2563 | ;; Might we be better off starting from the top level, two defuns back, | 2563 | ;; Might we be better off starting from the top level, two defuns back, |
| 2564 | ;; instead? | 2564 | ;; instead? This heuristic no longer works well in C++, where |
| 2565 | (when (> how-far c-state-cache-too-far) | 2565 | ;; declarations inside namespace brace blocks are frequently placed at |
| 2566 | ;; column zero. | ||
| 2567 | (when (and (not (c-major-mode-is 'c++-mode)) | ||
| 2568 | (> how-far c-state-cache-too-far)) | ||
| 2566 | (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! | 2569 | (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! |
| 2567 | (if (< (- here BOD-pos) how-far) | 2570 | (if (< (- here BOD-pos) how-far) |
| 2568 | (setq strategy 'BOD | 2571 | (setq strategy 'BOD |
| @@ -2649,17 +2652,20 @@ comment at the start of cc-engine.el for more info." | |||
| 2649 | ;; If we're essentially repeating a fruitless search, just give up. | 2652 | ;; If we're essentially repeating a fruitless search, just give up. |
| 2650 | (unless (and c-state-brace-pair-desert | 2653 | (unless (and c-state-brace-pair-desert |
| 2651 | (eq cache-pos (car c-state-brace-pair-desert)) | 2654 | (eq cache-pos (car c-state-brace-pair-desert)) |
| 2655 | (or (null (car c-state-brace-pair-desert)) | ||
| 2656 | (> from (car c-state-brace-pair-desert))) | ||
| 2652 | (<= from (cdr c-state-brace-pair-desert))) | 2657 | (<= from (cdr c-state-brace-pair-desert))) |
| 2653 | ;; DESERT-LIM. Only search what we absolutely need to, | 2658 | ;; DESERT-LIM. Avoid repeated searching through the cached desert. |
| 2654 | (let ((desert-lim | 2659 | (let ((desert-lim |
| 2655 | (and c-state-brace-pair-desert | 2660 | (and c-state-brace-pair-desert |
| 2656 | (eq cache-pos (car c-state-brace-pair-desert)) | 2661 | (eq cache-pos (car c-state-brace-pair-desert)) |
| 2662 | (>= from (cdr c-state-brace-pair-desert)) | ||
| 2657 | (cdr c-state-brace-pair-desert))) | 2663 | (cdr c-state-brace-pair-desert))) |
| 2658 | ;; CACHE-LIM. This limit will be necessary when an opening | 2664 | ;; CACHE-LIM. This limit will be necessary when an opening |
| 2659 | ;; paren at `cache-pos' has just had its matching close paren | 2665 | ;; paren at `cache-pos' has just had its matching close paren |
| 2660 | ;; inserted. `cache-pos' continues to be a search bound, even | 2666 | ;; inserted into the buffer. `cache-pos' continues to be a |
| 2661 | ;; though the algorithm below would skip over the new paren | 2667 | ;; search bound, even though the algorithm below would skip |
| 2662 | ;; pair. | 2668 | ;; over the new paren pair. |
| 2663 | (cache-lim (and cache-pos (< cache-pos from) cache-pos))) | 2669 | (cache-lim (and cache-pos (< cache-pos from) cache-pos))) |
| 2664 | (narrow-to-region | 2670 | (narrow-to-region |
| 2665 | (cond | 2671 | (cond |
| @@ -3342,12 +3348,18 @@ comment at the start of cc-engine.el for more info." | |||
| 3342 | (fset 'c-real-parse-state (symbol-function 'c-parse-state))) | 3348 | (fset 'c-real-parse-state (symbol-function 'c-parse-state))) |
| 3343 | (cc-bytecomp-defun c-real-parse-state) | 3349 | (cc-bytecomp-defun c-real-parse-state) |
| 3344 | 3350 | ||
| 3351 | (defvar c-parse-state-point nil) | ||
| 3345 | (defvar c-parse-state-state nil) | 3352 | (defvar c-parse-state-state nil) |
| 3346 | (defun c-record-parse-state-state () | 3353 | (defun c-record-parse-state-state () |
| 3354 | (setq c-parse-state-point (point)) | ||
| 3347 | (setq c-parse-state-state | 3355 | (setq c-parse-state-state |
| 3348 | (mapcar | 3356 | (mapcar |
| 3349 | (lambda (arg) | 3357 | (lambda (arg) |
| 3350 | (cons arg (symbol-value arg))) | 3358 | (let ((val (symbol-value arg))) |
| 3359 | (cons arg | ||
| 3360 | (if (consp val) | ||
| 3361 | (copy-tree val) | ||
| 3362 | val)))) | ||
| 3351 | '(c-state-cache | 3363 | '(c-state-cache |
| 3352 | c-state-cache-good-pos | 3364 | c-state-cache-good-pos |
| 3353 | c-state-nonlit-pos-cache | 3365 | c-state-nonlit-pos-cache |
| @@ -3360,7 +3372,8 @@ comment at the start of cc-engine.el for more info." | |||
| 3360 | c-state-point-min-lit-start | 3372 | c-state-point-min-lit-start |
| 3361 | c-state-min-scan-pos | 3373 | c-state-min-scan-pos |
| 3362 | c-state-old-cpp-beg | 3374 | c-state-old-cpp-beg |
| 3363 | c-state-old-cpp-end)))) | 3375 | c-state-old-cpp-end |
| 3376 | c-parse-state-point)))) | ||
| 3364 | (defun c-replay-parse-state-state () | 3377 | (defun c-replay-parse-state-state () |
| 3365 | (message | 3378 | (message |
| 3366 | (concat "(setq " | 3379 | (concat "(setq " |
| @@ -3370,6 +3383,16 @@ comment at the start of cc-engine.el for more info." | |||
| 3370 | c-parse-state-state " ") | 3383 | c-parse-state-state " ") |
| 3371 | ")"))) | 3384 | ")"))) |
| 3372 | 3385 | ||
| 3386 | (defun c-debug-parse-state-double-cons (state) | ||
| 3387 | (let (state-car conses-not-ok) | ||
| 3388 | (while state | ||
| 3389 | (setq state-car (car state) | ||
| 3390 | state (cdr state)) | ||
| 3391 | (if (and (consp state-car) | ||
| 3392 | (consp (car state))) | ||
| 3393 | (setq conses-not-ok t))) | ||
| 3394 | conses-not-ok)) | ||
| 3395 | |||
| 3373 | (defun c-debug-parse-state () | 3396 | (defun c-debug-parse-state () |
| 3374 | (let ((here (point)) (res1 (c-real-parse-state)) res2) | 3397 | (let ((here (point)) (res1 (c-real-parse-state)) res2) |
| 3375 | (let ((c-state-cache nil) | 3398 | (let ((c-state-cache nil) |
| @@ -3402,8 +3425,16 @@ comment at the start of cc-engine.el for more info." | |||
| 3402 | here res1 res2) | 3425 | here res1 res2) |
| 3403 | (message "Old state:") | 3426 | (message "Old state:") |
| 3404 | (c-replay-parse-state-state)) | 3427 | (c-replay-parse-state-state)) |
| 3428 | |||
| 3429 | (when (c-debug-parse-state-double-cons res1) | ||
| 3430 | (message "c-parse-state INVALIDITY at %s: %s" | ||
| 3431 | here res1) | ||
| 3432 | (message "Old state:") | ||
| 3433 | (c-replay-parse-state-state)) | ||
| 3434 | |||
| 3405 | (c-record-parse-state-state) | 3435 | (c-record-parse-state-state) |
| 3406 | res1)) | 3436 | res2 ; res1 correct a cascading series of errors ASAP |
| 3437 | )) | ||
| 3407 | 3438 | ||
| 3408 | (defun c-toggle-parse-state-debug (&optional arg) | 3439 | (defun c-toggle-parse-state-debug (&optional arg) |
| 3409 | (interactive "P") | 3440 | (interactive "P") |
| @@ -3411,7 +3442,9 @@ comment at the start of cc-engine.el for more info." | |||
| 3411 | (fset 'c-parse-state (symbol-function (if c-debug-parse-state | 3442 | (fset 'c-parse-state (symbol-function (if c-debug-parse-state |
| 3412 | 'c-debug-parse-state | 3443 | 'c-debug-parse-state |
| 3413 | 'c-real-parse-state))) | 3444 | 'c-real-parse-state))) |
| 3414 | (c-keep-region-active)) | 3445 | (c-keep-region-active) |
| 3446 | (message "c-debug-parse-state %sabled" | ||
| 3447 | (if c-debug-parse-state "en" "dis"))) | ||
| 3415 | (when c-debug-parse-state | 3448 | (when c-debug-parse-state |
| 3416 | (c-toggle-parse-state-debug 1)) | 3449 | (c-toggle-parse-state-debug 1)) |
| 3417 | 3450 | ||
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 50eaebe4dec..91866278e28 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -1034,7 +1034,10 @@ Note that the style variables are always made local to the buffer." | |||
| 1034 | (mapc (lambda (fn) | 1034 | (mapc (lambda (fn) |
| 1035 | (funcall fn beg end)) | 1035 | (funcall fn beg end)) |
| 1036 | c-get-state-before-change-functions)) | 1036 | c-get-state-before-change-functions)) |
| 1037 | )))) | 1037 | ))) |
| 1038 | ;; The following must be done here rather than in `c-after-change' because | ||
| 1039 | ;; newly inserted parens would foul up the invalidation algorithm. | ||
| 1040 | (c-invalidate-state-cache beg)) | ||
| 1038 | 1041 | ||
| 1039 | (defvar c-in-after-change-fontification nil) | 1042 | (defvar c-in-after-change-fontification nil) |
| 1040 | (make-variable-buffer-local 'c-in-after-change-fontification) | 1043 | (make-variable-buffer-local 'c-in-after-change-fontification) |
| @@ -1082,7 +1085,7 @@ Note that the style variables are always made local to the buffer." | |||
| 1082 | 1085 | ||
| 1083 | (c-trim-found-types beg end old-len) ; maybe we don't need all of these. | 1086 | (c-trim-found-types beg end old-len) ; maybe we don't need all of these. |
| 1084 | (c-invalidate-sws-region-after beg end) | 1087 | (c-invalidate-sws-region-after beg end) |
| 1085 | (c-invalidate-state-cache beg) | 1088 | ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'. |
| 1086 | (c-invalidate-find-decl-cache beg) | 1089 | (c-invalidate-find-decl-cache beg) |
| 1087 | 1090 | ||
| 1088 | (when c-recognize-<>-arglists | 1091 | (when c-recognize-<>-arglists |