]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Handle "noise" macros and compiler directives.
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 1223db3b33e304cb323f9c38047645ef2138ce61..66b5369bbba8cea755c53a0445744291f9ff4c2f 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
@@ -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,19 +656,19 @@ 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'.
 
@@ -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 -
@@ -1543,7 +1543,7 @@ comment at the start of cc-engine.el for more info."
 ;;    two newlines with horizontal whitespace between them.
 ;;
 ;;    The reason to include the first following char is to cope with
-;;    "rung positions" that doesn't have any ordinary whitespace.  If
+;;    "rung positions" that don't have any ordinary whitespace.  If
 ;;    `c-is-sws' is put on a token character it does not have
 ;;    `c-in-sws' set simultaneously.  That's the only case when that
 ;;    can occur, and the reason for not extending the `c-in-sws'
@@ -1714,7 +1714,9 @@ comment at the start of cc-engine.el for more info."
     ;; if it's anything that can't start syntactic ws, so we can bail out
     ;; early in the majority of cases when there just are a few ws chars.
     (skip-chars-forward " \t\n\r\f\v")
-    (when (looking-at c-syntactic-ws-start)
+    (when (or (looking-at c-syntactic-ws-start)
+             (and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re)))
 
       (setq rung-end-pos (min (1+ (point)) (point-max)))
       (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
@@ -1733,6 +1735,10 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; In the following while form, we move over a "ladder" and
+           ;; following simple WS each time round the loop, appending the WS
+           ;; onto the ladder, joining adjacent ladders, and terminating when
+           ;; there is no more WS or we reach EOB.
            (while
                (when (and rung-is-marked
                           (get-text-property (point) 'c-in-sws))
@@ -1776,6 +1782,7 @@ comment at the start of cc-engine.el for more info."
                            (setq rung-pos (point)
                                  last-put-in-sws-pos rung-pos)))
 
+           ;; Now move over any comments (x)or a CPP construct.
            (setq simple-ws-end (point))
            (c-forward-comments)
 
@@ -1801,6 +1808,13 @@ comment at the start of cc-engine.el for more info."
              (forward-line 1)
              (setq safe-start t)
              ;; Don't cache at eob in case the buffer is narrowed.
+             (not (eobp)))
+
+            ((and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re))
+             ;; Skip over a noise macro.
+             (goto-char (match-end 1))
+             (setq safe-start t)
              (not (eobp)))))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -1907,8 +1921,11 @@ comment at the start of cc-engine.el for more info."
     (when (and (not (bobp))
               (save-excursion
                 (backward-char)
-                (looking-at c-syntactic-ws-end)))
-
+                (or (looking-at c-syntactic-ws-end)
+                    (and c-opt-cpp-prefix
+                         (looking-at c-symbol-char-key)
+                         (progn (c-beginning-of-current-token)
+                                (looking-at c-noise-macro-name-re))))))
       ;; Try to find a rung position in the simple ws preceding point, so that
       ;; we can get a cache hit even if the last bit of the simple ws has
       ;; changed recently.
@@ -1927,6 +1944,9 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; Each time round the next while form, we move back over a ladder
+           ;; and append any simple WS preceding it, if possible joining with
+           ;; the previous ladder.
            (while
                (when (and rung-is-marked
                           (not (bobp))
@@ -2035,6 +2055,15 @@ comment at the start of cc-engine.el for more info."
              ;; narrowed out, and we can't risk marking the simple ws
              ;; at the end of it.
              (goto-char next-rung-pos)
+             t)
+
+            ((and c-opt-cpp-prefix
+                  (save-excursion
+                    (and (< (skip-syntax-backward "w_") 0)
+                         (progn (setq next-rung-pos (point))
+                                (looking-at c-noise-macro-name-re)))))
+             ;; Skipped over a noise macro
+             (goto-char next-rung-pos)
              t)))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -2523,6 +2552,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 +2626,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)))
 
 
@@ -3203,7 +3270,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
@@ -3226,9 +3293,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'.
@@ -3240,7 +3306,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)))))
@@ -3298,7 +3364,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
@@ -3319,9 +3384,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)
@@ -3791,8 +3860,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)
@@ -3959,7 +4028,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)
@@ -3967,7 +4036,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
@@ -5537,8 +5606,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
@@ -5555,40 +5625,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
@@ -5628,7 +5701,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.
 
@@ -5742,8 +5836,10 @@ comment at the start of cc-engine.el for more info."
                               `(c-forward-type)
                             `(c-forward-name)))
                nil
-             (and (looking-at c-keywords-regexp)
-                  (c-forward-keyword-clause 1))))
+             (cond ((looking-at c-keywords-regexp)
+                    (c-forward-keyword-clause 1))
+                   ((looking-at c-noise-macro-with-parens-name-re)
+                    (c-forward-noise-clause)))))
      (when (memq res '(t known found prefix))
        ,(when (eq type 'ref)
          `(when c-record-type-identifiers
@@ -5765,6 +5861,17 @@ comment at the start of cc-engine.el for more info."
                 (c-forward-syntactic-ws)
                 (c-forward-keyword-prefixed-id ,type)))))
 
