]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Finish fixing a cacheing bug in CC Mode (see 2016-03-09)
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 823d795b6de8af248e2792f2b3ebd1cd2ed61e7a..aac7e631087ca6cd63e368ffcb124f11b55b9e73 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode -*- coding: utf-8 -*-
 
-;; Copyright (C) 1985, 1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2016 Free Software Foundation, Inc.
 
 ;; Authors:    2001- Alan Mackenzie
 ;;             1998- Martin Stjernholm
 
 (defmacro c-declare-lang-variables ()
   `(progn
-     ,@(mapcan (lambda (init)
-                `(,(if (elt init 2)
-                       `(defvar ,(car init) nil ,(elt init 2))
-                     `(defvar ,(car init) nil))
-                  (make-variable-buffer-local ',(car init))))
-              (cdr c-lang-variable-inits))))
+     ,@(c--mapcan (lambda (init)
+                   `(,(if (elt init 2)
+                          `(defvar ,(car init) nil ,(elt init 2))
+                        `(defvar ,(car init) nil))
+                     (make-variable-buffer-local ',(car init))))
+                (cdr c-lang-variable-inits))))
 (c-declare-lang-variables)
 
 \f
@@ -618,11 +618,12 @@ comment at the start of cc-engine.el for more info."
 (defmacro c-bos-report-error ()
   '(unless noerror
      (setq c-parsing-error
-          (format "No matching `%s' found for `%s' on line %d"
-                  (elt saved-pos 1)
-                  (elt saved-pos 2)
-                  (1+ (count-lines (point-min)
-                                   (c-point 'bol (elt saved-pos 0))))))))
+          (format-message
+           "No matching `%s' found for `%s' on line %d"
+           (elt saved-pos 1)
+           (elt saved-pos 2)
+           (1+ (count-lines (point-min)
+                            (c-point 'bol (elt saved-pos 0))))))))
 
 (defun c-beginning-of-statement-1 (&optional lim ignore-labels
                                             noerror comma-delim)
@@ -633,7 +634,7 @@ move into or out of sexps (not even normal expression parentheses).
 
 If point is already at the earliest statement within braces or parens,
 this function doesn't move back into any whitespace preceding it; it
-returns 'same in this case.
+returns `same' in this case.
 
 Stop at statement continuation tokens like \"else\", \"catch\",
 \"finally\" and the \"while\" in \"do ... while\" if the start point
@@ -655,24 +656,24 @@ start of the definition in a \"#define\".  Also stop at start of
 macros before leaving them.
 
 Return:
-'label          if stopped at a label or \"case...:\" or \"default:\";
-'same           if stopped at the beginning of the current statement;
-'up             if stepped to a containing statement;
-'previous       if stepped to a preceding statement;
-'beginning      if stepped from a statement continuation clause to
+`label'         if stopped at a label or \"case...:\" or \"default:\";
+`same'          if stopped at the beginning of the current statement;
+`up'            if stepped to a containing statement;
+`previous'      if stepped to a preceding statement;
+`beginning'     if stepped from a statement continuation clause to
                 its start clause; or
-'macro          if stepped to a macro start.
-Note that 'same and not 'label is returned if stopped at the same
+`macro'         if stepped to a macro start.
+Note that `same' and not `label' is returned if stopped at the same
 label without crossing the colon character.
 
 LIM may be given to limit the search.  If the search hits the limit,
 point will be left at the closest following token, or at the start
-position if that is less ('same is returned in this case).
+position if that is less (`same' is returned in this case).
 
 NOERROR turns off error logging to `c-parsing-error'.
 
-Normally only ';' and virtual semicolons are considered to delimit
-statements, but if COMMA-DELIM is non-nil then ',' is treated
+Normally only `;' and virtual semicolons are considered to delimit
+statements, but if COMMA-DELIM is non-nil then `,' is treated
 as a delimiter too.
 
 Note that this function might do hidden buffer changes.  See the
@@ -1059,7 +1060,7 @@ comment at the start of cc-engine.el for more info."
                          (save-excursion
                            (c-forward-sexp) (point)))
                         ;; Just gone back over some paren block?
-                        ((looking-at "\\s\(")
+                        ((looking-at "\\s(")
                          (save-excursion
                            (goto-char (1+ (c-down-list-backward
                                            before-sws-pos)))
@@ -1232,7 +1233,7 @@ The variable `c-maybe-labelp' is set to the position of the first `:' that
 might start a label (i.e. not part of `::' and not preceded by `?').  If a
 single `?' is found, then `c-maybe-labelp' is cleared.
 
-For AWK, a statement which is terminated by an EOL (not a \; or a }) is
+For AWK, a statement which is terminated by an EOL (not a ; or a }) is
 regarded as having a \"virtual semicolon\" immediately after the last token on
 the line.  If this virtual semicolon is _at_ from, the function recognizes it.
 
@@ -1448,13 +1449,12 @@ This function does not do any hidden buffer changes."
       ;; same line.
       (re-search-forward "\\=\\s *[\n\r]" start t)
 
-      (if (if (let (open-paren-in-column-0-is-defun-start) (forward-comment -1))
+      (if (if (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.
-                 (let (open-paren-in-column-0-is-defun-start)
-                   (forward-comment -1))
+                 (forward-comment -1)
                t))
 
          ;; Emacs <= 20 and XEmacs move back over the closer of a
@@ -1481,7 +1481,7 @@ comment at the start of cc-engine.el for more info."
            ;; return t when moving backwards at bob.
            (not (bobp))
 
-           (if (let (open-paren-in-column-0-is-defun-start moved-comment)
+           (if (let (moved-comment)
                  (while
                      (and (not (setq moved-comment (forward-comment -1)))
                      ;; Cope specifically with ^M^J here -
@@ -2523,6 +2523,20 @@ comment at the start of cc-engine.el for more info."
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; 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.
+  (save-excursion
+    ;; Go back 2 bods, but ignore any bogus positions returned by
+    ;; beginning-of-defun (i.e. open paren in column zero).
+    (goto-char here)
+    (let ((cnt 2))
+      (while (not (or (bobp) (zerop cnt)))
+       (c-beginning-of-defun-1)        ; Pure elisp BOD.
+       (if (eq (char-after) ?\{)
+           (setq cnt (1- cnt)))))
+    (point)))
+
 (defun c-state-balance-parens-backwards (here- here+ top)
   ;; Return the position of the opening paren/brace/bracket before HERE- which
   ;; matches the outermost close p/b/b between HERE+ and TOP.  Except when
@@ -2583,22 +2597,46 @@ comment at the start of cc-engine.el for more info."
   ;; o - ('backward nil) - scan backwards (from HERE).
   ;; o - ('back-and-forward START-POINT) - like 'forward, but when HERE is earlier
   ;;     than GOOD-POS.
+  ;; 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)
-       strategy            ; 'forward, 'backward, or 'IN-LIT.
-       start-point)
+       BOD-pos             ; position of 2nd BOD before HERE.
+       strategy            ; 'forward, 'backward, 'BOD, or 'IN-LIT.
+       start-point
+       how-far)                        ; putative scanning distance.
     (setq good-pos (or good-pos (c-state-get-min-scan-pos)))
     (cond
      ((< here (c-state-get-min-scan-pos))
-      (setq strategy 'IN-LIT))
+      (setq strategy 'IN-LIT
+           start-point nil
+           cache-pos nil
+           how-far 0))
      ((<= good-pos here)
       (setq strategy 'forward
-           start-point (max good-pos cache-pos)))
+           start-point (max good-pos cache-pos)
+           how-far (- here start-point)))
      ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting.
-      (setq strategy 'backward))
+      (setq strategy 'backward
+           how-far (- good-pos here)))
      (t
       (setq strategy 'back-and-forward
-           start-point cache-pos)))
+           start-point cache-pos
+           how-far (- here start-point))))
+
+    ;; Might we be better off starting from the top level, two defuns back,
+    ;; instead?  This heuristic no longer works well in C++, where
+    ;; declarations inside namespace brace blocks are frequently placed at
+    ;; column zero.  (2015-11-10): Remove the condition on C++ Mode.
+    (when (and (or (not (memq 'col-0-paren c-emacs-features))
+                  open-paren-in-column-0-is-defun-start)
+              ;; (not (c-major-mode-is 'c++-mode))
+              (> how-far c-state-cache-too-far))
+      (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!!
+      (if (< (- here BOD-pos) how-far)
+         (setq strategy 'BOD
+               start-point BOD-pos)))
+
     (list strategy start-point)))
 
 
@@ -3135,16 +3173,20 @@ comment at the start of cc-engine.el for more info."
        nil))                           ; for the cond
 
      ((save-restriction
-        (narrow-to-region too-far-back (point-max))
-        (setq ren (c-safe (c-sc-scan-lists pos -1 -1))))
-
+       (narrow-to-region too-far-back (point-max))
+       (setq ren (c-safe (c-sc-scan-lists pos -1 -1))))
       ;; CASE 3: After a }/)/] before `here''s BOL.
       (list (1+ ren) (and dropped-cons pos) nil)) ; Return value
 
+     ((progn (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol)))
+            (>= cache-pos good-pos))
+      ;; CASE 3.5: Just after an existing entry in `c-state-cache' on `here''s
+      ;; line or the previous line.
+      (list cache-pos nil nil))
+
      (t
       ;; CASE 4; Best of a bad job: BOL before `here-bol', or beginning of
       ;; literal containing it.
-      (setq good-pos (c-state-lit-beg (c-point 'bopl here-bol)))
       (list good-pos (and dropped-cons good-pos) nil)))))
 
 
@@ -3199,7 +3241,7 @@ comment at the start of cc-engine.el for more info."
   ;; pair element into an open paren element.  Doing that would mean that the
   ;; new open paren wouldn't have the required preceding paren pair element.
   ;;
-  ;; This function is called from c-after-change.
+  ;; This function is called from c-before-change.
 
   ;; The caches of non-literals:
   ;; Note that we use "<=" for the possibility of the second char of a two-char
@@ -3222,9 +3264,8 @@ comment at the start of cc-engine.el for more info."
     ;; 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 (open-paren-in-column-0-is-defun-start
-         (here-bol (c-point 'bol here))
-         too-high-pa             ; recorded {/(/[ next above here, or nil.
+    (let ((here-bol (c-point 'bol here))
+         too-high-pa  ; recorded {/(/[ next above or just below here, or nil.
          dropped-cons            ; was the last removed element a brace pair?
          pa)
       ;; The easy bit - knock over-the-top bits off `c-state-cache'.
@@ -3236,7 +3277,7 @@ comment at the start of cc-engine.el for more info."
 
       ;; Do we need to add in an earlier brace pair, having lopped one off?
       (if (and dropped-cons
-              (< too-high-pa (+ here c-state-cache-too-far)))
+              (<= too-high-pa here))
          (c-append-lower-brace-pair-to-state-cache too-high-pa here here-bol))
       (setq c-state-cache-good-pos (or (c-state-cache-after-top-paren)
                                       (c-state-get-min-scan-pos)))))
@@ -3294,7 +3335,6 @@ comment at the start of cc-engine.el for more info."
   ;; This function might do hidden buffer changes.
   (let* ((here (point))
         (here-bopl (c-point 'bopl))
-        open-paren-in-column-0-is-defun-start
         strategy            ; 'forward, 'backward etc..
         ;; Candidate positions to start scanning from:
         cache-pos           ; highest position below HERE already existing in
@@ -3315,9 +3355,13 @@ comment at the start of cc-engine.el for more info."
          strategy (car res)
          start-point (cadr res))
 
+    (when (eq strategy 'BOD)
+      (setq c-state-cache nil
+           c-state-cache-good-pos start-point))
+
     ;; SCAN!
     (cond
-     ((memq strategy '(forward back-and-forward))
+     ((memq strategy '(forward back-and-forward BOD))
       (setq res (c-remove-stale-state-cache start-point here here-bopl))
       (setq cache-pos (car res)
            scan-backward-pos (cadr res)
@@ -3428,6 +3472,9 @@ comment at the start of cc-engine.el for more info."
 (make-variable-buffer-local 'c-parse-state-state)
 (defun c-record-parse-state-state ()
   (setq c-parse-state-point (point))
+  (when (markerp (cdr (assq 'c-state-old-cpp-beg c-parse-state-state)))
+    (move-marker (cdr (assq 'c-state-old-cpp-beg c-parse-state-state)) nil)
+    (move-marker (cdr (assq 'c-state-old-cpp-end c-parse-state-state)) nil))
   (setq c-parse-state-state
        (mapcar
         (lambda (arg)
@@ -3787,8 +3834,8 @@ comment at the start of cc-engine.el for more info."
 
 (defconst c-jump-syntax-balanced
   (if (memq 'gen-string-delim c-emacs-features)
-      "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\"\\|\\s|"
-    "\\w\\|\\s_\\|\\s\(\\|\\s\)\\|\\s\""))
+      "\\w\\|\\s_\\|\\s(\\|\\s)\\|\\s\"\\|\\s|"
+    "\\w\\|\\s_\\|\\s(\\|\\s)\\|\\s\""))
 
 (defconst c-jump-syntax-unbalanced
   (if (memq 'gen-string-delim c-emacs-features)
@@ -3955,7 +4002,7 @@ See `c-forward-token-2' for details."
 tokens like \"==\" as single tokens, i.e. all sequences of symbol
 characters are jumped over character by character.  This function is
 for compatibility only; it's only a wrapper over `c-forward-token-2'."
-  (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)"))
+  (let ((c-nonsymbol-token-regexp "\\s."))
     (c-forward-token-2 count balanced limit)))
 
 (defun c-backward-token-1 (&optional count balanced limit)
@@ -3963,7 +4010,7 @@ for compatibility only; it's only a wrapper over `c-forward-token-2'."
 tokens like \"==\" as single tokens, i.e. all sequences of symbol
 characters are jumped over character by character.  This function is
 for compatibility only; it's only a wrapper over `c-backward-token-2'."
-  (let ((c-nonsymbol-token-regexp "\\s.\\|\\s\(\\|\\s\)"))
+  (let ((c-nonsymbol-token-regexp "\\s."))
     (c-backward-token-2 count balanced limit)))
 
 \f
@@ -4215,8 +4262,7 @@ comment at the start of cc-engine.el for more info."
        (setq safe-pos-list (cdr safe-pos-list)))
       (unless (setq safe-pos (car-safe safe-pos-list))
        (setq safe-pos (max (or (c-safe-position
-                                (point) (or c-state-cache
-                                            (c-parse-state)))
+                                (point) (c-parse-state))
                                0)
                            (point-min))
              safe-pos-list (list safe-pos)))
@@ -4264,107 +4310,108 @@ Non-nil is returned if the point moved, nil otherwise.
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
 
-  (let ((start (point))
-       state-2
-       ;; A list of syntactically relevant positions in descending
-       ;; order.  It's used to avoid scanning repeatedly over
-       ;; potentially large regions with `parse-partial-sexp' to verify
-       ;; each position.  Used in `c-ssb-lit-begin'
-       safe-pos-list
-       ;; The result from `c-beginning-of-macro' at the start position or the
-       ;; start position itself if it isn't within a macro.  Evaluated on
-       ;; demand.
-       start-macro-beg
-       ;; The earliest position after the current one with the same paren
-       ;; level.  Used only when `paren-level' is set.
-       lit-beg
-       (paren-level-pos (point)))
-
-    (while
-       (progn
-         ;; The next loop "tries" to find the end point each time round,
-         ;; loops when it hasn't succeeded.
-         (while
-             (and
-              (let ((pos (point)))
-                (while (and
-                        (< (skip-chars-backward skip-chars limit) 0)
-                        ;; Don't stop inside a literal.
-                        (when (setq lit-beg (c-ssb-lit-begin))
-                          (goto-char lit-beg)
-                          t)))
-                (< (point) pos))
-
-              (let ((pos (point)) state-2 pps-end-pos)
+  (c-self-bind-state-cache
+   (let ((start (point))
+        state-2
+        ;; A list of syntactically relevant positions in descending
+        ;; order.  It's used to avoid scanning repeatedly over
+        ;; potentially large regions with `parse-partial-sexp' to verify
+        ;; each position.  Used in `c-ssb-lit-begin'
+        safe-pos-list
+        ;; The result from `c-beginning-of-macro' at the start position or the
+        ;; start position itself if it isn't within a macro.  Evaluated on
+        ;; demand.
+        start-macro-beg
+        ;; The earliest position after the current one with the same paren
+        ;; level.  Used only when `paren-level' is set.
+        lit-beg
+        (paren-level-pos (point)))
+
+     (while
+        (progn
+          ;; The next loop "tries" to find the end point each time round,
+          ;; loops when it hasn't succeeded.
+          (while
+              (and
+               (let ((pos (point)))
+                 (while (and
+                         (< (skip-chars-backward skip-chars limit) 0)
+                         ;; Don't stop inside a literal.
+                         (when (setq lit-beg (c-ssb-lit-begin))
+                           (goto-char lit-beg)
+                           t)))
+                 (< (point) pos))
+
+               (let ((pos (point)) state-2 pps-end-pos)
 
-                (cond
-                 ((and paren-level
-                       (save-excursion
-                         (setq state-2 (parse-partial-sexp
-                                        pos paren-level-pos -1)
-                               pps-end-pos (point))
-                         (/= (car state-2) 0)))
-                  ;; Not at the right level.
-
-                  (if (and (< (car state-2) 0)
-                           ;; We stop above if we go out of a paren.
-                           ;; Now check whether it precedes or is
-                           ;; nested in the starting sexp.
-                           (save-excursion
-                             (setq state-2
-                                   (parse-partial-sexp
-                                    pps-end-pos paren-level-pos
-                                    nil nil state-2))
-                             (< (car state-2) 0)))
-
-                      ;; We've stopped short of the starting position
-                      ;; so the hit was inside a nested list.  Go up
-                      ;; until we are at the right level.
-                      (condition-case nil
-                          (progn
-                            (goto-char (scan-lists pos -1
-                                                   (- (car state-2))))
-                            (setq paren-level-pos (point))
-                            (if (and limit (>= limit paren-level-pos))
-                                (progn
-                                  (goto-char limit)
-                                  nil)
-                              t))
-                        (error
-                         (goto-char (or limit (point-min)))
-                         nil))
-
-                    ;; The hit was outside the list at the start
-                    ;; position.  Go to the start of the list and exit.
-                    (goto-char (1+ (elt state-2 1)))
-                    nil))
-
-                 ((c-beginning-of-macro limit)
-                  ;; Inside a macro.
-                  (if (< (point)
-                         (or start-macro-beg
-                             (setq start-macro-beg
-                                   (save-excursion
-                                     (goto-char start)
-                                     (c-beginning-of-macro limit)
-                                     (point)))))
-                      t
-
-                    ;; It's inside the same macro we started in so it's
-                    ;; a relevant match.
-                    (goto-char pos)
-                    nil))))))
-
-         (> (point)
-            (progn
-              ;; Skip syntactic ws afterwards so that we don't stop at the
-              ;; end of a comment if `skip-chars' is something like "^/".
-              (c-backward-syntactic-ws)
-              (point)))))
+                 (cond
+                  ((and paren-level
+                        (save-excursion
+                          (setq state-2 (parse-partial-sexp
+                                         pos paren-level-pos -1)
+                                pps-end-pos (point))
+                          (/= (car state-2) 0)))
+                   ;; Not at the right level.
+
+                   (if (and (< (car state-2) 0)
+                            ;; We stop above if we go out of a paren.
+                            ;; Now check whether it precedes or is
+                            ;; nested in the starting sexp.
+                            (save-excursion
+                              (setq state-2
+                                    (parse-partial-sexp
+                                     pps-end-pos paren-level-pos
+                                     nil nil state-2))
+                              (< (car state-2) 0)))
+
+                       ;; We've stopped short of the starting position
+                       ;; so the hit was inside a nested list.  Go up
+                       ;; until we are at the right level.
+                       (condition-case nil
+                           (progn
+                             (goto-char (scan-lists pos -1
+                                                    (- (car state-2))))
+                             (setq paren-level-pos (point))
+                             (if (and limit (>= limit paren-level-pos))
+                                 (progn
+                                   (goto-char limit)
+                                   nil)
+                               t))
+                         (error
+                          (goto-char (or limit (point-min)))
+                          nil))
+
+                     ;; The hit was outside the list at the start
+                     ;; position.  Go to the start of the list and exit.
+                     (goto-char (1+ (elt state-2 1)))
+                     nil))
+
+                  ((c-beginning-of-macro limit)
+                   ;; Inside a macro.
+                   (if (< (point)
+                          (or start-macro-beg
+                              (setq start-macro-beg
+                                    (save-excursion
+                                      (goto-char start)
+                                      (c-beginning-of-macro limit)
+                                      (point)))))
+                       t
+
+                     ;; It's inside the same macro we started in so it's
+                     ;; a relevant match.
+                     (goto-char pos)
+                     nil))))))
+
+          (> (point)
+             (progn
+               ;; Skip syntactic ws afterwards so that we don't stop at the
+               ;; end of a comment if `skip-chars' is something like "^/".
+               (c-backward-syntactic-ws)
+               (point)))))
 
-    ;; We might want to extend this with more useful return values in
-    ;; the future.
-    (/= (point) start)))
+     ;; We might want to extend this with more useful return values in
+     ;; the future.
+     (/= (point) start))))
 
 ;; The following is an alternative implementation of
 ;; `c-syntactic-skip-backward' that uses backward movement to keep
@@ -4612,7 +4659,7 @@ comment at the start of cc-engine.el for more info."
 (defun c-literal-type (range)
   "Convenience function that given the result of `c-literal-limits',
 returns nil or the type of literal that the range surrounds, one
-of the symbols 'c, 'c++ or 'string.  It's much faster than using
+of the symbols `c', `c++' or `string'.  It's much faster than using
 `c-in-literal' and is intended to be used when you need both the
 type of a literal and its limits.
 
@@ -5533,8 +5580,9 @@ comment at the start of cc-engine.el for more info."
 
 (defun c-before-change-check-<>-operators (beg end)
   ;; Unmark certain pairs of "< .... >" which are currently marked as
-  ;; template/generic delimiters.  (This marking is via syntax-table
-  ;; text properties).
+  ;; template/generic delimiters.  (This marking is via syntax-table text
+  ;; properties), and expand the (c-new-BEG c-new-END) region to include all
+  ;; unmarked < and > operators within the certain bounds (see below).
   ;;
   ;; These pairs are those which are in the current "statement" (i.e.,
   ;; the region between the {, }, or ; before BEG and the one after
@@ -5551,40 +5599,43 @@ comment at the start of cc-engine.el for more info."
   ;; FIXME!!!  This routine ignores the possibility of macros entirely.
   ;; 2010-01-29.
   (save-excursion
-    (let ((beg-lit-limits (progn (goto-char beg) (c-literal-limits)))
-         (end-lit-limits (progn (goto-char end) (c-literal-limits)))
-         new-beg new-end need-new-beg need-new-end)
-      ;; Locate the barrier before the changed region
+    (c-save-buffer-state
+       ((beg-lit-limits (progn (goto-char beg) (c-literal-limits)))
+        (end-lit-limits (progn (goto-char end) (c-literal-limits)))
+        new-beg new-end beg-limit end-limit)
+      ;; Locate the earliest < after the barrier before the changed region,
+      ;; which isn't already marked as a paren.
       (goto-char  (if beg-lit-limits (car beg-lit-limits) beg))
-      (c-syntactic-skip-backward "^;{}" (c-determine-limit 512))
-      (setq new-beg (point))
+      (setq beg-limit (c-determine-limit 512))
 
       ;; Remove the syntax-table/category properties from each pertinent <...>
-      ;; pair.  Firsly, the ones with the < before beg and > after beg.
-      (while
-         (c-search-forward-char-property 'syntax-table c-<-as-paren-syntax beg)
-       (if (c-clear-<-pair-props-if-match-after beg (1- (point)))
-           (setq need-new-beg t)))
+      ;; pair.  Firstly, the ones with the < before beg and > after beg....
+      (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
+                   (eq (char-before) ?<))
+       (c-backward-token-2)
+       (when (eq (char-after) ?<)
+         (c-clear-<-pair-props-if-match-after beg)))
+      (c-forward-syntactic-ws)
+      (setq new-beg (point))
 
-      ;; Locate the barrier after END.
+      ;; ...Then the ones with < before end and > after end.
       (goto-char (if end-lit-limits (cdr end-lit-limits) end))
-      (c-syntactic-re-search-forward "[;{}]" (c-determine-+ve-limit 512) 'end)
+      (setq end-limit (c-determine-+ve-limit 512))
+      (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 'end)
+                 (eq (char-before) ?>))
+       (c-end-of-current-token)
+       (when (eq (char-before) ?>)
+         (c-clear->-pair-props-if-match-before end (1- (point)))))
+      (c-backward-syntactic-ws)
       (setq new-end (point))
 
-      ;; Remove syntax-table properties from the remaining pertinent <...>
-      ;; pairs, those with a > after end and < before end.
-      (while (c-search-backward-char-property 'syntax-table c->-as-paren-syntax end)
-       (if (c-clear->-pair-props-if-match-before end)
-           (setq need-new-end t)))
-
       ;; Extend the fontification region, if needed.
-      (when need-new-beg
-       (goto-char new-beg)
-       (c-forward-syntactic-ws)
-       (and (< (point) c-new-BEG) (setq c-new-BEG (point))))
-
-      (when need-new-end
-       (and (> new-end c-new-END) (setq c-new-END new-end))))))
+      (and new-beg
+          (< new-beg c-new-BEG)
+          (setq c-new-BEG new-beg))
+      (and new-end
+          (> new-end c-new-END)
+          (setq c-new-END new-end)))))
 
 (defun c-after-change-check-<>-operators (beg end)
   ;; This is called from `after-change-functions' when
@@ -5624,7 +5675,28 @@ comment at the start of cc-engine.el for more info."
            (c-clear-<>-pair-props)
            (forward-char)))))))
 
-
+(defun c-restore-<>-properties (_beg _end _old-len)
+  ;; This function is called as an after-change function.  It restores the
+  ;; category/syntax-table properties on template/generic <..> pairs between
+  ;; c-new-BEG and c-new-END.  It may do hidden buffer changes.
+  (c-save-buffer-state ((c-parse-and-markup-<>-arglists t)
+                       c-restricted-<>-arglists lit-limits)
+    (goto-char c-new-BEG)
+    (if (setq lit-limits (c-literal-limits))
+       (goto-char (cdr lit-limits)))
+    (while (and (< (point) c-new-END)
+               (c-syntactic-re-search-forward "<" c-new-END 'bound))
+      (backward-char)
+      (save-excursion
+       (c-backward-token-2)
+       (setq c-restricted-<>-arglists
+            (and (not (looking-at c-opt-<>-sexp-key))
+                 (progn (c-backward-syntactic-ws) ; to ( or ,
+                        (and (memq (char-before) '(?\( ?,)) ; what about <?
+                             (not (eq (c-get-char-property (point) 'c-type)
+                                      'c-decl-arg-start)))))))
+      (or (c-forward-<>-arglist nil)
+         (forward-char)))))
 \f
 ;; Handling of small scale constructs like types and names.
 
@@ -5920,7 +5992,7 @@ comment at the start of cc-engine.el for more info."
   ;; Recursive part of `c-forward-<>-arglist'.
   ;;
   ;; This function might do hidden buffer changes.
-  (let ((start (point)) res pos tmp
+  (let ((start (point)) res pos
        ;; Cover this so that any recorded found type ranges are
        ;; automatically lost if it turns out to not be an angle
        ;; bracket arglist.  It's propagated through the return value
@@ -5972,7 +6044,7 @@ comment at the start of cc-engine.el for more info."
 
                      (when (or (looking-at "extends")
                                (looking-at "super"))
-                       (forward-word)
+                       (forward-word-strictly)
                        (c-forward-syntactic-ws)
                        (let ((c-promote-possible-types t)
                              (c-record-found-types t))
@@ -5987,7 +6059,10 @@ comment at the start of cc-engine.el for more info."
                   ;; Stop on ',', '|', '&', '+' and '-' to catch
                   ;; common binary operators that could be between
                   ;; two comparison expressions "a<b" and "c>d".
-                  "[<;{},|+&-]\\|[>)]"
+                  ;; 2016-02-11: C++11 templates can now contain arithmetic
+                  ;; expressions, so template detection in C++ is now less
+                  ;; robust than it was.
+                  c-<>-notable-chars-re
                   nil t t))
 
                (cond
@@ -5995,7 +6070,9 @@ comment at the start of cc-engine.el for more info."
                  ;; Either an operator starting with '>' or the end of
                  ;; the angle bracket arglist.
 
-                 (if (looking-at c->-op-without->-cont-regexp)
+                 (if (save-excursion
+                       (c-backward-token-2)
+                       (looking-at c-multichar->-op-not->>-regexp))
                      (progn
                        (goto-char (match-end 0))
                        t)              ; Continue the loop.
@@ -6015,15 +6092,13 @@ comment at the start of cc-engine.el for more info."
                  ;; Either an operator starting with '<' or a nested arglist.
                  (setq pos (point))
                  (let (id-start id-end subres keyword-match)
-                  (cond
+                   (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 '<'
+                       (backward-char) ; to the '<'
                        (and
                         (save-excursion
                           ;; There's always an identifier before an angle
@@ -6043,7 +6118,9 @@ comment at the start of cc-engine.el for more info."
                                  (and keyword-match
                                       (c-keyword-member
                                        (c-keyword-sym (match-string 1))
-                                       'c-<>-type-kwds)))))))
+                                       'c-<>-type-kwds))))))
+                       (or subres (goto-char pos))
+                       subres)
                      ;; It was an angle bracket arglist.
                      (setq c-record-found-types subres)
 
@@ -6059,11 +6136,16 @@ comment at the start of cc-engine.el for more info."
                            (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.
+                    ;; At a "less than" operator.
+                    (t
+                     ;; (forward-char) ; NO!  We've already gone over the <.
+                     )))
+                 t)                    ; carry on looping.
+
+                ((and
+                  (eq (char-before) ?\()
+                  (c-go-up-list-forward)
+                  (eq (char-before) ?\))))
 
                 ((and (not c-restricted-<>-arglists)
                       (or (and (eq (char-before) ?&)
@@ -6572,16 +6654,22 @@ comment at the start of cc-engine.el for more info."
     res))
 
 (defun c-forward-annotation ()
-  ;; Used for Java code only at the moment.  Assumes point is on the
-  ;; @, moves forward an annotation.  returns nil if there is no
-  ;; annotation at point.
-  (and (looking-at "@")
-       (progn (forward-char) t)
-       (c-forward-type)
-       (progn (c-forward-syntactic-ws) t)
-       (if (looking-at "(")
-          (c-go-list-forward)
-        t)))
+  ;; Used for Java code only at the moment.  Assumes point is on the @, moves
+  ;; forward an annotation and returns t.  Leaves point unmoved and returns
+  ;; nil if there is no annotation at point.
+  (let ((pos (point)))
+    (or
+     (and (looking-at "@")
+         (not (looking-at c-keywords-regexp))
+         (progn (forward-char) t)
+         (looking-at c-symbol-key)
+         (progn (goto-char (match-end 0))
+                (c-forward-syntactic-ws)
+                t)
+         (if (looking-at "(")
+             (c-go-list-forward)
+           t))
+     (progn (goto-char pos) nil))))
 
 (defmacro c-pull-open-brace (ps)
   ;; Pull the next open brace from PS (which has the form of paren-state),
@@ -6622,49 +6710,71 @@ comment at the start of cc-engine.el for more info."
     (or res (goto-char here))
     res))
 
+(defmacro c-back-over-list-of-member-inits ()
+  ;; Go back over a list of elements, each looking like:
+  ;; <symbol> (<expression>) ,
+  ;; or <symbol> {<expression>} ,
+  ;; when we are putatively immediately after a comma.  Stop when we don't see
+  ;; a comma.  If either of <symbol> or bracketed <expression> is missing,
+  ;; throw nil to 'level.  If the terminating } or ) is unmatched, throw nil
+  ;; to 'done.  This is not a general purpose macro!
+  `(while (eq (char-before) ?,)
+     (backward-char)
+     (c-backward-syntactic-ws)
+     (when (not (memq (char-before) '(?\) ?})))
+       (throw 'level nil))
+     (when (not (c-go-list-backward))
+       (throw 'done nil))
+     (c-backward-syntactic-ws)
+     (when (not (c-simple-skip-symbol-backward))
+       (throw 'level nil))
+     (c-backward-syntactic-ws)))
+
 (defun c-back-over-member-initializers ()
   ;; Test whether we are in a C++ member initializer list, and if so, go back
   ;; to the introducing ":", returning the position of the opening paren of
   ;; the function's arglist.  Otherwise return nil, leaving point unchanged.
   (let ((here (point))
        (paren-state (c-parse-state))
-       res)
-
+       pos level-plausible at-top-level res)
+    ;; Assume tentatively that we're at the top level.  Try to go back to the
+    ;; colon we seek.
     (setq res
          (catch 'done
-           (if (not (c-at-toplevel-p))
-               (progn
-                 (while (not (c-at-toplevel-p))
-                   (goto-char (c-pull-open-brace paren-state)))
-                 (c-backward-syntactic-ws)
-                 (when (not (c-simple-skip-symbol-backward))
-                   (throw 'done nil))
-                 (c-backward-syntactic-ws))
-             (c-backward-syntactic-ws)
-             (when (memq (char-before) '(?\) ?}))
-               (when (not (c-go-list-backward))
-                 (throw 'done nil))
-               (c-backward-syntactic-ws))
-             (when (c-simple-skip-symbol-backward)
-               (c-backward-syntactic-ws)))
-
-           (while (eq (char-before) ?,)
-             (backward-char)
-             (c-backward-syntactic-ws)
-
-             (when (not (memq (char-before) '(?\) ?})))
-               (throw 'done nil))
-             (when (not (c-go-list-backward))
-               (throw 'done nil))
-             (c-backward-syntactic-ws)
-             (when (not (c-simple-skip-symbol-backward))
-               (throw 'done nil))
-             (c-backward-syntactic-ws))
-
-           (and
-            (eq (char-before) ?:)
-            (c-just-after-func-arglist-p))))
+           (setq level-plausible
+                 (catch 'level
+                   (c-backward-syntactic-ws)
+                   (when (memq (char-before) '(?\) ?}))
+                     (when (not (c-go-list-backward))
+                       (throw 'done nil))
+                     (c-backward-syntactic-ws))
+                   (when (c-simple-skip-symbol-backward)
+                     (c-backward-syntactic-ws))
+                   (c-back-over-list-of-member-inits)
+                   (and (eq (char-before) ?:)
+                        (save-excursion
+                          (c-backward-token-2)
+                          (not (looking-at c-:$-multichar-token-regexp)))
+                        (c-just-after-func-arglist-p))))
+
+           (while (and (not (and level-plausible
+                                 (setq at-top-level (c-at-toplevel-p))))
+                       (setq pos (c-pull-open-brace paren-state))) ; might be a paren.
+             (setq level-plausible
+                   (catch 'level
+                     (goto-char pos)
+                     (c-backward-syntactic-ws)
+                     (when (not (c-simple-skip-symbol-backward))
+                       (throw 'level nil))
+                     (c-backward-syntactic-ws)
+                     (c-back-over-list-of-member-inits)
+                     (and (eq (char-before) ?:)
+                          (save-excursion
+                            (c-backward-token-2)
+                            (not (looking-at c-:$-multichar-token-regexp)))
+                          (c-just-after-func-arglist-p)))))
 
+           (and at-top-level level-plausible)))
     (or res (goto-char here))
     res))
 
@@ -6711,6 +6821,119 @@ comment at the start of cc-engine.el for more info."
        ;; This identifier is bound only in the inner let.
        '(setq start id-start))))
 
+(defun c-forward-declarator (&optional limit accept-anon)
+  ;; Assuming point is at the start of a declarator, move forward over it,
+  ;; leaving point at the next token after it (e.g. a ) or a ; or a ,).
+  ;;
+  ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT), where ID-START and
+  ;; ID-END are the bounds of the declarator's identifier, and
+  ;; BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id.
+  ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(".
+  ;;
+  ;; If ACCEPT-ANON is non-nil, move forward over any "anonymous declarator",
+  ;; i.e. something like the (*) in int (*), such as might be found in a
+  ;; declaration.  In such a case ID-START and ID-END in the return value are
+  ;; both set to nil.  A "null" "anonymous declarator" gives a non-nil result.
+  ;;
+  ;; If no declarator is found, leave point unmoved and return nil.  LIMIT is
+  ;; an optional limit for forward searching.
+  ;;
+  ;; Note that the global variable `c-last-identifier-range' is written to, so
+  ;; the caller should bind it if necessary.
+
+  ;; Inside the following "condition form", we move forward over the
+  ;; declarator's identifier up as far as any opening bracket (for array
+  ;; size) or paren (for parameters of function-type) or brace (for
+  ;; array/struct initialization) or "=" or terminating delimiter
+  ;; (e.g. "," or ";" or "}").
+  (let ((here (point))
+       id-start id-end brackets-after-id paren-depth)
+    (or limit (setq limit (point-max)))
+    (if        (and
+        (< (point) limit)
+
+        ;; The following form moves forward over the declarator's
+        ;; identifier (and what precedes it), returning t.  If there
+        ;; wasn't one, it returns nil.
+        (let (got-identifier)
+          (setq paren-depth 0)
+          ;; Skip over type decl prefix operators, one for each iteration
+          ;; of the while.  These are, e.g. "*" in "int *foo" or "(" and
+          ;; "*" in "int (*foo) (void)" (Note similar code in
+          ;; `c-forward-decl-or-cast-1'.)
+          (while (and (looking-at c-type-decl-prefix-key)
+                      (if (and (c-major-mode-is 'c++-mode)
+                               (match-beginning 3))
+                          ;; If the third submatch matches in C++ then
+                          ;; we're looking at an identifier that's a
+                          ;; prefix only if it specifies a member pointer.
+                          (progn
+                            (setq id-start (point))
+                            (c-forward-name)
+                            (if (looking-at "\\(::\\)")
+                                ;; We only check for a trailing "::" and
+                                ;; let the "*" that should follow be
+                                ;; matched in the next round.
+                                t
+                              ;; It turned out to be the real identifier,
+                              ;; so flag that and stop.
+                              (setq got-identifier t)
+                              nil))
+                        t))
+            (if (eq (char-after) ?\()
+                (progn
+                  (setq paren-depth (1+ paren-depth))
+                  (forward-char))
+              (goto-char (match-end 1)))
+            (c-forward-syntactic-ws))
+
+          ;; If we haven't passed the identifier already, do it now.
+          (unless got-identifier
+            (setq id-start (point)))
+          (cond
+           ((or got-identifier
+                (c-forward-name))
+            (save-excursion
+              (c-backward-syntactic-ws)
+              (setq id-end (point))))
+           (accept-anon
+            (setq id-start nil id-end nil)
+            t)
+           (t (/= (point) here))))
+
+        ;; Skip out of the parens surrounding the identifier.  If closing
+        ;; parens are missing, this form returns nil.
+        (or (= paren-depth 0)
+            (c-safe (goto-char (scan-lists (point) 1 paren-depth))))
+
+        (<= (point) limit)
+
+        ;; Skip over any trailing bit, such as "__attribute__".
+        (progn
+          (when (looking-at c-decl-hangon-key)
+            (c-forward-keyword-clause 1))
+          (<= (point) limit))
+
+        ;; Search syntactically to the end of the declarator (";",
+        ;; ",", a closing paren, eob etc) or to the beginning of an
+        ;; initializer or function prototype ("=" or "\\s\(").
+        ;; Note that square brackets are now not also treated as
+        ;; initializers, since this broke when there were also
+        ;; initializing brace lists.
+        (let (found)
+          (while
+              (and (setq found (c-syntactic-re-search-forward
+                                "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t))
+                   (eq (char-before) ?\[)
+                   (c-go-up-list-forward))
+            (setq brackets-after-id t))
+          (backward-char)
+          found))
+       (list id-start id-end brackets-after-id (match-beginning 1))
+
+      (goto-char here)
+      nil)))
+
 (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
   ;; Move forward over a declaration or a cast if at the start of one.
   ;; The point is assumed to be at the start of some token.  Nil is
@@ -6874,9 +7097,8 @@ comment at the start of cc-engine.el for more info."
          (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto
                    (and (c-major-mode-is 'java-mode)
                         (looking-at "@[A-Za-z0-9]+")))
-           (save-match-data
-             (if (looking-at c-typedef-key)
-               (setq at-typedef t)))
+           (if (save-match-data (looking-at c-typedef-key))
+               (setq at-typedef t))
            (setq kwd-sym (c-keyword-sym (match-string 1)))
            (save-excursion
              (c-forward-keyword-clause 1)
@@ -7066,7 +7288,7 @@ comment at the start of cc-engine.el for more info."
       (goto-char id-start)
 
       ;; Skip over type decl prefix operators.  (Note similar code in
-      ;; `c-font-lock-declarators'.)
+      ;; `c-forward-declarator'.)
       (if (and c-recognize-typeless-decls
               (equal c-type-decl-prefix-key "\\<\\>"))
          (when (eq (char-after) ?\()
@@ -7119,7 +7341,7 @@ comment at the start of cc-engine.el for more info."
                       (setq paren-depth (1- paren-depth))
                       (forward-char)
                       t)
-                  (when (if (save-match-data (looking-at "\\s\("))
+                  (when (if (save-match-data (looking-at "\\s("))
                             (c-safe (c-forward-sexp 1) t)
                           (goto-char (match-end 1))
                           t)
@@ -7193,7 +7415,7 @@ comment at the start of cc-engine.el for more info."
 
         (setq at-decl-end
               (looking-at (cond ((eq context '<>) "[,>]")
-                                (context "[,\)]")
+                                (context "[,)]")
                                 (t "[,;]"))))
 
         ;; Now we've collected info about various characteristics of
@@ -7517,7 +7739,7 @@ comment at the start of cc-engine.el for more info."
         ;; The closing paren should follow.
         (progn
           (c-forward-syntactic-ws)
-          (looking-at "\\s\)"))
+          (looking-at "\\s)"))
 
         ;; There should be a primary expression after it.
         (let (pos)
@@ -7914,7 +8136,7 @@ comment at the start of cc-engine.el for more info."
 
          (catch 'break
            ;; Look for ": superclass-name" or "( category-name )".
-           (when (looking-at "[:\(]")
+           (when (looking-at "[:(]")
              (setq start-char (char-after))
              (forward-char)
              (c-forward-syntactic-ws)
@@ -7972,7 +8194,7 @@ comment at the start of cc-engine.el for more info."
   ;; This should be called with point inside an argument list.
   ;;
   ;; Only one level of enclosing parentheses is considered, so for
-  ;; instance `nil' is returned when in a function call within an asm
+  ;; instance nil is returned when in a function call within an asm
   ;; operand.
   ;;
   ;; This function might do hidden buffer changes.
@@ -8004,6 +8226,8 @@ brace.
 
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
+  ;; Note to maintainers: this function consumes a great mass of CPU cycles.
+  ;; Its use should thus be minimized as far as possible.
   (let ((paren-state (c-parse-state)))
     (or (not (c-most-enclosing-brace paren-state))
        (c-search-uplist-for-classkey paren-state))))
@@ -8064,14 +8288,14 @@ comment at the start of cc-engine.el for more info."
   ;; Return the position of the first argument declaration if point is
   ;; inside a K&R style argument declaration list, nil otherwise.
   ;; `c-recognize-knr-p' is not checked.  If LIM is non-nil, it's a
-  ;; position that bounds the backward search for the argument list.
+  ;; position that bounds the backward search for the argument list.  This
+  ;; function doesn't move point.
   ;;
   ;; Point must be within a possible K&R region, e.g. just before a top-level
   ;; "{".  It must be outside of parens and brackets.  The test can return
   ;; false positives otherwise.
   ;;
   ;; This function might do hidden buffer changes.
-
   (save-excursion
     (save-restriction
       ;; If we're in a macro, our search range is restricted to it.  Narrow to
@@ -8080,8 +8304,12 @@ comment at the start of cc-engine.el for more info."
             (macro-end (save-excursion (and macro-start (c-end-of-macro) (point))))
             (low-lim (max (or lim (point-min))   (or macro-start (point-min))))
             before-lparen after-rparen
-            (pp-count-out 20)) ; Max number of paren/brace constructs before
-                               ; we give up
+            (here (point))
+            (pp-count-out 20)  ; Max number of paren/brace constructs before
+                               ; we give up.
+            ids              ; List of identifiers in the parenthesized list.
+            id-start after-prec-token decl-or-cast decl-res
+            c-last-identifier-range identifier-ok)
        (narrow-to-region low-lim (or macro-end (point-max)))
 
        ;; Search backwards for the defun's argument list.  We give up if we
@@ -8100,8 +8328,12 @@ comment at the start of cc-engine.el for more info."
        ;; int foo (bar, baz, yuk)
        ;;     int bar [] ;
        ;;     int (*baz) (my_type) ;
-       ;;     int (*) (void) (*yuk) (void) ;
+       ;;     int (*(* yuk) (void)) (void) ;
        ;; {
+       ;;
+       ;; Additionally, for a knr list to be recognized:
+       ;; o - The identifier of each declarator up to and including the
+       ;;   one "near" point must be contained in the arg list.
 
        (catch 'knr
          (while (> pp-count-out 0) ; go back one paren/bracket pair each time.
@@ -8147,21 +8379,58 @@ comment at the start of cc-engine.el for more info."
                       (goto-char before-lparen)
                       (c-forward-token-2) ; to first token inside parens
                       (and
-                       (c-on-identifier)
-                       (c-forward-token-2)
+                       (setq id-start (c-on-identifier)) ; Must be at least one.
                        (catch 'id-list
-                         (while (eq (char-after) ?\,)
+                         (while
+                             (progn
+                               (forward-char)
+                               (c-end-of-current-token)
+                               (push (buffer-substring-no-properties id-start
+                                                                     (point))
+                                     ids)
+                               (c-forward-syntactic-ws)
+                               (eq (char-after) ?\,))
                            (c-forward-token-2)
-                           (unless (c-on-identifier) (throw 'id-list nil))
-                           (c-forward-token-2))
-                         (eq (char-after) ?\))))))
+                           (unless (setq id-start (c-on-identifier))
+                             (throw 'id-list nil)))
+                         (eq (char-after) ?\)))))
 
+                    ;; Are all the identifiers in the k&r list up to the
+                    ;; current one also in the argument list?
+                    (progn
+                      (forward-char)   ; over the )
+                      (setq after-prec-token after-rparen)
+                      (c-forward-syntactic-ws)
+                      (while (and
+                              (or (consp (setq decl-or-cast
+                                               (c-forward-decl-or-cast-1
+                                                after-prec-token
+                                                nil ; Or 'arglist ???
+                                                nil)))
+                                  (progn
+                                    (goto-char after-prec-token)
+                                    (c-forward-syntactic-ws)
+                                    (setq identifier-ok (eq (char-after) ?{))
+                                    nil))
+                              (eq (char-after) ?\;)
+                              (setq after-prec-token (1+ (point)))
+                              (goto-char (car decl-or-cast))
+                              (setq decl-res (c-forward-declarator))
+                              (setq identifier-ok
+                                    (member (buffer-substring-no-properties
+                                       (car decl-res) (cadr decl-res))
+                                      ids))
+                              (progn
+                                (goto-char after-prec-token)
+                                (prog1 (< (point) here)
+                                  (c-forward-syntactic-ws))))
+                        (setq identifier-ok nil))
+                      identifier-ok))
                    ;; ...Yes.  We've identified the function's argument list.
                    (throw 'knr
                           (progn (goto-char after-rparen)
                                  (c-forward-syntactic-ws)
                                  (point)))
-
                  ;; ...No.  The current parens aren't the function's arg list.
                  (goto-char before-lparen))
 
@@ -8429,7 +8698,7 @@ comment at the start of cc-engine.el for more info."
                            ;; Check for `c-opt-block-decls-with-vars-key'
                            ;; before the first paren.
                            (c-syntactic-re-search-forward
-                            (concat "[;=\(\[{]\\|\\("
+                            (concat "[;=([{]\\|\\("
                                     c-opt-block-decls-with-vars-key
                                     "\\)")
                             lim t t t)
@@ -8437,7 +8706,7 @@ comment at the start of cc-engine.el for more info."
                            (not (eq (char-before) ?_))
                            ;; Check that the first following paren is
                            ;; the block.
-                           (c-syntactic-re-search-forward "[;=\(\[{]"
+                           (c-syntactic-re-search-forward "[;=([{]"
                                                           lim t t t)
                            (eq (char-before) ?{)))))))
            ;; The declaration doesn't have any of the
@@ -8956,7 +9225,7 @@ comment at the start of cc-engine.el for more info."
                         (> (point) closest-lim))
                  (not (bobp))
                  (progn (backward-char)
-                        (looking-at "[\]\).]\\|\\w\\|\\s_"))
+                        (looking-at "[]).]\\|\\w\\|\\s_"))
                  (c-safe (forward-char)
                          (goto-char (scan-sexps (point) -1))))
 
@@ -9019,6 +9288,11 @@ comment at the start of cc-engine.el for more info."
            (goto-char containing-sexp)
            (if (or (save-excursion
                      (c-backward-syntactic-ws lim)
+                     (while (and (eq (char-before) ?>)
+                                 (c-get-char-property (1- (point))
+                                                      'syntax-table)
+                                 (c-go-list-backward nil lim))
+                       (c-backward-syntactic-ws lim))
                      (and (> (point) (or lim (point-min)))
                           (c-on-identifier)))
                    (and c-special-brace-lists
@@ -9566,7 +9840,6 @@ comment at the start of cc-engine.el for more info."
     (c-save-buffer-state
        ((indent-point (point))
         (case-fold-search nil)
-        open-paren-in-column-0-is-defun-start
         ;; A whole ugly bunch of various temporary variables.  Have
         ;; to declare them here since it's not possible to declare
         ;; a variable with only the scope of a cond test and the
@@ -9821,7 +10094,19 @@ comment at the start of cc-engine.el for more info."
                                       paren-state)))
 
        ;; CASE 14: A case or default label
-       ((looking-at c-label-kwds-regexp)
+       ((save-excursion
+         (and (looking-at c-label-kwds-regexp)
+              (or (c-major-mode-is 'idl-mode)
+                  (and
+                   containing-sexp
+                   (goto-char containing-sexp)
+                   (eq (char-after) ?{)
+                   (progn (c-backward-syntactic-ws) t)
+                   (eq (char-before) ?\))
+                   (c-go-list-backward)
+                   (progn (c-backward-syntactic-ws) t)
+                   (c-simple-skip-symbol-backward)
+                   (looking-at c-block-stmt-2-key)))))
        (if containing-sexp
            (progn
              (goto-char containing-sexp)
@@ -9837,6 +10122,7 @@ comment at the start of cc-engine.el for more info."
        ((save-excursion
          (back-to-indentation)
          (and (not (looking-at c-syntactic-ws-start))
+              (not (looking-at c-label-kwds-regexp))
               (c-forward-label)))
        (cond (containing-decl-open
               (setq placeholder (c-add-class-syntax 'inclass
@@ -10009,7 +10295,8 @@ comment at the start of cc-engine.el for more info."
         ;; Note there is no limit on the backward search here, since member
         ;; init lists can, in practice, be very large.
         ((save-excursion
-           (when (setq placeholder (c-back-over-member-initializers))
+           (when (and (c-major-mode-is 'c++-mode)
+                      (setq placeholder (c-back-over-member-initializers)))
              (setq tmp-pos (point))))
          (if (= (c-point 'bosws) (1+ tmp-pos))
                (progn
@@ -11228,8 +11515,8 @@ Cannot combine absolute offsets %S and %S in `add' method"
 \f
 (cc-provide 'cc-engine)
 
-;;; Local Variables:
-;;; indent-tabs-mode: t
-;;; tab-width: 8
-;;; End:
+;; Local Variables:
+;; indent-tabs-mode: t
+;; tab-width: 8
+;; End:
 ;;; cc-engine.el ends here