Spelling fixes.
[bpt/emacs.git] / lisp / progmodes / cc-engine.el
index 0eec54f..5ec0ab0 100644 (file)
@@ -705,10 +705,13 @@ comment at the start of cc-engine.el for more info."
        ;; The last position where a label is possible provided the
        ;; statement started there.  It's nil as long as no invalid
        ;; label content has been found (according to
-       ;; `c-nonlabel-token-key'.  It's `start' if no valid label
+       ;; `c-nonlabel-token-key').  It's `start' if no valid label
        ;; content was found in the label.  Note that we might still
        ;; regard it a label if it starts with `c-label-kwds'.
        label-good-pos
+       ;; Putative positions of the components of a bitfield declaration,
+       ;; e.g. "int foo : NUM_FOO_BITS ;"
+       bitfield-type-pos bitfield-id-pos bitfield-size-pos
        ;; Symbol just scanned back over (e.g. 'while or 'boundary).
        ;; See above.
        sym
@@ -765,13 +768,22 @@ comment at the start of cc-engine.el for more info."
            ;; Record this as the first token if not starting inside it.
            (setq tok start))
 
-        ;; The following while loop goes back one sexp (balanced parens,
-        ;; etc. with contents, or symbol or suchlike) each iteration.  This
-        ;; movement is accomplished with a call to scan-sexps approx 130 lines
-        ;; below.
+
+       ;; The following while loop goes back one sexp (balanced parens,
+       ;; etc. with contents, or symbol or suchlike) each iteration.  This
+       ;; movement is accomplished with a call to c-backward-sexp approx 170
+       ;; lines below.
+       ;;
+       ;; The loop is exited only by throwing nil to the (catch 'loop ...):
+       ;; 1. On reaching the start of a macro;
+       ;; 2. On having passed a stmt boundary with the PDA stack empty;
+       ;; 3. On reaching the start of an Objective C method def;
+       ;; 4. From macro `c-bos-pop-state'; when the stack is empty;
+       ;; 5. From macro `c-bos-pop-state-and-retry' when the stack is empty.
        (while
            (catch 'loop ;; Throw nil to break, non-nil to continue.
              (cond
+              ;; Are we in a macro, just after the opening #?
               ((save-excursion
                  (and macro-start      ; Always NIL for AWK.
                       (progn (skip-chars-backward " \t")
@@ -792,7 +804,7 @@ comment at the start of cc-engine.el for more info."
                  (setq pos saved
                        ret 'macro
                        ignore-labels t))
-               (throw 'loop nil))
+               (throw 'loop nil))      ; 1. Start of macro.
 
               ;; Do a round through the automaton if we've just passed a
               ;; statement boundary or passed a "while"-like token.
@@ -801,7 +813,7 @@ comment at the start of cc-engine.el for more info."
                         (setq sym (intern (match-string 1)))))
 
                (when (and (< pos start) (null stack))
-                 (throw 'loop nil))
+                 (throw 'loop nil))    ; 2. Statement boundary.
 
                ;; The PDA state handling.
                 ;;
@@ -918,19 +930,14 @@ comment at the start of cc-engine.el for more info."
                 ;; HERE IS THE SINGLE PLACE INSIDE THE PDA LOOP WHERE WE MOVE
                ;; BACKWARDS THROUGH THE SOURCE.
 
-               ;; This is typically fast with the caching done by
-               ;; c-(backward|forward)-sws.
                (c-backward-syntactic-ws)
-
                (let ((before-sws-pos (point))
-                     ;; Set as long as we have to continue jumping by sexps.
-                     ;; It's the position to use as end in the next round.
-                     sexp-loop-continue-pos
                      ;; The end position of the area to search for statement
                      ;; barriers in this round.
-                     (sexp-loop-end-pos pos))
+                     (maybe-after-boundary-pos pos))
 
-                 ;; The following while goes back one sexp per iteration.
+                 ;; Go back over exactly one logical sexp, taking proper
+                 ;; account of macros and escaped EOLs.
                  (while
                      (progn
                        (unless (c-safe (c-backward-sexp) t)
@@ -938,81 +945,87 @@ comment at the start of cc-engine.el for more info."
                          ;; stack won't be empty the code below will report a
                          ;; suitable error.
                          (throw 'loop nil))
-
-                       ;; Check if the sexp movement crossed a statement or
-                       ;; declaration boundary.  But first modify the point
-                       ;; so that `c-crosses-statement-barrier-p' only looks
-                       ;; at the non-sexp chars following the sexp.
-                       (save-excursion
-                         (when (setq
-                                boundary-pos
-                                (cond
-                                 ((if macro-start
-                                      nil
-                                    (save-excursion
-                                      (when (c-beginning-of-macro)
-                                        ;; Set continuation position in case
-                                        ;; `c-crosses-statement-barrier-p'
-                                        ;; doesn't detect anything below.
-                                        (setq sexp-loop-continue-pos (point)))))
-                                  ;; If the sexp movement took us into a
-                                  ;; macro then there were only some non-sexp
-                                  ;; chars after it.  Skip out of the macro
-                                  ;; to analyze them but not the non-sexp
-                                  ;; chars that might be inside the macro.
-                                  (c-end-of-macro)
-                                  (c-crosses-statement-barrier-p
-                                   (point) sexp-loop-end-pos))
-
-                                 ((and
-                                   (eq (char-after) ?{)
-                                   (not (c-looking-at-inexpr-block lim nil t)))
-                                  ;; Passed a block sexp.  That's a boundary
-                                  ;; alright.
-                                  (point))
-
-                                 ((looking-at "\\s\(")
-                                  ;; Passed some other paren.  Only analyze
-                                  ;; the non-sexp chars after it.
-                                  (goto-char (1+ (c-down-list-backward
-                                                  before-sws-pos)))
-                                  ;; We're at a valid token start position
-                                  ;; (outside the `save-excursion') if
-                                  ;; `c-crosses-statement-barrier-p' failed.
-                                  (c-crosses-statement-barrier-p
-                                   (point) sexp-loop-end-pos))
-
-                                 (t
-                                  ;; Passed a symbol sexp or line
-                                  ;; continuation.  It doesn't matter that
-                                  ;; it's included in the analyzed region.
-                                  (if (c-crosses-statement-barrier-p
-                                       (point) sexp-loop-end-pos)
-                                      t
-                                    ;; If it was a line continuation then we
-                                    ;; have to continue looping.
-                                    (if (looking-at "\\\\$")
-                                        (setq sexp-loop-continue-pos (point)))
-                                    nil))))
-
-                           (setq pptok ptok
-                                 ptok tok
-                                 tok boundary-pos
-                                 sym 'boundary)
-                           ;; Like a C "continue".  Analyze the next sexp.
-                           (throw 'loop t)))
-
-                       sexp-loop-continue-pos) ; End of "go back a sexp" loop condition.
-                   (goto-char sexp-loop-continue-pos)
-                   (setq sexp-loop-end-pos sexp-loop-continue-pos
-                         sexp-loop-continue-pos nil))))
+                       (cond
+                        ;; Have we moved into a macro?
+                        ((and (not macro-start)
+                              (c-beginning-of-macro))
+                         ;; Have we crossed a statement boundary?  If not,
+                         ;; keep going back until we find one or a "real" sexp.
+                         (and
+                          (save-excursion
+                            (c-end-of-macro)
+                            (not (c-crosses-statement-barrier-p
+                                  (point) maybe-after-boundary-pos)))
+                          (setq maybe-after-boundary-pos (point))))
+                        ;; Have we just gone back over an escaped NL?  This
+                        ;; doesn't count as a sexp.
+                        ((looking-at "\\\\$")))))
+
+                 ;; Have we crossed a statement boundary?
+                 (setq boundary-pos
+                       (cond
+                        ;; Are we at a macro beginning?
+                        ((and (not macro-start)
+                              c-opt-cpp-prefix
+                              (looking-at c-opt-cpp-prefix))
+                         (save-excursion
+                           (c-end-of-macro)
+                           (c-crosses-statement-barrier-p
+                            (point) maybe-after-boundary-pos)))
+                        ;; Just gone back over a brace block?
+                        ((and
+                          (eq (char-after) ?{)
+                          (not (c-looking-at-inexpr-block lim nil t)))
+                         (save-excursion
+                           (c-forward-sexp) (point)))
+                        ;; Just gone back over some paren block?
+                        ((looking-at "\\s\(")
+                         (save-excursion
+                           (goto-char (1+ (c-down-list-backward
+                                           before-sws-pos)))
+                           (c-crosses-statement-barrier-p
+                            (point) maybe-after-boundary-pos)))
+                        ;; Just gone back over an ordinary symbol of some sort?
+                        (t (c-crosses-statement-barrier-p
+                            (point) maybe-after-boundary-pos))))
+
+                 (when boundary-pos
+                   (setq pptok ptok
+                         ptok tok
+                         tok boundary-pos
+                         sym 'boundary)
+                   ;; Like a C "continue".  Analyze the next sexp.
+                   (throw 'loop t))))
 
              ;; ObjC method def?
              (when (and c-opt-method-key
                         (setq saved (c-in-method-def-p)))
                (setq pos saved
                      ignore-labels t)  ; Avoid the label check on exit.
-               (throw 'loop nil))
+               (throw 'loop nil))      ; 3. ObjC method def.
+
+             ;; Might we have a bitfield declaration, "<type> <id> : <size>"?
+             (if c-has-bitfields
+                 (cond
+                  ;; The : <size> and <id> fields?
+                  ((and (numberp c-maybe-labelp)
+                        (not bitfield-size-pos)
+                        (save-excursion
+                          (goto-char (or tok start))
+                          (not (looking-at c-keywords-regexp)))
+                        (not (looking-at c-keywords-regexp))
+                        (not (c-punctuation-in (point) c-maybe-labelp)))
+                   (setq bitfield-size-pos (or tok start)
+                         bitfield-id-pos (point)))
+                  ;; The <type> field?
+                  ((and bitfield-id-pos
+                        (not bitfield-type-pos))
+                   (if (and (looking-at c-symbol-key) ; Can only be an integer type.  :-)
+                            (not (looking-at c-not-primitive-type-keywords-regexp))
+                            (not (c-punctuation-in (point) tok)))
+                       (setq bitfield-type-pos (point))
+                     (setq bitfield-size-pos nil
+                           bitfield-id-pos nil)))))
 
              ;; Handle labels.
              (unless (eq ignore-labels t)
@@ -1022,7 +1035,12 @@ comment at the start of cc-engine.el for more info."
                  ;; (including a case label) or something like C++'s "public:"?
                  ;; A case label might use an expression rather than a token.
                  (setq after-case:-pos (or tok start))
-                 (if (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
+                 (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'"
+                         ;; Catch C++'s inheritance construct "class foo : bar".
+                         (save-excursion
+                           (and
+                            (c-safe (c-backward-sexp) t)
+                            (looking-at c-nonlabel-token-2-key))))
                      (setq c-maybe-labelp nil)
                    (if after-labels-pos ; Have we already encountered a label?
                        (if (not last-label-pos)
@@ -1044,7 +1062,9 @@ comment at the start of cc-engine.el for more info."
                    pptok ptok
                    ptok tok
                    tok (point)
-                   pos tok)))          ; Not nil (for the while loop).
+                   pos tok) ; always non-nil
+             )              ; end of (catch loop ....)
+         )                  ; end of sexp-at-a-time (while ....)
 
        ;; If the stack isn't empty there might be errors to report.
        (while stack
@@ -1067,6 +1087,7 @@ comment at the start of cc-engine.el for more info."
                   (eq c-maybe-labelp t)
                   (not (eq ret 'beginning))
                   after-labels-pos
+                  (not bitfield-type-pos) ; Bitfields take precedence over labels.
                   (or (not label-good-pos)
                       (<= label-good-pos pos)
                       (progn
@@ -1104,6 +1125,19 @@ comment at the start of cc-engine.el for more info."
       (goto-char pos)
       ret)))
 
+(defun c-punctuation-in (from to)
+  "Return non-nil if there is a non-comment non-macro punctuation character
+between FROM and TO.  FROM must not be in a string or comment.  The returned
+value is the position of the first such character."
+  (save-excursion
+    (goto-char from)
+    (let ((pos (point)))
+      (while (progn (skip-chars-forward c-symbol-chars to)
+                   (c-forward-syntactic-ws to)
+                   (> (point) pos))
+       (setq pos (point))))
+    (and (< (point) to) (point))))
+
 (defun c-crosses-statement-barrier-p (from to)
   "Return non-nil if buffer positions FROM to TO cross one or more
 statement or declaration boundaries.  The returned value is actually
@@ -1120,42 +1154,65 @@ the line.  If this virtual semicolon is _at_ from, the function recognizes it.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
-  (let ((skip-chars c-stmt-delim-chars)
-       lit-range)
-    (save-excursion
-      (catch 'done
-       (goto-char from)
-       (while (progn (skip-chars-forward skip-chars to)
-                     (< (point) to))
-         (cond
-          ((setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
-           (goto-char (cdr lit-range)))
-          ((eq (char-after) ?:)
-           (forward-char)
-           (if (and (eq (char-after) ?:)
-                    (< (point) to))
-               ;; Ignore scope operators.
-               (forward-char)
-             (setq c-maybe-labelp (1- (point)))))
-          ((eq (char-after) ??)
-           ;; A question mark.  Can't be a label, so stop
-           ;; looking for more : and ?.
-           (setq c-maybe-labelp nil
-                 skip-chars (substring c-stmt-delim-chars 0 -2)))
-          ((memq (char-after) '(?# ?\n ?\r)) ; A virtual semicolon?
-           (if (and (eq (char-before) ?\\) (memq (char-after) '(?\n ?\r)))
-               (backward-char))
-           (skip-chars-backward " \t" from)
-           (if (c-at-vsemi-p)
-               (throw 'done (point))
-             (forward-line)))
-          (t (throw 'done (point)))))
-       ;; In trailing space after an as yet undetected virtual semicolon?
-       (c-backward-syntactic-ws from)
-       (if (and (< (point) to)
-                (c-at-vsemi-p))
-           (point)
-         nil)))))
+  (let* ((skip-chars
+         ;; If the current language has CPP macros, insert # into skip-chars.
+         (if c-opt-cpp-symbol
+             (concat (substring c-stmt-delim-chars 0 1) ; "^"
+                     c-opt-cpp-symbol                   ; usually "#"
+                     (substring c-stmt-delim-chars 1))  ; e.g. ";{}?:"
+           c-stmt-delim-chars))
+        (non-skip-list
+         (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
+        lit-range vsemi-pos)
+    (save-restriction
+      (widen)
+      (save-excursion
+       (catch 'done
+         (goto-char from)
+         (while (progn (skip-chars-forward
+                        skip-chars
+                        (min to (c-point 'bonl)))
+                       (< (point) to))
+           (cond
+            ;; Virtual semicolon?
+            ((and (bolp)
+                  (save-excursion
+                    (progn
+                      (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
+                          (goto-char (car lit-range)))
+                      (c-backward-syntactic-ws) ; ? put a limit here, maybe?
+                      (setq vsemi-pos (point))
+                      (c-at-vsemi-p))))
+             (throw 'done vsemi-pos))
+            ;; In a string/comment?
+            ((setq lit-range (c-literal-limits))
+             (goto-char (cdr lit-range)))
+            ((eq (char-after) ?:)
+             (forward-char)
+             (if (and (eq (char-after) ?:)
+                      (< (point) to))
+                 ;; Ignore scope operators.
+                 (forward-char)
+               (setq c-maybe-labelp (1- (point)))))
+            ((eq (char-after) ??)
+             ;; A question mark.  Can't be a label, so stop
+             ;; looking for more : and ?.
+             (setq c-maybe-labelp nil
+                   skip-chars (substring c-stmt-delim-chars 0 -2)))
+            ;; At a CPP construct?
+            ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol)
+                  (save-excursion
+                    (forward-line 0)
+                    (looking-at c-opt-cpp-prefix)))
+             (c-end-of-macro))
+            ((memq (char-after) non-skip-list)
+             (throw 'done (point)))))
+         ;; In trailing space after an as yet undetected virtual semicolon?
+         (c-backward-syntactic-ws from)
+         (if (and (< (point) to)
+                  (c-at-vsemi-p))
+             (point)
+           nil))))))
 
 (defun c-at-statement-start-p ()
   "Return non-nil if the point is at the first token in a statement
@@ -1301,12 +1358,13 @@ This function does not do any hidden buffer changes."
       ;; same line.
       (re-search-forward "\\=\\s *[\n\r]" start t)
 
-      (if (if (forward-comment -1)
+      (if (if (let (open-paren-in-column-0-is-defun-start) (forward-comment -1))
              (if (eolp)
                  ;; If forward-comment above succeeded and we're at eol
                  ;; then the newline we moved over above didn't end a
                  ;; line comment, so we give it another go.
-                 (forward-comment -1)
+                 (let (open-paren-in-column-0-is-defun-start)
+                   (forward-comment -1))
                t))
 
          ;; Emacs <= 20 and XEmacs move back over the closer of a
@@ -1333,7 +1391,8 @@ comment at the start of cc-engine.el for more info."
            ;; return t when moving backwards at bob.
            (not (bobp))
 
-           (if (forward-comment -1)
+           (if (let (open-paren-in-column-0-is-defun-start)
+                 (forward-comment -1))
                (if (looking-at "\\*/")
                    ;; Emacs <= 20 and XEmacs move back over the
                    ;; closer of a block comment that lacks an opener.
@@ -1736,7 +1795,7 @@ comment at the start of cc-engine.el for more info."
        rung-is-marked simple-ws-beg cmt-skip-pos)
 
     ;; Skip simple horizontal ws and do a quick check on the preceding
-    ;; character to see if it's anying that can't end syntactic ws, so we can
+    ;; character to see if it's anything that can't end syntactic ws, so we can
     ;; bail out early in the majority of cases when there just are a few ws
     ;; chars.  Newlines are complicated in the backward direction, so we can't
     ;; skip over them.
@@ -1973,7 +2032,7 @@ comment at the start of cc-engine.el for more info."
 (defconst c-state-cache-too-far 5000)
 ;; A maximum comfortable scanning distance, e.g. between
 ;; `c-state-cache-good-pos' and "HERE" (where we call c-parse-state).  When
-;; this distance is exceeded, we take "emergency meausures", e.g. by clearing
+;; this distance is exceeded, we take "emergency measures", e.g. by clearing
 ;; the cache and starting again from point-min or a beginning of defun.  This
 ;; value can be tuned for efficiency or set to a lower value for testing.
 
@@ -2099,13 +2158,17 @@ comment at the start of cc-engine.el for more info."
       pos))
 
 (defsubst c-state-cache-non-literal-place (pos state)
-  ;; Return a position outside of a string/comment at or before POS.
+  ;; Return a position outside of a string/comment/macro at or before POS.
   ;; STATE is the parse-partial-sexp state at POS.
-  (if (or (nth 3 state)                        ; in a string?
-         (nth 4 state))                ; in a comment?
-      (nth 8 state)
-    pos))
-
+  (let ((res (if (or (nth 3 state)     ; in a string?
+                    (nth 4 state))     ; in a comment?
+                (nth 8 state)
+              pos)))
+    (save-excursion
+      (goto-char res)
+      (if (c-beginning-of-macro)
+         (point)
+       res))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Stuff to do with point-min, and coping with any literal there.
@@ -2239,7 +2302,7 @@ comment at the start of cc-engine.el for more info."
 ;; `c-parse-state', or nil.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; Defuns which analyse the buffer, yet don't change `c-state-cache'.
+;; Defuns which analyze the buffer, yet don't change `c-state-cache'.
 (defun c-get-fallback-scan-pos (here)
   ;; Return a start position for building `c-state-cache' from
   ;; scratch.  This will be at the top level, 2 defuns back.
@@ -2268,7 +2331,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; If there aren't enough opening paren/brace/brackets, return the position
   ;; of the outermost one found, or HERE- if there are none.  If there are no
-  ;; closeing p/b/bs between HERE+ and TOP, return HERE-.  HERE-/+ and TOP
+  ;; closing p/b/bs between HERE+ and TOP, return HERE-.  HERE-/+ and TOP
   ;; must not be inside literals.  Only the accessible portion of the buffer
   ;; will be scanned.
 
@@ -2301,7 +2364,7 @@ comment at the start of cc-engine.el for more info."
 
 (defun c-parse-state-get-strategy (here good-pos)
   ;; Determine the scanning strategy for adjusting `c-parse-state', attempting
-  ;; to minimise the amount of scanning.  HERE is the pertinent position in
+  ;; to minimize the amount of scanning.  HERE is the pertinent position in
   ;; the buffer, GOOD-POS is a position where `c-state-cache' (possibly with
   ;; its head trimmed) is known to be good, or nil if there is no such
   ;; position.
@@ -2421,7 +2484,7 @@ comment at the start of cc-engine.el for more info."
                     (<= from (cdr c-state-brace-pair-desert)))
          ;; Only search what we absolutely need to:
          (if (and c-state-brace-pair-desert
-                  (> from (cdr c-state-brace-pair-desert)))
+                  (eq cache-pos (car c-state-brace-pair-desert)))
              (narrow-to-region (cdr c-state-brace-pair-desert) (point-max)))
 
          ;; In the next pair of nested loops, the inner one moves back past a
@@ -2485,7 +2548,7 @@ comment at the start of cc-engine.el for more info."
                        c-state-cache)))
        ;; N.B.  This defsubst codes one method for the simple, normal case,
        ;; and a more sophisticated, slower way for the general case.  Don't
-       ;; eliminate this defsubst - it's a speed optimisation.
+       ;; eliminate this defsubst - it's a speed optimization.
        (c-append-lower-brace-pair-to-state-cache (1- bra+1)))))
 
 (defun c-append-to-state-cache (from)
@@ -2725,7 +2788,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; 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
-  ;; optimised to eliminate (or minimise) scanning between these two
+  ;; optimized to eliminate (or minimize) scanning between these two
   ;; positions.
   ;;
   ;; Return a three element list (GOOD-POS SCAN-BACK-POS FWD-FLAG), where:
@@ -2757,7 +2820,7 @@ comment at the start of cc-engine.el for more info."
                                        ; or `here' itself.
        here- here+                  ; start/end of macro around HERE, or HERE
        (here-bol (c-point 'bol here))
-       (too-far-back (max (- here c-state-cache-too-far) 1)))
+       (too-far-back (max (- here c-state-cache-too-far) (point-min))))
 
     ;; Remove completely irrelevant entries from `c-state-cache'.
     (while (and c-state-cache
@@ -2901,9 +2964,9 @@ comment at the start of cc-engine.el for more info."
            c-state-cache-good-pos nil
            c-state-min-scan-pos nil)
 
-;;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value below
-;;; `here'.  To maintain its consistency, we may need to insert a new brace
-;;; pair.
+    ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value
+    ;; below `here'.  To maintain its consistency, we may need to insert a new
+    ;; brace pair.
     (let ((here-bol (c-point 'bol here))
          too-high-pa             ; recorded {/(/[ next above here, or nil.
          dropped-cons            ; was the last removed element a brace pair?
@@ -3092,6 +3155,33 @@ comment at the start of cc-engine.el for more info."
 (unless (fboundp 'c-real-parse-state)
   (fset 'c-real-parse-state (symbol-function 'c-parse-state)))
 (cc-bytecomp-defun c-real-parse-state)
+
+(defvar c-parse-state-state nil)
+(defun c-record-parse-state-state ()
+  (setq c-parse-state-state
+       (mapcar
+        (lambda (arg)
+          (cons arg (symbol-value arg)))
+        '(c-state-cache
+          c-state-cache-good-pos
+          c-state-nonlit-pos-cache
+          c-state-nonlit-pos-cache-limit
+          c-state-brace-pair-desert
+          c-state-point-min
+          c-state-point-min-lit-type
+          c-state-point-min-lit-start
+          c-state-min-scan-pos
+          c-state-old-cpp-beg
+          c-state-old-cpp-end))))
+(defun c-replay-parse-state-state ()
+  (message
+   (concat "(setq "
+    (mapconcat
+     (lambda (arg)
+       (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg)))
+     c-parse-state-state "  ")
+    ")")))
+
 (defun c-debug-parse-state ()
   (let ((here (point)) (res1 (c-real-parse-state)) res2)
     (let ((c-state-cache nil)
@@ -3110,15 +3200,21 @@ comment at the start of cc-engine.el for more info."
       ;; The cache can actually go further back due to the ad-hoc way
       ;; the first paren is found, so try to whack off a bit of its
       ;; start before complaining.
-      (save-excursion
-       (goto-char (or (c-least-enclosing-brace res2) (point)))
-       (c-beginning-of-defun-1)
-       (while (not (or (bobp) (eq (char-after) ?{)))
-         (c-beginning-of-defun-1))
-       (unless (equal (c-whack-state-before (point) res1) res2)
-         (message (concat "c-parse-state inconsistency at %s: "
-                          "using cache: %s, from scratch: %s")
-                  here res1 res2))))
+      ;; (save-excursion
+      ;;       (goto-char (or (c-least-enclosing-brace res2) (point)))
+      ;;       (c-beginning-of-defun-1)
+      ;;       (while (not (or (bobp) (eq (char-after) ?{)))
+      ;;         (c-beginning-of-defun-1))
+      ;;       (unless (equal (c-whack-state-before (point) res1) res2)
+      ;;         (message (concat "c-parse-state inconsistency at %s: "
+      ;;                          "using cache: %s, from scratch: %s")
+      ;;                  here res1 res2)))
+      (message (concat "c-parse-state inconsistency at %s: "
+                      "using cache: %s, from scratch: %s")
+              here res1 res2)
+      (message "Old state:")
+      (c-replay-parse-state-state))
+    (c-record-parse-state-state)
     res1))
 
 (defun c-toggle-parse-state-debug (&optional arg)
@@ -3955,7 +4051,7 @@ comment at the start of cc-engine.el for more info."
                     ;; a relevant match.
                     (goto-char pos)
                     nil))))))
-            
+
          (> (point)
             (progn
               ;; Skip syntactic ws afterwards so that we don't stop at the
@@ -4123,9 +4219,9 @@ comment at the start of cc-engine.el for more info."
 ;; complicated anyway.  In this case, lim is only used to detect
 ;; cpp directives.
 ;;
-;; Note that there is a bug in Xemacs's buffer-syntactic-context when used in
+;; Note that there is a bug in XEmacs's buffer-syntactic-context when used in
 ;; conjunction with syntax-table-properties.  The bug is present in, e.g.,
-;; Xemacs 21.4.4.  It manifested itself thus:
+;; XEmacs 21.4.4.  It manifested itself thus:
 ;;
 ;; Starting with an empty AWK Mode buffer, type
 ;; /regexp/ {<C-j>
@@ -4137,9 +4233,9 @@ comment at the start of cc-engine.el for more info."
 ;; fails to take account of the change of the s-t property on the opening / to
 ;; "string", and reports that the { is within a string started by the second /.
 ;;
-;; The workaround for this is for the AWK Mode initialisation to switch the
+;; The workaround for this is for the AWK Mode initialization to switch the
 ;; defalias for c-in-literal to c-slow-in-literal.  This will slow down other
-;; cc-modes in Xemacs whenever an awk-buffer has been initialised.
+;; cc-modes in XEmacs whenever an awk-buffer has been initialized.
 ;;
 ;; (Alan Mackenzie, 2003/4/30).
 
@@ -4808,7 +4904,7 @@ comment at the start of cc-engine.el for more info."
            (setq cfd-prop-match nil))
 
        (when (/= cfd-macro-end 0)
-         ;; Restore limits if we did macro narrowment above.
+         ;; Restore limits if we did macro narrowing above.
          (narrow-to-region (point-min) cfd-buffer-end)))
 
       (goto-char cfd-continue-pos)
@@ -4956,7 +5052,7 @@ comment at the start of cc-engine.el for more info."
 ;; The strategy now (2010-01) adopted is to mark and unmark < and
 ;; > IN MATCHING PAIRS ONLY.  [Previously, they were marked
 ;; individually when their context so indicated.  This gave rise to
-;; intractible problems when one of a matching pair was deleted, or
+;; intractable problems when one of a matching pair was deleted, or
 ;; pulled into a literal.]
 ;;
 ;; At each buffer change, the syntax-table properties are removed in a
@@ -5869,7 +5965,7 @@ comment at the start of cc-engine.el for more info."
   ;;     `*-font-lock-extra-types');
   ;;   o - 'prefix if it's a known prefix of a type;
   ;;   o - 'found if it's a type that matches one in `c-found-types';
-  ;;   o - 'maybe if it's an identfier that might be a type; or
+  ;;   o - 'maybe if it's an identifier that might be a type; or
   ;;   o -  nil if it can't be a type (the point isn't moved then).
   ;;
   ;; The point is assumed to be at the beginning of a token.
@@ -6181,7 +6277,7 @@ comment at the start of cc-engine.el for more info."
   ;;      car ^                                     ^ point
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
-  ;; 
+  ;;
   ;;   The cdr of the return value is non-nil when a
   ;;   `c-typedef-decl-kwds' specifier is found in the declaration.
   ;;   Specifically it is a dotted pair (A . B) where B is t when a
@@ -6189,7 +6285,7 @@ comment at the start of cc-engine.el for more info."
   ;;   other `c-typedef-decl-kwds' (e.g. class, struct, enum)
   ;;   specifier is present.  I.e., (some of) the declared
   ;;   identifier(s) are types.
-  ;; 
+  ;;
   ;; If a cast is parsed:
   ;;
   ;;   The point is left at the first token after the closing paren of
@@ -6290,7 +6386,9 @@ comment at the start of cc-engine.el for more info."
        (let* ((start (point)) kwd-sym kwd-clause-end found-type)
 
          ;; Look for a specifier keyword clause.
-         (when (looking-at c-prefix-spec-kwds-re)
+         (when (or (looking-at c-prefix-spec-kwds-re)
+                   (and (c-major-mode-is 'java-mode)
+                        (looking-at "@[A-Za-z0-9]+")))
            (if (looking-at c-typedef-key)
                (setq at-typedef t))
            (setq kwd-sym (c-keyword-sym (match-string 1)))
@@ -6616,19 +6714,27 @@ comment at the start of cc-engine.el for more info."
          (if backup-at-type
              (progn
 
-               ;; CASE 3
-               (when (= (point) start)
-                 ;; Got a plain list of identifiers.  If a colon follows it's
-                  ;; a valid label.  Otherwise the last one probably is the
-                  ;; declared identifier and we should back up to the previous
-                  ;; type, providing it isn't a cast.
+
+                ;; CASE 3
+                (when (= (point) start)
+                  ;; Got a plain list of identifiers. If a colon follows it's
+                  ;; a valid label, or maybe a bitfield.  Otherwise the last
+                  ;; one probably is the declared identifier and we should
+                  ;; back up to the previous type, providing it isn't a cast.
                   (if (and (eq (char-after) ?:)
                            (not (c-major-mode-is 'java-mode)))
-                      ;; If we've found a specifier keyword then it's a
-                      ;; declaration regardless.
-                      (throw 'at-decl-or-cast (eq at-decl-or-cast t))
-                   (setq backup-if-not-cast t)
-                   (throw 'at-decl-or-cast t)))
+                      (cond
+                       ;; If we've found a specifier keyword then it's a
+                       ;; declaration regardless.
+                       ((eq at-decl-or-cast t)
+                        (throw 'at-decl-or-cast t))
+                       ((and c-has-bitfields
+                             (eq at-decl-or-cast 'ids)) ; bitfield.
+                        (setq backup-if-not-cast t)
+                        (throw 'at-decl-or-cast t)))
+
+                    (setq backup-if-not-cast t)
+                    (throw 'at-decl-or-cast t)))
 
                ;; CASE 4
                (when (and got-suffix
@@ -6994,7 +7100,7 @@ comment at the start of cc-engine.el for more info."
   ;;   colon).  Currently (2006-03), this applies only to Objective C's
   ;;   keywords "@private", "@protected", and "@public".  Returns t.
   ;;
-  ;; One of the things which will NOT be recognised as a label is a bit-field
+  ;; One of the things which will NOT be recognized as a label is a bit-field
   ;; element of a struct, something like "int foo:5".
   ;;
   ;; The end of the label is taken to be just after the colon, or the end of
@@ -7080,12 +7186,14 @@ comment at the start of cc-engine.el for more info."
           ;; Check that we're not after a token that can't precede a label.
           (or
            ;; Trivially succeeds when there's no preceding token.
+           ;; Succeeds when we're at a virtual semicolon.
            (if preceding-token-end
                (<= preceding-token-end (point-min))
              (save-excursion
                (c-backward-syntactic-ws)
                (setq preceding-token-end (point))
-               (bobp)))
+               (or (bobp)
+                   (c-at-vsemi-p))))
 
            ;; Check if we're after a label, if we're after a closing
            ;; paren that belong to statement, and with
@@ -7959,6 +8067,29 @@ comment at the start of cc-engine.el for more info."
          (back-to-indentation)
          (vector (point) open-paren-pos))))))
 
+(defmacro c-pull-open-brace (ps)
+  ;; Pull the next open brace from PS (which has the form of paren-state),
+  ;; skipping over any brace pairs.  Returns NIL when PS is exhausted.
+  `(progn
+     (while (consp (car ,ps))
+       (setq ,ps (cdr ,ps)))
+     (prog1 (car ,ps)
+       (setq ,ps (cdr ,ps)))))
+
+(defun c-most-enclosing-decl-block (paren-state)
+  ;; Return the buffer position of the most enclosing decl-block brace (in the
+  ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if
+  ;; none was found.
+  (let* ((open-brace (c-pull-open-brace paren-state))
+        (next-open-brace (c-pull-open-brace paren-state)))
+    (while (and open-brace
+               (save-excursion
+                 (goto-char open-brace)
+                 (not (c-looking-at-decl-block next-open-brace nil))))
+      (setq open-brace next-open-brace
+           next-open-brace (c-pull-open-brace paren-state)))
+    open-brace))
+
 (defun c-inside-bracelist-p (containing-sexp paren-state)
   ;; return the buffer position of the beginning of the brace list
   ;; statement if we're inside a brace list, otherwise return nil.
@@ -8294,6 +8425,57 @@ comment at the start of cc-engine.el for more info."
                                                    paren-state)
                                   containing-sexp)))))
 
+(defun c-at-macro-vsemi-p (&optional pos)
+  ;; Is there a "virtual semicolon" at POS or point?
+  ;; (See cc-defs.el for full details of "virtual semicolons".)
+  ;;
+  ;; This is true when point is at the last non syntactic WS position on the
+  ;; line, there is a macro call last on the line, and this particular macro's
+  ;; name is defined by the regexp `c-vs-macro-regexp' as not needing a
+  ;; semicolon.
+  (save-excursion
+    (save-restriction
+      (widen)
+      (if pos
+         (goto-char pos)
+       (setq pos (point)))
+      (and
+       c-macro-with-semi-re
+       (not (c-in-literal))
+       (eq (skip-chars-backward " \t") 0)
+
+       ;; Check we've got nothing after this except comments and empty lines
+       ;; joined by escaped EOLs.
+       (skip-chars-forward " \t")      ; always returns non-nil.
+       (progn
+        (while                       ; go over 1 block comment per iteration.
+            (and
+             (looking-at "\\(\\\\[\n\r][ \t]*\\)*")
+             (goto-char (match-end 0))
+             (cond
+              ((looking-at c-block-comment-start-regexp)
+               (and (forward-comment 1)
+                    (skip-chars-forward " \t"))) ; always returns non-nil
+              ((looking-at c-line-comment-start-regexp)
+               (end-of-line)
+               nil)
+              (t nil))))
+        (eolp))
+
+       (goto-char pos)
+       (progn (c-backward-syntactic-ws)
+             (eq (point) pos))
+
+       ;; Check for one of the listed macros being before point.
+       (or (not (eq (char-before) ?\)))
+          (when (c-go-list-backward)
+            (c-backward-syntactic-ws)
+            t))
+       (c-simple-skip-symbol-backward)
+       (looking-at c-macro-with-semi-re)))))
+
+(defun c-macro-vsemi-status-unknown-p () t) ; See cc-defs.el.
+
 \f
 ;; `c-guess-basic-syntax' and the functions that precedes it below
 ;; implements the main decision tree for determining the syntactic
@@ -8650,7 +8832,7 @@ comment at the start of cc-engine.el for more info."
        ;; CASE B.4: Continued statement with block open.  The most
        ;; accurate analysis is perhaps `statement-cont' together with
        ;; `block-open' but we play DWIM and use `substatement-open'
-       ;; instead.  The rationaly is that this typically is a macro
+       ;; instead.  The rationale is that this typically is a macro
        ;; followed by a block which makes it very similar to a
        ;; statement with a substatement block.
        (t
@@ -8712,6 +8894,35 @@ comment at the start of cc-engine.el for more info."
        (c-beginning-of-statement-1 containing-sexp)
        (c-add-syntax 'annotation-var-cont (point)))
 
+     ;; CASE G: a template list continuation?
+     ;; Mostly a duplication of case 5D.3 to fix templates-19:
+     ((and (c-major-mode-is 'c++-mode)
+          (save-excursion
+            (goto-char indent-point)
+            (c-with-syntax-table c++-template-syntax-table
+              (setq placeholder (c-up-list-backward)))
+            (and placeholder
+                 (eq (char-after placeholder) ?<)
+                 (/= (char-before placeholder) ?<)
+                 (progn
+                   (goto-char (1+ placeholder))
+                   (not (looking-at c-<-op-cont-regexp))))))
+      (c-with-syntax-table c++-template-syntax-table
+       (goto-char placeholder)
+       (c-beginning-of-statement-1 containing-sexp t)
+       (if (save-excursion
+             (c-backward-syntactic-ws containing-sexp)
+             (eq (char-before) ?<))
+           ;; In a nested template arglist.
+           (progn
+             (goto-char placeholder)
+             (c-syntactic-skip-backward "^,;" containing-sexp t)
+             (c-forward-syntactic-ws))
+         (back-to-indentation)))
+      ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
+      ;; template aware.
+      (c-add-syntax 'template-args-cont (point) placeholder))
+
      ;; CASE D: continued statement.
      (t
       (c-beginning-of-statement-1 containing-sexp)
@@ -9371,7 +9582,7 @@ comment at the start of cc-engine.el for more info."
            (c-add-syntax 'inher-cont (c-point 'boi)))
 
           ;; CASE 5D.5: Continuation of the "expression part" of a
-          ;; top level construct.  Or, perhaps, an unrecognised construct.
+          ;; top level construct.  Or, perhaps, an unrecognized construct.
           (t
            (while (and (setq placeholder (point))
                        (eq (car (c-beginning-of-decl-1 containing-sexp))
@@ -9382,7 +9593,7 @@ comment at the start of cc-engine.el for more info."
                        (< (point) placeholder)))
            (c-add-stmt-syntax
             (cond
-             ((eq (point) placeholder) 'statement) ; unrecognised construct
+             ((eq (point) placeholder) 'statement) ; unrecognized construct
              ;; A preceding comma at the top level means that a
              ;; new variable declaration starts here.  Use
              ;; topmost-intro-cont for it, for consistency with