+(defun c-forward-noise-clause ()
+  ;; Point is at a c-noise-macro-with-parens-names macro identifier.  Go
+  ;; forward over this name, any parenthesis expression which follows it, and
+  ;; any syntactic WS, ending up at the next token.  If there is an unbalanced
+  ;; paren expression, leave point at it.  Always Return t.
+  (c-forward-token-2)
+  (if (and (eq (char-after) ?\()
+          (c-go-list-forward))
+      (c-forward-syntactic-ws))
+  t)
+
 (defun c-forward-keyword-clause (match)
   ;; Submatch MATCH in the current match data is assumed to surround a
   ;; token.  If it's a keyword, move over it and any immediately
@@ -5924,7 +6031,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
@@ -5991,7 +6098,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
@@ -5999,7 +6109,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.
@@ -6019,15 +6131,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
@@ -6047,7 +6157,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)
 
@@ -6063,11 +6175,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) ?&)
@@ -6385,6 +6502,13 @@ comment at the start of cc-engine.el for more info."
                                     ; "typedef".
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
+
+      (while (cond
+             ((looking-at c-decl-hangon-key)
+              (c-forward-keyword-clause 1))
+             ((looking-at c-noise-macro-with-parens-name-re)
+              (c-forward-noise-clause))))
+
       (setq pos (point))
 
       (setq name-res (c-forward-name))
@@ -6576,16 +6700,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),
@@ -6626,49 +6756,65 @@ 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) ?:)
+                        (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) ?:)
+                          (c-just-after-func-arglist-p)))))
 
+           (and at-top-level level-plausible)))
     (or res (goto-char here))
     res))
 
@@ -6715,6 +6861,129 @@ 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
+                 (cond
+                  ((looking-at c-decl-hangon-key)
+                   (c-forward-keyword-clause 1))
+                  ((looking-at c-noise-macro-with-parens-name-re)
+                   (c-forward-noise-clause))
+                  ((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)
+                   t)))
+
+          ;; 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
+             (while (cond
+                     ((looking-at c-decl-hangon-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
+             (<= (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
@@ -6872,19 +7141,24 @@ comment at the start of cc-engine.el for more info."
     ;; macros like __INLINE__, so we recognize both types and known
     ;; specifiers after them too.
     (while
-       (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+       (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
 
+         (cond
          ;; Look for a specifier keyword clause.
-         (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]+")))
+          ((or (looking-at c-prefix-spec-kwds-re)
+               (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)))
+                 (setq at-typedef t)))
            (setq kwd-sym (c-keyword-sym (match-string 1)))
            (save-excursion
              (c-forward-keyword-clause 1)
              (setq kwd-clause-end (point))))
+          ((looking-at c-noise-macro-with-parens-name-re)
+           (setq noise-start (point))
+           (c-forward-noise-clause)
+           (setq kwd-clause-end (point))))
 
          (when (setq found-type (c-forward-type t)) ; brace-block-too
            ;; Found a known or possible type or a prefix of a known type.
@@ -6922,16 +7196,17 @@ comment at the start of cc-engine.el for more info."
                  backup-at-type-decl nil
                  backup-maybe-typeless nil))
 
-         (if kwd-sym
+         (if (or kwd-sym noise-start)
              (progn
                ;; Handle known specifier keywords and
                ;; `c-decl-hangon-kwds' which can occur after known
                ;; types.
 
-               (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
-                   ;; It's a hang-on keyword that can occur anywhere.
+               (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+                       noise-start)
+                   ;; It's a hang-on keyword or noise clause that can occur
+                   ;; anywhere.
                    (progn
-                     (setq at-decl-or-cast t)
                      (if at-type
                          ;; Move the identifier start position if
                          ;; we've passed a type.
@@ -6983,8 +7258,11 @@ comment at the start of cc-engine.el for more info."
       ;; If a known type was found, we still need to skip over any
       ;; hangon keyword clauses after it.  Otherwise it has already
       ;; been done in the loop above.
-      (while (looking-at c-decl-hangon-key)
-       (c-forward-keyword-clause 1))
+      (while
+         (cond ((looking-at c-decl-hangon-key)
+                (c-forward-keyword-clause 1))
+               ((looking-at c-noise-macro-with-parens-name-re)
+                (c-forward-noise-clause))))
       (setq id-start (point)))
 
      ((eq at-type 'prefix)
@@ -7070,7 +7348,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) ?\()
@@ -7123,7 +7401,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)
@@ -7197,7 +7475,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
@@ -7521,7 +7799,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)
@@ -7918,7 +8196,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)
@@ -8008,6 +8286,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))))
@@ -8068,14 +8348,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
@@ -8084,8 +8364,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
@@ -8104,8 +8388,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.
@@ -8151,21 +8439,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))
 
@@ -8433,7 +8758,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)
@@ -8441,7 +8766,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
@@ -8704,6 +9029,11 @@ comment at the start of cc-engine.el for more info."
           t)
          ((looking-at c-after-brace-list-key) t)
          ((looking-at c-brace-list-key) nil)
+         ((eq (char-after) ?\()
+          (and (eq (c-backward-token-2) 0)
+               (or (looking-at c-decl-hangon-key)
+                   (looking-at c-noise-macro-with-parens-name-re))))
+
          ((and c-recognize-<>-arglists
                (eq (char-after) ?<)
                (looking-at "\\s("))
@@ -8960,7 +9290,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))))
 
@@ -9023,6 +9353,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
@@ -9570,7 +9905,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
@@ -9825,7 +10159,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)
@@ -9841,6 +10187,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
@@ -9947,9 +10294,11 @@ comment at the start of cc-engine.el for more info."
           ;; CASE 5A.3: brace list open
           ((save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
              (setq placeholder (c-point 'boi))
              (or (consp special-brace-list)
                  (and (or (save-excursion
@@ -10001,9 +10350,11 @@ comment at the start of cc-engine.el for more info."
           (t
            (save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
              (c-add-syntax 'defun-open (c-point 'boi))
              ;; Bogus to use bol here, but it's the legacy.  (Resolved,
              ;; 2007-11-09)
@@ -10013,7 +10364,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
@@ -10633,9 +10985,11 @@ comment at the start of cc-engine.el for more info."
            (c-beginning-of-statement-1
             (c-safe-position (1- containing-sexp) paren-state))
            (c-forward-token-2 0)
-           (while (looking-at c-specifier-key)
-             (goto-char (match-end 1))
-             (c-forward-syntactic-ws))
+           (while (cond
+                   ((looking-at c-specifier-key)
+                    (c-forward-keyword-clause 1))
+                   ((looking-at c-noise-macro-with-parens-name-re)
+                    (c-forward-noise-clause))))
            (c-add-syntax 'brace-list-open (c-point 'boi))))
 
         ;; CASE 9B: brace-list-close brace