]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Merge from emacs-24; up to 2014-07-26T11:58:24Z!schwab@linux-m68k.org
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 3d6398014dbbd16d3c31472dff243648bb582ffd..9a2531d1e9933b731b54a4a1426d9c21e99703da 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode -*- coding: utf-8 -*-
 
-;; Copyright (C) 1985, 1987, 1992-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1987, 1992-2014 Free Software Foundation, Inc.
 
 ;; Authors:    2001- Alan Mackenzie
 ;;             1998- Martin Stjernholm
 (cc-require-when-compile 'cc-langs)
 (cc-require 'cc-vars)
 
+(eval-when-compile (require 'cl))
+
 \f
 ;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
 
 (defmacro c-declare-lang-variables ()
   `(progn
-     ,@(apply 'nconc
-             (mapcar (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)))))
+     ,@(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
@@ -826,7 +827,6 @@ comment at the start of cc-engine.el for more info."
            ;; Record this as the first token if not starting inside it.
            (setq tok start))
 
-
        ;; The following while loop goes back one sexp (balanced parens,
        ;; etc. with contents, or symbol or suchlike) each iteration.  This
        ;; movement is accomplished with a call to c-backward-sexp approx 170
@@ -1033,7 +1033,10 @@ comment at the start of cc-engine.el for more info."
                         ;; Just gone back over a brace block?
                         ((and
                           (eq (char-after) ?{)
-                          (not (c-looking-at-inexpr-block lim nil t)))
+                          (not (c-looking-at-inexpr-block lim nil t))
+                          (save-excursion
+                            (c-backward-token-2 1 t nil)
+                            (not (looking-at "=\\([^=]\\|$\\)"))))
                          (save-excursion
                            (c-forward-sexp) (point)))
                         ;; Just gone back over some paren block?
@@ -1261,12 +1264,15 @@ comment at the start of cc-engine.el for more info."
              ;; looking for more : and ?.
              (setq c-maybe-labelp nil
                    skip-chars (substring c-stmt-delim-chars 0 -2)))
-            ;; At a CPP construct?
-            ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol)
-                  (save-excursion
-                    (forward-line 0)
-                    (looking-at c-opt-cpp-prefix)))
-             (c-end-of-macro))
+            ;; At a CPP construct or a "#" or "##" operator?
+            ((and c-opt-cpp-symbol (looking-at c-opt-cpp-symbol))
+             (if (save-excursion
+                   (skip-chars-backward " \t")
+                   (and (bolp)
+                        (or (bobp)
+                            (not (eq (char-before (1- (point))) ?\\)))))
+                 (c-end-of-macro)
+               (skip-chars-forward c-opt-cpp-symbol)))
             ((memq (char-after) non-skip-list)
              (throw 'done (point)))))
          ;; In trailing space after an as yet undetected virtual semicolon?
@@ -2153,7 +2159,6 @@ comment at the start of cc-engine.el for more info."
 ;; the middle of the desert, as long as it is not within a brace pair
 ;; recorded in `c-state-cache' or a paren/bracket pair.
 
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; We maintain a simple cache of positions which aren't in a literal, so as to
 ;; speed up testing for non-literality.
@@ -2216,7 +2221,9 @@ comment at the start of cc-engine.el for more info."
        ((and (not not-in-delimiter)    ; inside a comment starter
             (not (bobp))
             (progn (backward-char)
-                   (looking-at c-comment-start-regexp)))
+                   (and (not (and (memq 'category-properties c-emacs-features)
+                                  (looking-at "\\s!")))
+                        (looking-at c-comment-start-regexp))))
        (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
              co-st (point))
        (forward-comment 1)
@@ -2549,8 +2556,11 @@ comment at the start of cc-engine.el for more info."
   ;; The return value is a list, one of the following:
   ;;
   ;; o - ('forward START-POINT) - scan forward from START-POINT,
-  ;;    which is not less than the highest position in `c-state-cache' below here.
+  ;;    which is not less than the highest position in `c-state-cache' below HERE,
+  ;;     which is after GOOD-POS.
   ;; o - ('backward nil) - scan backwards (from HERE).
+  ;; o - ('back-and-forward START-POINT) - like 'forward, but when HERE is earlier
+  ;;     than GOOD-POS.
   ;; 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.
@@ -2565,9 +2575,9 @@ comment at the start of cc-engine.el for more info."
      ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting.
       (setq strategy 'backward))
      (t
-      (setq strategy 'forward
+      (setq strategy 'back-and-forward
            start-point cache-pos)))
-    (list strategy (and (eq strategy 'forward) start-point))))
+    (list strategy start-point)))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2769,7 +2779,7 @@ comment at the start of cc-engine.el for more info."
        paren+1               ; Pos after some opening or closing paren.
        paren+1s              ; A list of `paren+1's; used to determine a
                              ; good-pos.
-       bra+1 ce+1            ; just after L/R bra-ces.
+       bra+1                 ; just after L bra-ce.
        bra+1s                ; list of OLD values of bra+1.
        mstart)               ; start of a macro.
 
@@ -2839,9 +2849,10 @@ comment at the start of cc-engine.el for more info."
 
 (defun c-remove-stale-state-cache (start-point here pps-point)
   ;; Remove stale entries from the `c-cache-state', i.e. those which will
-  ;; not be in it when it is amended for position HERE.  Additionally, the
-  ;; "outermost" open-brace entry before HERE will be converted to a cons if
-  ;; the matching close-brace is scanned.
+  ;; not be in it when it is amended for position HERE.  This may involve
+  ;; replacing a CONS element for a brace pair containing HERE with its car.
+  ;; Additionally, the "outermost" open-brace entry before HERE will be
+  ;; converted to a cons if the matching close-brace is below HERE.
   ;;
   ;; START-POINT is a "maximal" "safe position" - there must be no open
   ;; parens/braces/brackets between START-POINT and HERE.
@@ -2852,7 +2863,7 @@ comment at the start of cc-engine.el for more info."
   ;; adjust it to get outside a string/comment.         (Sorry about this!  The code
   ;; needs to be FAST).
   ;;
-  ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where
+  ;; Return a list (GOOD-POS SCAN-BACK-POS CONS-SEPARATED PPS-STATE), where
   ;; o - GOOD-POS is a position where the new value `c-state-cache' is known
   ;;   to be good (we aim for this to be as high as possible);
   ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
@@ -2860,6 +2871,9 @@ comment at the start of cc-engine.el for more info."
   ;;   position to scan backwards from.  It is the position of the "{" of the
   ;;   last element to be removed from `c-state-cache', when that elt is a
   ;;   cons, otherwise nil.
+  ;; o - CONS-SEPARATED is t when a cons element in `c-state-cache' has been
+  ;;   replaced by its car because HERE lies inside the brace pair represented
+  ;;   by the cons.
   ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
   (save-excursion
     (save-restriction
@@ -2887,6 +2901,7 @@ comment at the start of cc-engine.el for more info."
             pos
             upper-lim     ; ,beyond which `c-state-cache' entries are removed
             scan-back-pos
+            cons-separated
             pair-beg pps-point-state target-depth)
 
        ;; Remove entries beyond HERE.  Also remove any entries inside
@@ -2908,7 +2923,8 @@ comment at the start of cc-engine.el for more info."
                   (consp (car c-state-cache))
                   (> (cdar c-state-cache) upper-lim))
          (setcar c-state-cache (caar c-state-cache))
-         (setq scan-back-pos (car c-state-cache)))
+         (setq scan-back-pos (car c-state-cache)
+               cons-separated t))
 
        ;; The next loop jumps forward out of a nested level of parens each
        ;; time round; the corresponding elements in `c-state-cache' are
@@ -2980,7 +2996,7 @@ comment at the start of cc-engine.el for more info."
          (setq c-state-cache (cons (cons pair-beg pos)
                                    c-state-cache)))
 
-       (list pos scan-back-pos pps-state)))))
+       (list pos scan-back-pos cons-separated pps-state)))))
 
 (defun c-remove-stale-state-cache-backwards (here)
   ;; Strip stale elements of `c-state-cache' by moving backwards through the
@@ -3180,7 +3196,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 ((here-bol (c-point 'bol here))
+    (let (open-paren-in-column-0-is-defun-start
+         (here-bol (c-point 'bol here))
          too-high-pa             ; recorded {/(/[ next above here, or nil.
          dropped-cons            ; was the last removed element a brace pair?
          pa)
@@ -3251,6 +3268,7 @@ 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
@@ -3260,6 +3278,7 @@ comment at the start of cc-engine.el for more info."
                     ; are no open parens/braces between it and HERE.
         bopl-state
         res
+        cons-separated
         scan-backward-pos scan-forward-p) ; used for 'backward.
     ;; If POINT-MIN has changed, adjust the cache
     (unless (= (point-min) c-state-point-min)
@@ -3272,13 +3291,15 @@ comment at the start of cc-engine.el for more info."
 
     ;; SCAN!
     (cond
-     ((eq strategy 'forward)
+     ((memq strategy '(forward back-and-forward))
       (setq res (c-remove-stale-state-cache start-point here here-bopl))
       (setq cache-pos (car res)
            scan-backward-pos (cadr res)
-           bopl-state (car (cddr res))) ; will be nil if (< here-bopl
+           cons-separated (car (cddr res))
+           bopl-state (cadr (cddr res))) ; will be nil if (< here-bopl
                                        ; start-point)
-      (if scan-backward-pos
+      (if (and scan-backward-pos
+              (or cons-separated (eq strategy 'forward))) ;scan-backward-pos
          (c-append-lower-brace-pair-to-state-cache scan-backward-pos here))
       (setq good-pos
            (c-append-to-state-cache cache-pos here))
@@ -3370,6 +3391,7 @@ comment at the start of cc-engine.el for more info."
 
 (defvar c-parse-state-point nil)
 (defvar c-parse-state-state nil)
+(make-variable-buffer-local 'c-parse-state-state)
 (defun c-record-parse-state-state ()
   (setq c-parse-state-point (point))
   (setq c-parse-state-state
@@ -3694,7 +3716,7 @@ comment at the start of cc-engine.el for more info."
          (while (let ((pos (or (and (looking-at c-nonsymbol-token-regexp)
                                     (match-end 0))
                                ;; `c-nonsymbol-token-regexp' should always match
-                               ;; since we've skipped backward over punctuator
+                               ;; since we've skipped backward over punctuation
                                ;; or paren syntax, but consume one char in case
                                ;; it doesn't so that we don't leave point before
                                ;; some earlier incorrect token.
@@ -3718,7 +3740,7 @@ comment at the start of cc-engine.el for more info."
                    (if (looking-at c-nonsymbol-token-regexp)
                        (goto-char (match-end 0))
                      ;; `c-nonsymbol-token-regexp' should always match since
-                     ;; we've skipped backward over punctuator or paren
+                     ;; we've skipped backward over punctuation or paren
                      ;; syntax, but move forward in case it doesn't so that
                      ;; we don't leave point earlier than we started with.
                      (forward-char))
@@ -4144,7 +4166,7 @@ comment at the start of cc-engine.el for more info."
   ;; Use `parse-partial-sexp' from a safe position down to the point to check
   ;; if it's outside comments and strings.
   (save-excursion
-    (let ((pos (point)) safe-pos state pps-end-pos)
+    (let ((pos (point)) safe-pos state)
       ;; Pick a safe position as close to the point as possible.
       ;;
       ;; FIXME: Consult `syntax-ppss' here if our cache doesn't give a good
@@ -4226,16 +4248,18 @@ comment at the start of cc-engine.el for more info."
          ;; loops when it hasn't succeeded.
          (while
              (and
-              (< (skip-chars-backward skip-chars limit) 0)
+              (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
-                 ;; Don't stop inside a literal
-                 ((setq lit-beg (c-ssb-lit-begin))
-                  (goto-char lit-beg)
-                  t)
-
                  ((and paren-level
                        (save-excursion
                          (setq state-2 (parse-partial-sexp
@@ -4729,6 +4753,11 @@ comment at the start of cc-engine.el for more info."
   ;; inside `c-find-decl-spots'.  The point is left at `cfd-match-pos'
   ;; if there is a match, otherwise at `cfd-limit'.
   ;;
+  ;; The macro moves point forward to the next putative start of a declaration
+  ;; or cfd-limit.  This decl start is the next token after a "declaration
+  ;; prefix".  The declaration prefix is the earlier of `cfd-prop-match' and
+  ;; `cfd-re-match'.  `cfd-match-pos' is set to the decl prefix.
+  ;;
   ;; This macro might do hidden buffer changes.
 
   '(progn
@@ -4750,34 +4779,47 @@ comment at the start of cc-engine.el for more info."
        (if (> cfd-re-match-end (point))
           (goto-char cfd-re-match-end))
 
-       (while (if (setq cfd-re-match-end
-                       (re-search-forward c-decl-prefix-or-start-re
-                                          cfd-limit 'move))
-
-                 ;; Match.  Check if it's inside a comment or string literal.
-                 (c-got-face-at
-                  (if (setq cfd-re-match (match-end 1))
-                      ;; Matched the end of a token preceding a decl spot.
-                      (progn
-                        (goto-char cfd-re-match)
-                        (1- cfd-re-match))
-                    ;; Matched a token that start a decl spot.
-                    (goto-char (match-beginning 0))
-                    (point))
-                  c-literal-faces)
-
-               ;; No match.  Finish up and exit the loop.
-               (setq cfd-re-match cfd-limit)
-               nil)
-
-        ;; Skip out of comments and string literals.
-        (while (progn
-                 (goto-char (next-single-property-change
-                             (point) 'face nil cfd-limit))
-                 (and (< (point) cfd-limit)
-                      (c-got-face-at (point) c-literal-faces)))))
+       ;; Each time round, the next `while' moves forward over a pseudo match
+       ;; of `c-decl-prefix-or-start-re' which is either inside a literal, or
+       ;; is a ":" not preceded by "public", etc..  `cfd-re-match' and
+       ;; `cfd-re-match-end' get set.
+       (while
+          (progn
+            (setq cfd-re-match-end (re-search-forward c-decl-prefix-or-start-re
+                                                      cfd-limit 'move))
+            (cond
+             ((null cfd-re-match-end)
+              ;; No match.  Finish up and exit the loop.
+              (setq cfd-re-match cfd-limit)
+              nil)
+             ((c-got-face-at
+               (if (setq cfd-re-match (match-end 1))
+                   ;; Matched the end of a token preceding a decl spot.
+                   (progn
+                     (goto-char cfd-re-match)
+                     (1- cfd-re-match))
+                 ;; Matched a token that start a decl spot.
+                 (goto-char (match-beginning 0))
+                 (point))
+               c-literal-faces)
+              ;; Pseudo match inside a comment or string literal.  Skip out
+              ;; of comments and string literals.
+              (while (progn
+                       (goto-char (next-single-property-change
+                                   (point) 'face nil cfd-limit))
+                       (and (< (point) cfd-limit)
+                            (c-got-face-at (point) c-literal-faces))))
+              t)                     ; Continue the loop over pseudo matches.
+             ((and (match-string 1)
+                   (string= (match-string 1) ":")
+                   (save-excursion
+                     (or (/= (c-backward-token-2 2) 0) ; no search limit.  :-(
+                         (not (looking-at c-decl-start-colon-kwd-re)))))
+              ;; Found a ":" which isn't part of "public:", etc.
+              t)
+             (t nil)))) ;; Found a real match.  Exit the pseudo-match loop.
 
-       ;; If we matched at the decl start, we have to back up over the
+       ;; If our match was at the decl start, we have to back up over the
        ;; preceding syntactic ws to set `cfd-match-pos' and to catch
        ;; any decl spots in the syntactic ws.
        (unless cfd-re-match
@@ -4818,14 +4860,17 @@ comment at the start of cc-engine.el for more info."
   ;; it should return non-nil to ensure that the next search will find them.
   ;;
   ;; Such a spot is:
-  ;; o  The first token after bob.
-  ;; o  The first token after the end of submatch 1 in
-  ;;    `c-decl-prefix-or-start-re' when that submatch matches.
-  ;; o  The start of each `c-decl-prefix-or-start-re' match when
-  ;;    submatch 1 doesn't match.
-  ;; o  The first token after the end of each occurrence of the
-  ;;    `c-type' text property with the value `c-decl-end', provided
-  ;;    `c-type-decl-end-used' is set.
+  ;; o The first token after bob.
+  ;; o The first token after the end of submatch 1 in
+  ;;   `c-decl-prefix-or-start-re' when that submatch matches.  This
+  ;;   submatch is typically a (L or R) brace or paren, a ;, or a ,.
+  ;; o The start of each `c-decl-prefix-or-start-re' match when
+  ;;   submatch 1 doesn't match.  This is, for example, the keyword
+  ;;   "class" in Pike.
+  ;; o The start of a previously recognized declaration; "recognized"
+  ;;   means that the last char of the previous token has a `c-type'
+  ;;   text property with the value `c-decl-end'; this only holds
+  ;;   when `c-type-decl-end-used' is set.
   ;;
   ;; Only a spot that match CFD-DECL-RE and whose face is in the
   ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called.  The face
@@ -4857,7 +4902,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This function might do hidden buffer changes.
 
-  (let ((cfd-start-pos (point))
+  (let ((cfd-start-pos (point))                ; never changed
        (cfd-buffer-end (point-max))
        ;; The end of the token preceding the decl spot last found
        ;; with `c-decl-prefix-or-start-re'.  `cfd-limit' if there's
@@ -4896,10 +4941,20 @@ comment at the start of cc-engine.el for more info."
       ;; statement or declaration, which is earlier than the first
       ;; returned match.
 
+      ;; This `cond' moves back over any literals or macros.  It has special
+      ;; handling for when the region being searched is entirely within a
+      ;; macro.  It sets `cfd-continue-pos' (unless we've reached
+      ;; `cfd-limit').
       (cond
        ;; First we need to move to a syntactically relevant position.
        ;; Begin by backing out of comment or string literals.
+       ;;
+       ;; This arm of the cond actually triggers if we're in a literal,
+       ;; and cfd-limit is at most at BONL.
        ((and
+        ;; This arm of the `and' moves backwards out of a literal when
+        ;; the face at point is a literal face.  In this case, its value
+        ;; is always non-nil.
         (when (c-got-face-at (point) c-literal-faces)
           ;; Try to use the faces to back up to the start of the
           ;; literal.  FIXME: What if the point is on a declaration
@@ -4928,7 +4983,7 @@ comment at the start of cc-engine.el for more info."
             (let ((range (c-literal-limits)))
               (if range (goto-char (car range)))))
 
-          (setq start-in-literal (point)))
+          (setq start-in-literal (point))) ; end of `and' arm.
 
         ;; The start is in a literal.  If the limit is in the same
         ;; one we don't have to find a syntactic position etc.  We
@@ -4943,18 +4998,18 @@ comment at the start of cc-engine.el for more info."
                                (point) 'face nil cfd-limit))
                    (and (< (point) cfd-limit)
                         (c-got-face-at (point) c-literal-faces))))
-          (= (point) cfd-limit)))
+          (= (point) cfd-limit)))      ; end of `cond' arm condition
 
        ;; Completely inside a literal.  Set up variables to trig the
        ;; (< cfd-continue-pos cfd-start-pos) case below and it'll
        ;; find a suitable start position.
-       (setq cfd-continue-pos start-in-literal))
+       (setq cfd-continue-pos start-in-literal)) ; end of `cond' arm
 
        ;; Check if the region might be completely inside a macro, to
        ;; optimize that like the completely-inside-literal above.
        ((save-excursion
          (and (= (forward-line 1) 0)
-              (bolp)                   ; forward-line has funny behavior at eob.
+              (bolp)                 ; forward-line has funny behavior at eob.
               (>= (point) cfd-limit)
               (progn (backward-char)
                      (eq (char-before) ?\\))))
@@ -4964,6 +5019,8 @@ comment at the start of cc-engine.el for more info."
        (setq cfd-continue-pos (1- cfd-start-pos)
              start-in-macro t))
 
+       ;; The default arm of the `cond' moves back over any macro we're in
+       ;; and over any syntactic WS.  It sets `c-find-decl-syntactic-pos'.
        (t
        ;; Back out of any macro so we don't miss any declaration
        ;; that could follow after it.
@@ -5010,10 +5067,10 @@ comment at the start of cc-engine.el for more info."
                  (< (point) cfd-limit))
            ;; Do an initial search now.  In the bob case above it's
            ;; only done to search for a `c-decl-end' spot.
-           (c-find-decl-prefix-search))
+           (c-find-decl-prefix-search)) ; sets cfd-continue-pos
 
          (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos)
-                                          cfd-match-pos)))))
+                                          cfd-match-pos))))) ; end of `cond'
 
       ;; Advance `cfd-continue-pos' if it's before the start position.
       ;; The closest continue position that might have effect at or
@@ -5072,7 +5129,7 @@ comment at the start of cc-engine.el for more info."
          ;; `cfd-match-pos' so we can continue at the start position.
          ;; (Note that we don't get here if the first match is below
          ;; it.)
-         (goto-char cfd-start-pos)))
+         (goto-char cfd-start-pos)))   ; end of `cond'
 
        ;; Delete found matches if they are before our new continue
        ;; position, so that `c-find-decl-prefix-search' won't back up
@@ -5081,7 +5138,7 @@ comment at the start of cc-engine.el for more info."
        (when (and cfd-re-match (< cfd-re-match cfd-continue-pos))
          (setq cfd-re-match nil))
        (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos))
-         (setq cfd-prop-match nil)))
+         (setq cfd-prop-match nil)))   ; end of `when'
 
       (if syntactic-pos
          ;; This is the normal case and we got a proper syntactic
@@ -5102,9 +5159,10 @@ comment at the start of cc-engine.el for more info."
        ;; good start position for the search, so do it.
        (c-find-decl-prefix-search)))
 
-    ;; Now loop.  Round what?  (ACM, 2006/7/5).  We already got the first match.
-
+    ;; Now loop, one decl spot per iteration.  We already have the first
+    ;; match in `cfd-match-pos'.
     (while (progn
+            ;; Go forward over "false matches", one per iteration.
             (while (and
                     (< cfd-match-pos cfd-limit)
 
@@ -5145,10 +5203,10 @@ comment at the start of cc-engine.el for more info."
                          (goto-char cfd-continue-pos)
                          t)))
 
-                    (< (point) cfd-limit))
-              (c-find-decl-prefix-search))
+                    (< (point) cfd-limit)) ; end of "false matches" condition
+              (c-find-decl-prefix-search)) ; end of "false matches" loop
 
-            (< (point) cfd-limit))
+            (< (point) cfd-limit))   ; end of condition for "decl-spot" while
 
       (when (and
             (>= (point) cfd-start-pos)
@@ -5176,7 +5234,7 @@ comment at the start of cc-engine.el for more info."
                   ;; The matched token was the last thing in the macro,
                   ;; so the whole match is bogus.
                   (setq cfd-macro-end 0)
-                  nil))))
+                  nil))))              ; end of when condition
 
        (c-debug-put-decl-spot-faces cfd-match-pos (point))
        (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0))
@@ -5489,8 +5547,6 @@ comment at the start of cc-engine.el for more info."
       (when need-new-end
        (and (> 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
   ;; c-recognize-<>-arglists' is set.  It ensures that no "<" or ">"
@@ -5825,7 +5881,6 @@ 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
        ;; Cover this so that any recorded found type ranges are
        ;; automatically lost if it turns out to not be an angle
@@ -5902,7 +5957,7 @@ 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-cont-regexp)
+                 (if (looking-at c->-op-without->-cont-regexp)
                      (progn
                        (goto-char (match-end 0))
                        t)              ; Continue the loop.
@@ -5951,7 +6006,6 @@ comment at the start of cc-engine.el for more info."
                                       (c-keyword-member
                                        (c-keyword-sym (match-string 1))
                                        'c-<>-type-kwds)))))))
-
                      ;; It was an angle bracket arglist.
                      (setq c-record-found-types subres)
 
@@ -6244,7 +6298,8 @@ comment at the start of cc-engine.el for more info."
   ;;     `*-font-lock-extra-types');
   ;;   o - 'prefix if it's a known prefix of a type;
   ;;   o - 'found if it's a type that matches one in `c-found-types';
-  ;;   o - 'maybe if it's an identifier that might be a type; or
+  ;;   o - 'maybe if it's an identifier that might be a type;
+  ;;   o - 'decltype if it's a decltype(variable) declaration; - or
   ;;   o -  nil if it can't be a type (the point isn't moved then).
   ;;
   ;; The point is assumed to be at the beginning of a token.
@@ -6274,6 +6329,16 @@ comment at the start of cc-engine.el for more info."
        (setq res 'prefix)))
 
     (cond
+     ((looking-at c-typeof-key) ; e.g. C++'s "decltype".
+      (goto-char (match-end 1))
+      (c-forward-syntactic-ws)
+      (setq res (and (eq (char-after) ?\()
+                    (c-safe (c-forward-sexp))
+                    'decltype))
+      (if res
+         (c-forward-syntactic-ws)
+       (goto-char start)))
+
      ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT
                                     ; "typedef".
       (goto-char (match-end 1))
@@ -6400,7 +6465,7 @@ comment at the start of cc-engine.el for more info."
       ;; of these alter the classification of the found type, since
       ;; these operators typically are allowed in normal expressions
       ;; too.
-      (when c-opt-type-suffix-key
+      (when c-opt-type-suffix-key      ; e.g. "..."
        (while (looking-at c-opt-type-suffix-key)
          (goto-char (match-end 1))
          (c-forward-syntactic-ws)))
@@ -6479,6 +6544,15 @@ comment at the start of cc-engine.el for more info."
           (c-go-list-forward)
          t)))
 
+(defmacro c-pull-open-brace (ps)
+  ;; Pull the next open brace from PS (which has the form of paren-state),
+  ;; skipping over any brace pairs.  Returns NIL when PS is exhausted.
+  `(progn
+     (while (consp (car ,ps))
+       (setq ,ps (cdr ,ps)))
+     (prog1 (car ,ps)
+       (setq ,ps (cdr ,ps)))))
+
 (defun c-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
@@ -6603,6 +6677,13 @@ comment at the start of cc-engine.el for more info."
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
   ;;
+  ;;     auto foo = 5;
+  ;;      car ^   ^ point
+  ;;     auto cplusplus_11 (int a, char *b) -> decltype (bar):
+  ;;      car ^                             ^ point
+  ;;
+  ;;
+  ;;
   ;;   The cdr of the return value is non-nil when a
   ;;   `c-typedef-decl-kwds' specifier is found in the declaration.
   ;;   Specifically it is a dotted pair (A . B) where B is t when a
@@ -6668,6 +6749,10 @@ comment at the start of cc-engine.el for more info."
        ;; If `backup-at-type' is nil then the other variables have
        ;; undefined values.
        backup-at-type backup-type-start backup-id-start
+       ;; This stores `kwd-sym' of the symbol before the current one.
+       ;; This is needed to distinguish the C++11 version of "auto" from
+       ;; the pre C++11 meaning.
+       backup-kwd-sym
        ;; Set if we've found a specifier (apart from "typedef") that makes
        ;; the defined identifier(s) types.
        at-type-decl
@@ -6676,6 +6761,10 @@ comment at the start of cc-engine.el for more info."
        ;; Set if we've found a specifier that can start a declaration
        ;; where there's no type.
        maybe-typeless
+       ;; Save the value of kwd-sym between loops of the "Check for a
+       ;; type" loop.  Needed to distinguish a C++11 "auto" from a pre
+       ;; C++11 one.
+       prev-kwd-sym
        ;; If a specifier is found that also can be a type prefix,
        ;; these flags are set instead of those above.  If we need to
        ;; back up an identifier, they are copied to the real flag
@@ -6693,6 +6782,8 @@ comment at the start of cc-engine.el for more info."
        backup-if-not-cast
        ;; For casts, the return position.
        cast-end
+       ;; Have we got a new-style C++11 "auto"?
+       new-style-auto
        ;; Save `c-record-type-identifiers' and
        ;; `c-record-ref-identifiers' since ranges are recorded
        ;; speculatively and should be thrown away if it turns out
@@ -6711,11 +6802,12 @@ comment at the start of cc-engine.el for more info."
        (let* ((start (point)) kwd-sym kwd-clause-end found-type)
 
          ;; Look for a specifier keyword clause.
-         (when (or (looking-at c-prefix-spec-kwds-re)
+         (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]+")))
-           (if (looking-at c-typedef-key)
-               (setq at-typedef t))
+           (save-match-data
+             (if (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)
@@ -6723,6 +6815,12 @@ comment at the start of cc-engine.el for more info."
 
          (when (setq found-type (c-forward-type t)) ; brace-block-too
            ;; Found a known or possible type or a prefix of a known type.
+           (when (and (c-major-mode-is 'c++-mode) ; C++11 style "auto"?
+                      (eq prev-kwd-sym (c-keyword-sym "auto"))
+                      (looking-at "[=(]")) ; FIXME!!! proper regexp.
+             (setq new-style-auto t)
+             (setq found-type nil)
+             (goto-char start))        ; position of foo in "auto foo"
 
            (when at-type
              ;; Got two identifiers with nothing but whitespace
@@ -6741,6 +6839,7 @@ comment at the start of cc-engine.el for more info."
            (setq backup-at-type at-type
                  backup-type-start type-start
                  backup-id-start id-start
+                 backup-kwd-sym kwd-sym
                  at-type found-type
                  type-start start
                  id-start (point)
@@ -6796,6 +6895,7 @@ comment at the start of cc-engine.el for more info."
                    ;; specifier keyword and we know we're in a
                    ;; declaration.
                    (setq at-decl-or-cast t)
+                   (setq prev-kwd-sym kwd-sym)
 
                    (goto-char kwd-clause-end))))
 
@@ -6890,45 +6990,57 @@ comment at the start of cc-engine.el for more info."
          ;; can happen since we don't know if
          ;; `c-restricted-<>-arglists' will be correct inside the
          ;; arglist paren that gets entered.
-         c-parse-and-markup-<>-arglists)
+         c-parse-and-markup-<>-arglists
+         ;; Start of the identifier for which `got-identifier' was set.
+         name-start)
 
       (goto-char id-start)
 
       ;; Skip over type decl prefix operators.  (Note similar code in
       ;; `c-font-lock-declarators'.)
-      (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.
-                     (when (setq got-identifier (c-forward-name))
-                       (if (looking-at "\\(::\\)")
-                           ;; We only check for a trailing "::" and
-                           ;; let the "*" that should follow be
-                           ;; matched in the next round.
-                           (progn (setq got-identifier nil) t)
-                         ;; It turned out to be the real identifier,
-                         ;; so stop.
-                         nil))
-                   t))
-
-       (if (eq (char-after) ?\()
+      (if (and c-recognize-typeless-decls
+              (equal c-type-decl-prefix-key "\\<\\>"))
+         (when (eq (char-after) ?\()
            (progn
              (setq paren-depth (1+ paren-depth))
-             (forward-char))
-         (unless got-prefix-before-parens
-           (setq got-prefix-before-parens (= paren-depth 0)))
-         (setq got-prefix t)
-         (goto-char (match-end 1)))
-       (c-forward-syntactic-ws))
+             (forward-char)))
+       (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.
+                       (when (progn (setq pos (point))
+                                    (setq got-identifier (c-forward-name)))
+                         (setq name-start pos)
+                         (if (looking-at "\\(::\\)")
+                             ;; We only check for a trailing "::" and
+                             ;; let the "*" that should follow be
+                             ;; matched in the next round.
+                             (progn (setq got-identifier nil) t)
+                           ;; It turned out to be the real identifier,
+                           ;; so stop.
+                           nil))
+                     t))
+
+         (if (eq (char-after) ?\()
+             (progn
+               (setq paren-depth (1+ paren-depth))
+               (forward-char))
+           (unless got-prefix-before-parens
+             (setq got-prefix-before-parens (= paren-depth 0)))
+           (setq got-prefix t)
+           (goto-char (match-end 1)))
+         (c-forward-syntactic-ws)))
 
       (setq got-parens (> paren-depth 0))
 
       ;; Skip over an identifier.
       (or got-identifier
          (and (looking-at c-identifier-start)
-              (setq got-identifier (c-forward-name))))
+              (setq pos (point))
+              (setq got-identifier (c-forward-name))
+              (setq name-start pos)))
 
       ;; Skip over type decl suffix operators.
       (while (if (looking-at c-type-decl-suffix-key)
@@ -6975,70 +7087,84 @@ comment at the start of cc-engine.el for more info."
 
        (c-forward-syntactic-ws))
 
-      (when (and (or maybe-typeless backup-maybe-typeless)
-                (not got-identifier)
-                (not got-prefix)
-                at-type)
+      (when (or (and new-style-auto
+                    (looking-at c-auto-ops-re))
+               (and (or maybe-typeless backup-maybe-typeless)
+                    (not got-identifier)
+                    (not got-prefix)
+                    at-type))
        ;; Have found no identifier but `c-typeless-decl-kwds' has
        ;; matched so we know we're inside a declaration.  The
        ;; preceding type must be the identifier instead.
        (c-fdoc-shift-type-backward))
 
+      ;; Prepare the "-> type;" for fontification later on.
+      (when (and new-style-auto
+                (looking-at c-haskell-op-re))
+       (save-excursion
+         (goto-char (match-end 0))
+         (c-forward-syntactic-ws)
+         (setq type-start (point))
+         (setq at-type (c-forward-type))))
+
       (setq
        at-decl-or-cast
        (catch 'at-decl-or-cast
 
         ;; CASE 1
-       (when (> paren-depth 0)
-         ;; Encountered something inside parens that isn't matched by
-         ;; the `c-type-decl-*' regexps, so it's not a type decl
-         ;; expression.  Try to skip out to the same paren depth to
-         ;; not confuse the cast check below.
-         (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
-         ;; If we've found a specifier keyword then it's a
-         ;; declaration regardless.
-         (throw 'at-decl-or-cast (eq at-decl-or-cast t)))
-
-       (setq at-decl-end
-             (looking-at (cond ((eq context '<>) "[,>]")
-                               (context "[,\)]")
-                               (t "[,;]"))))
-
-       ;; Now we've collected info about various characteristics of
-       ;; the construct we're looking at.  Below follows a decision
-       ;; tree based on that.  It's ordered to check more certain
-       ;; signs before less certain ones.
-
-       (if got-identifier
-           (progn
+        (when (> paren-depth 0)
+          ;; Encountered something inside parens that isn't matched by
+          ;; the `c-type-decl-*' regexps, so it's not a type decl
+          ;; expression.  Try to skip out to the same paren depth to
+          ;; not confuse the cast check below.
+          (c-safe (goto-char (scan-lists (point) 1 paren-depth)))
+          ;; If we've found a specifier keyword then it's a
+          ;; declaration regardless.
+          (throw 'at-decl-or-cast (eq at-decl-or-cast t)))
+
+        (setq at-decl-end
+              (looking-at (cond ((eq context '<>) "[,>]")
+                                (context "[,\)]")
+                                (t "[,;]"))))
+
+        ;; Now we've collected info about various characteristics of
+        ;; the construct we're looking at.  Below follows a decision
+        ;; tree based on that.  It's ordered to check more certain
+        ;; signs before less certain ones.
+
+        (if got-identifier
+            (progn
 
-             ;; CASE 2
-             (when (and (or at-type maybe-typeless)
-                        (not (or got-prefix got-parens)))
-               ;; Got another identifier directly after the type, so it's a
-               ;; declaration.
-               (throw 'at-decl-or-cast t))
-
-             (when (and got-parens
-                        (not got-prefix)
-                        (not got-suffix-after-parens)
-                        (or backup-at-type
-                            maybe-typeless
-                            backup-maybe-typeless))
-               ;; Got a declaration of the form "foo bar (gnu);" where we've
-               ;; recognized "bar" as the type and "gnu" as the declarator.
-               ;; In this case it's however more likely that "bar" is the
-               ;; declarator and "gnu" a function argument or initializer (if
-               ;; `c-recognize-paren-inits' is set), since the parens around
-               ;; "gnu" would be superfluous if it's a declarator.  Shift the
-               ;; type one step backward.
-               (c-fdoc-shift-type-backward)))
-
-         ;; Found no identifier.
-
-         (if backup-at-type
-             (progn
+              ;; CASE 2
+              (when (and (or at-type maybe-typeless)
+                         (not (or got-prefix got-parens)))
+                ;; Got another identifier directly after the type, so it's a
+                ;; declaration.
+                (throw 'at-decl-or-cast t))
 
+              (when (and got-parens
+                         (not got-prefix)
+                         ;; (not got-suffix-after-parens)
+                         (or backup-at-type
+                             maybe-typeless
+                             backup-maybe-typeless
+                             (eq at-decl-or-cast t)
+                             (save-excursion
+                               (goto-char name-start)
+                               (not (memq (c-forward-type) '(nil maybe))))))
+                ;; Got a declaration of the form "foo bar (gnu);" or "bar
+                ;; (gnu);" where we've recognized "bar" as the type and "gnu"
+                ;; as the declarator.  In this case it's however more likely
+                ;; that "bar" is the declarator and "gnu" a function argument
+                ;; or initializer (if `c-recognize-paren-inits' is set),
+                ;; since the parens around "gnu" would be superfluous if it's
+                ;; a declarator.  Shift the type one step backward.
+                (c-fdoc-shift-type-backward)))
+
+          ;; Found no identifier.
+
+          (if backup-at-type
+              (progn
 
                 ;; CASE 3
                 (when (= (point) start)
@@ -7061,250 +7187,251 @@ comment at the start of cc-engine.el for more info."
                     (setq backup-if-not-cast t)
                     (throw 'at-decl-or-cast t)))
 
-               ;; CASE 4
-               (when (and got-suffix
-                          (not got-prefix)
-                          (not got-parens))
-                 ;; Got a plain list of identifiers followed by some suffix.
-                 ;; If this isn't a cast then the last identifier probably is
-                 ;; the declared one and we should back up to the previous
-                 ;; type.
-                 (setq backup-if-not-cast t)
-                 (throw 'at-decl-or-cast t)))
-
-           ;; CASE 5
-           (when (eq at-type t)
-             ;; If the type is known we know that there can't be any
-             ;; identifier somewhere else, and it's only in declarations in
-             ;; e.g. function prototypes and in casts that the identifier may
-             ;; be left out.
-             (throw 'at-decl-or-cast t))
-
-           (when (= (point) start)
-             ;; Only got a single identifier (parsed as a type so far).
-             ;; CASE 6
-             (if (and
-                  ;; Check that the identifier isn't at the start of an
-                  ;; expression.
-                  at-decl-end
-                  (cond
-                   ((eq context 'decl)
-                    ;; Inside an arglist that contains declarations.  If K&R
-                    ;; style declarations and parenthesis style initializers
-                    ;; aren't allowed then the single identifier must be a
-                    ;; type, else we require that it's known or found
-                    ;; (primitive types are handled above).
-                    (or (and (not c-recognize-knr-p)
-                             (not c-recognize-paren-inits))
-                        (memq at-type '(known found))))
-                   ((eq context '<>)
-                    ;; Inside a template arglist.  Accept known and found
-                    ;; types; other identifiers could just as well be
-                    ;; constants in C++.
-                    (memq at-type '(known found)))))
-                 (throw 'at-decl-or-cast t)
-               ;; CASE 7
-               ;; Can't be a valid declaration or cast, but if we've found a
-               ;; specifier it can't be anything else either, so treat it as
-               ;; an invalid/unfinished declaration or cast.
-               (throw 'at-decl-or-cast at-decl-or-cast))))
-
-         (if (and got-parens
-                  (not got-prefix)
-                  (not context)
-                  (not (eq at-type t))
-                  (or backup-at-type
-                      maybe-typeless
-                      backup-maybe-typeless
-                      (when c-recognize-typeless-decls
-                        (or (not got-suffix)
-                            (not (looking-at
-                                  c-after-suffixed-type-maybe-decl-key))))))
-             ;; Got an empty paren pair and a preceding type that probably
-             ;; really is the identifier.  Shift the type backwards to make
-             ;; the last one the identifier.  This is analogous to the
-             ;; "backtracking" done inside the `c-type-decl-suffix-key' loop
-             ;; above.
-             ;;
-             ;; Exception: In addition to the conditions in that
-             ;; "backtracking" code, do not shift backward if we're not
-             ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]".
-             ;; Since there's no preceding type, the shift would mean that
-             ;; the declaration is typeless.  But if the regexp doesn't match
-             ;; then we will simply fall through in the tests below and not
-             ;; recognize it at all, so it's better to try it as an abstract
-             ;; declarator instead.
-             (c-fdoc-shift-type-backward)
-
-           ;; Still no identifier.
-           ;; CASE 8
-           (when (and got-prefix (or got-parens got-suffix))
-             ;; Require `got-prefix' together with either `got-parens' or
-             ;; `got-suffix' to recognize it as an abstract declarator:
-             ;; `got-parens' only is probably an empty function call.
-             ;; `got-suffix' only can build an ordinary expression together
-             ;; with the preceding identifier which we've taken as a type.
-             ;; We could actually accept on `got-prefix' only, but that can
-             ;; easily occur temporarily while writing an expression so we
-             ;; avoid that case anyway.  We could do a better job if we knew
-             ;; the point when the fontification was invoked.
-             (throw 'at-decl-or-cast t))
-
-           ;; CASE 9
-           (when (and at-type
-                      (not got-prefix)
-                      (not got-parens)
-                      got-suffix-after-parens
-                      (eq (char-after got-suffix-after-parens) ?\())
-             ;; Got a type, no declarator but a paren suffix. I.e. it's a
-             ;; normal function call after all (or perhaps a C++ style object
-             ;; instantiation expression).
-             (throw 'at-decl-or-cast nil))))
-
-       ;; CASE 10
-       (when at-decl-or-cast
-         ;; By now we've located the type in the declaration that we know
-         ;; we're in.
-         (throw 'at-decl-or-cast t))
-
-       ;; CASE 11
-       (when (and got-identifier
-                  (not context)
-                  (looking-at c-after-suffixed-type-decl-key)
-                  (if (and got-parens
+                ;; CASE 4
+                (when (and got-suffix
                            (not got-prefix)
-                           (not got-suffix)
-                           (not (eq at-type t)))
-                      ;; Shift the type backward in the case that there's a
-                      ;; single identifier inside parens.  That can only
-                      ;; occur in K&R style function declarations so it's
-                      ;; more likely that it really is a function call.
-                      ;; Therefore we only do this after
-                      ;; `c-after-suffixed-type-decl-key' has matched.
-                      (progn (c-fdoc-shift-type-backward) t)
-                    got-suffix-after-parens))
-         ;; A declaration according to `c-after-suffixed-type-decl-key'.
-         (throw 'at-decl-or-cast t))
-
-       ;; CASE 12
-       (when (and (or got-prefix (not got-parens))
-                  (memq at-type '(t known)))
-         ;; It's a declaration if a known type precedes it and it can't be a
-         ;; function call.
-         (throw 'at-decl-or-cast t))
-
-       ;; If we get here we can't tell if this is a type decl or a normal
-       ;; expression by looking at it alone.  (That's under the assumption
-       ;; that normal expressions always can look like type decl expressions,
-       ;; which isn't really true but the cases where it doesn't hold are so
-       ;; uncommon (e.g. some placements of "const" in C++) it's not worth
-       ;; the effort to look for them.)
+                           (not got-parens))
+                  ;; Got a plain list of identifiers followed by some suffix.
+                  ;; If this isn't a cast then the last identifier probably is
+                  ;; the declared one and we should back up to the previous
+                  ;; type.
+                  (setq backup-if-not-cast t)
+                  (throw 'at-decl-or-cast t)))
+
+            ;; CASE 5
+            (when (eq at-type t)
+              ;; If the type is known we know that there can't be any
+              ;; identifier somewhere else, and it's only in declarations in
+              ;; e.g. function prototypes and in casts that the identifier may
+              ;; be left out.
+              (throw 'at-decl-or-cast t))
+
+            (when (= (point) start)
+              ;; Only got a single identifier (parsed as a type so far).
+              ;; CASE 6
+              (if (and
+                   ;; Check that the identifier isn't at the start of an
+                   ;; expression.
+                   at-decl-end
+                   (cond
+                    ((eq context 'decl)
+                     ;; Inside an arglist that contains declarations.  If K&R
+                     ;; style declarations and parenthesis style initializers
+                     ;; aren't allowed then the single identifier must be a
+                     ;; type, else we require that it's known or found
+                     ;; (primitive types are handled above).
+                     (or (and (not c-recognize-knr-p)
+                              (not c-recognize-paren-inits))
+                         (memq at-type '(known found))))
+                    ((eq context '<>)
+                     ;; Inside a template arglist.  Accept known and found
+                     ;; types; other identifiers could just as well be
+                     ;; constants in C++.
+                     (memq at-type '(known found)))))
+                  (throw 'at-decl-or-cast t)
+                ;; CASE 7
+                ;; Can't be a valid declaration or cast, but if we've found a
+                ;; specifier it can't be anything else either, so treat it as
+                ;; an invalid/unfinished declaration or cast.
+                (throw 'at-decl-or-cast at-decl-or-cast))))
+
+          (if (and got-parens
+                   (not got-prefix)
+                   (not context)
+                   (not (eq at-type t))
+                   (or backup-at-type
+                       maybe-typeless
+                       backup-maybe-typeless
+                       (when c-recognize-typeless-decls
+                         (or (not got-suffix)
+                             (not (looking-at
+                                   c-after-suffixed-type-maybe-decl-key))))))
+              ;; Got an empty paren pair and a preceding type that probably
+              ;; really is the identifier.  Shift the type backwards to make
+              ;; the last one the identifier.  This is analogous to the
+              ;; "backtracking" done inside the `c-type-decl-suffix-key' loop
+              ;; above.
+              ;;
+              ;; Exception: In addition to the conditions in that
+              ;; "backtracking" code, do not shift backward if we're not
+              ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]".
+              ;; Since there's no preceding type, the shift would mean that
+              ;; the declaration is typeless.  But if the regexp doesn't match
+              ;; then we will simply fall through in the tests below and not
+              ;; recognize it at all, so it's better to try it as an abstract
+              ;; declarator instead.
+              (c-fdoc-shift-type-backward)
+
+            ;; Still no identifier.
+            ;; CASE 8
+            (when (and got-prefix (or got-parens got-suffix))
+              ;; Require `got-prefix' together with either `got-parens' or
+              ;; `got-suffix' to recognize it as an abstract declarator:
+              ;; `got-parens' only is probably an empty function call.
+              ;; `got-suffix' only can build an ordinary expression together
+              ;; with the preceding identifier which we've taken as a type.
+              ;; We could actually accept on `got-prefix' only, but that can
+              ;; easily occur temporarily while writing an expression so we
+              ;; avoid that case anyway.  We could do a better job if we knew
+              ;; the point when the fontification was invoked.
+              (throw 'at-decl-or-cast t))
+
+            ;; CASE 9
+            (when (and at-type
+                       (not got-prefix)
+                       (not got-parens)
+                       got-suffix-after-parens
+                       (eq (char-after got-suffix-after-parens) ?\())
+              ;; Got a type, no declarator but a paren suffix. I.e. it's a
+              ;; normal function call after all (or perhaps a C++ style object
+              ;; instantiation expression).
+              (throw 'at-decl-or-cast nil))))
+
+        ;; CASE 10
+        (when at-decl-or-cast
+          ;; By now we've located the type in the declaration that we know
+          ;; we're in.
+          (throw 'at-decl-or-cast t))
+
+        ;; CASE 11
+        (when (and got-identifier
+                   (not context)
+                   (looking-at c-after-suffixed-type-decl-key)
+                   (if (and got-parens
+                            (not got-prefix)
+                            (not got-suffix)
+                            (not (eq at-type t)))
+                       ;; Shift the type backward in the case that there's a
+                       ;; single identifier inside parens.  That can only
+                       ;; occur in K&R style function declarations so it's
+                       ;; more likely that it really is a function call.
+                       ;; Therefore we only do this after
+                       ;; `c-after-suffixed-type-decl-key' has matched.
+                       (progn (c-fdoc-shift-type-backward) t)
+                     got-suffix-after-parens))
+          ;; A declaration according to `c-after-suffixed-type-decl-key'.
+          (throw 'at-decl-or-cast t))
+
+        ;; CASE 12
+        (when (and (or got-prefix (not got-parens))
+                   (memq at-type '(t known)))
+          ;; It's a declaration if a known type precedes it and it can't be a
+          ;; function call.
+          (throw 'at-decl-or-cast t))
+
+        ;; If we get here we can't tell if this is a type decl or a normal
+        ;; expression by looking at it alone.  (That's under the assumption
+        ;; that normal expressions always can look like type decl expressions,
+        ;; which isn't really true but the cases where it doesn't hold are so
+        ;; uncommon (e.g. some placements of "const" in C++) it's not worth
+        ;; the effort to look for them.)
 
 ;;; 2008-04-16: commented out the next form, to allow the function to recognize
 ;;; "foo (int bar)" in CC (an implicit type (in class foo) without a semicolon)
 ;;; as a(n almost complete) declaration, enabling it to be fontified.
-       ;; CASE 13
-       ;; (unless (or at-decl-end (looking-at "=[^=]"))
-       ;; If this is a declaration it should end here or its initializer(*)
-       ;; should start here, so check for allowed separation tokens.  Note
-       ;; that this rule doesn't work e.g. with a K&R arglist after a
-       ;; function header.
-       ;;
-       ;; *) Don't check for C++ style initializers using parens
-       ;; since those already have been matched as suffixes.
-       ;;
-       ;; If `at-decl-or-cast' is then we've found some other sign that
-       ;; it's a declaration or cast, so then it's probably an
-       ;; invalid/unfinished one.
-       ;;  (throw 'at-decl-or-cast at-decl-or-cast))
-
-       ;; Below are tests that only should be applied when we're certain to
-       ;; not have parsed halfway through an expression.
-
-       ;; CASE 14
-       (when (memq at-type '(t known))
-         ;; The expression starts with a known type so treat it as a
-         ;; declaration.
-         (throw 'at-decl-or-cast t))
-
-       ;; CASE 15
-       (when (and (c-major-mode-is 'c++-mode)
-                  ;; In C++ we check if the identifier is a known type, since
-                  ;; (con|de)structors use the class name as identifier.
-                  ;; We've always shifted over the identifier as a type and
-                  ;; then backed up again in this case.
-                  identifier-type
-                  (or (memq identifier-type '(found known))
-                      (and (eq (char-after identifier-start) ?~)
-                           ;; `at-type' probably won't be 'found for
-                           ;; destructors since the "~" is then part of the
-                           ;; type name being checked against the list of
-                           ;; known types, so do a check without that
-                           ;; operator.
-                           (or (save-excursion
-                                 (goto-char (1+ identifier-start))
-                                 (c-forward-syntactic-ws)
-                                 (c-with-syntax-table
-                                     c-identifier-syntax-table
-                                   (looking-at c-known-type-key)))
-                               (save-excursion
-                                 (goto-char (1+ identifier-start))
-                                 ;; We have already parsed the type earlier,
-                                 ;; so it'd be possible to cache the end
-                                 ;; position instead of redoing it here, but
-                                 ;; then we'd need to keep track of another
-                                 ;; position everywhere.
-                                 (c-check-type (point)
-                                               (progn (c-forward-type)
-                                                      (point))))))))
-         (throw 'at-decl-or-cast t))
-
-       (if got-identifier
-           (progn
-             ;; CASE 16
-             (when (and got-prefix-before-parens
-                        at-type
-                        (or at-decl-end (looking-at "=[^=]"))
-                        (not context)
-                        (not got-suffix))
-               ;; Got something like "foo * bar;".  Since we're not inside an
-               ;; arglist it would be a meaningless expression because the
-               ;; result isn't used.  We therefore choose to recognize it as
-               ;; a declaration.  Do not allow a suffix since it could then
-               ;; be a function call.
-               (throw 'at-decl-or-cast t))
-
-             ;; CASE 17
-             (when (and (or got-suffix-after-parens
-                            (looking-at "=[^=]"))
-                        (eq at-type 'found)
-                        (not (eq context 'arglist)))
-               ;; Got something like "a (*b) (c);" or "a (b) = c;".  It could
-               ;; be an odd expression or it could be a declaration.  Treat
-               ;; it as a declaration if "a" has been used as a type
-               ;; somewhere else (if it's a known type we won't get here).
-               (throw 'at-decl-or-cast t)))
-
-         ;; CASE 18
-         (when (and context
-                    (or got-prefix
-                        (and (eq context 'decl)
-                             (not c-recognize-paren-inits)
-                             (or got-parens got-suffix))))
-           ;; Got a type followed by an abstract declarator.  If `got-prefix'
-           ;; is set it's something like "a *" without anything after it.  If
-           ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]",
-           ;; or similar, which we accept only if the context rules out
-           ;; expressions.
-           (throw 'at-decl-or-cast t)))
-
-       ;; If we had a complete symbol table here (which rules out
-       ;; `c-found-types') we should return t due to the disambiguation rule
-       ;; (in at least C++) that anything that can be parsed as a declaration
-       ;; is a declaration.  Now we're being more defensive and prefer to
-       ;; highlight things like "foo (bar);" as a declaration only if we're
-       ;; inside an arglist that contains declarations.
-       (eq context 'decl))))
+        ;; CASE 13
+        ;;     (unless (or at-decl-end (looking-at "=[^=]"))
+        ;; If this is a declaration it should end here or its initializer(*)
+        ;; should start here, so check for allowed separation tokens.  Note
+        ;; that this rule doesn't work e.g. with a K&R arglist after a
+        ;; function header.
+        ;;
+        ;; *) Don't check for C++ style initializers using parens
+        ;; since those already have been matched as suffixes.
+        ;;
+        ;; If `at-decl-or-cast' is then we've found some other sign that
+        ;; it's a declaration or cast, so then it's probably an
+        ;; invalid/unfinished one.
+        ;;       (throw 'at-decl-or-cast at-decl-or-cast))
+
+        ;; Below are tests that only should be applied when we're certain to
+        ;; not have parsed halfway through an expression.
+
+        ;; CASE 14
+        (when (memq at-type '(t known))
+          ;; The expression starts with a known type so treat it as a
+          ;; declaration.
+          (throw 'at-decl-or-cast t))
+
+        ;; CASE 15
+        (when (and (c-major-mode-is 'c++-mode)
+                   ;; In C++ we check if the identifier is a known type, since
+                   ;; (con|de)structors use the class name as identifier.
+                   ;; We've always shifted over the identifier as a type and
+                   ;; then backed up again in this case.
+                   identifier-type
+                   (or (memq identifier-type '(found known))
+                       (and (eq (char-after identifier-start) ?~)
+                            ;; `at-type' probably won't be 'found for
+                            ;; destructors since the "~" is then part of the
+                            ;; type name being checked against the list of
+                            ;; known types, so do a check without that
+                            ;; operator.
+                            (or (save-excursion
+                                  (goto-char (1+ identifier-start))
+                                  (c-forward-syntactic-ws)
+                                  (c-with-syntax-table
+                                      c-identifier-syntax-table
+                                    (looking-at c-known-type-key)))
+                                (save-excursion
+                                  (goto-char (1+ identifier-start))
+                                  ;; We have already parsed the type earlier,
+                                  ;; so it'd be possible to cache the end
+                                  ;; position instead of redoing it here, but
+                                  ;; then we'd need to keep track of another
+                                  ;; position everywhere.
+                                  (c-check-type (point)
+                                                (progn (c-forward-type)
+                                                       (point))))))))
+          (throw 'at-decl-or-cast t))
+
+        (if got-identifier
+            (progn
+              ;; CASE 16
+              (when (and got-prefix-before-parens
+                         at-type
+                         (or at-decl-end (looking-at "=[^=]"))
+                         (not context)
+                         (not got-suffix))
+                ;; Got something like "foo * bar;".  Since we're not inside an
+                ;; arglist it would be a meaningless expression because the
+                ;; result isn't used.  We therefore choose to recognize it as
+                ;; a declaration.  Do not allow a suffix since it could then
+                ;; be a function call.
+                (throw 'at-decl-or-cast t))
+
+              ;; CASE 17
+              (when (and (or got-suffix-after-parens
+                             (looking-at "=[^=]"))
+                         (eq at-type 'found)
+                         (not (eq context 'arglist)))
+                ;; Got something like "a (*b) (c);" or "a (b) = c;".  It could
+                ;; be an odd expression or it could be a declaration.  Treat
+                ;; it as a declaration if "a" has been used as a type
+                ;; somewhere else (if it's a known type we won't get here).
+                (throw 'at-decl-or-cast t)))
+
+          ;; CASE 18
+          (when (and context
+                     (or got-prefix
+                         (and (eq context 'decl)
+                              (not c-recognize-paren-inits)
+                              (or got-parens got-suffix))))
+            ;; Got a type followed by an abstract declarator.  If `got-prefix'
+            ;; is set it's something like "a *" without anything after it.  If
+            ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]",
+            ;; or similar, which we accept only if the context rules out
+            ;; expressions.
+            (throw 'at-decl-or-cast t)))
+
+        ;; If we had a complete symbol table here (which rules out
+        ;; `c-found-types') we should return t due to the disambiguation rule
+        ;; (in at least C++) that anything that can be parsed as a declaration
+        ;; is a declaration.  Now we're being more defensive and prefer to
+        ;; highlight things like "foo (bar);" as a declaration only if we're
+        ;; inside an arglist that contains declarations.
+         ;; CASE 19
+        (eq context 'decl))))
 
     ;; The point is now after the type decl expression.
 
@@ -7393,7 +7520,13 @@ comment at the start of cc-engine.el for more info."
        ;; interactive refontification.
        (c-put-c-type-property (point) 'c-decl-arg-start))
 
-      (when (and c-record-type-identifiers at-type (not (eq at-type t)))
+      ;; Record the type's coordinates in `c-record-type-identifiers' for
+      ;; later fontification.
+      (when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
+                ;; There seems no reason to exclude a token from
+                ;; fontification just because it's "a known type that can't
+                ;; be a name or other expression".  2013-09-18.
+                )
        (let ((c-promote-possible-types t))
          (save-excursion
            (goto-char type-start)
@@ -7487,10 +7620,10 @@ comment at the start of cc-engine.el for more info."
                    (c-put-c-type-property (1- (point)) 'c-decl-end)
                    t)
 
-             ;; It's an unfinished label.  We consider the keyword enough
-             ;; to recognize it as a label, so that it gets fontified.
-             ;; Leave the point at the end of it, but don't put any
-             ;; `c-decl-end' marker.
+               ;; It's an unfinished label.  We consider the keyword enough
+               ;; to recognize it as a label, so that it gets fontified.
+               ;; Leave the point at the end of it, but don't put any
+               ;; `c-decl-end' marker.
                (goto-char kwd-end)
                t))))
 
@@ -7675,69 +7808,69 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This function might do hidden buffer changes.
 
-    (let ((start (point))
-         start-char
-         (c-promote-possible-types t)
-         lim
-         ;; Turn off recognition of angle bracket arglists while parsing
-         ;; types here since the protocol reference list might then be
-         ;; considered part of the preceding name or superclass-name.
-         c-recognize-<>-arglists)
-
-      (if (or
-          (when (looking-at
-                 (eval-when-compile
-                   (c-make-keywords-re t
-                     (append (c-lang-const c-protection-kwds objc)
-                             '("@end"))
-                     'objc-mode)))
-            (goto-char (match-end 1))
-            t)
-
-          (and
-           (looking-at
-            (eval-when-compile
-              (c-make-keywords-re t
-                '("@interface" "@implementation" "@protocol")
-                'objc-mode)))
-
-           ;; Handle the name of the class itself.
-           (progn
-;            (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's
-;            at EOB.
-             (goto-char (match-end 0))
-             (setq lim (point))
-             (c-skip-ws-forward)
-             (c-forward-type))
-
-           (catch 'break
-             ;; Look for ": superclass-name" or "( category-name )".
-             (when (looking-at "[:\(]")
-               (setq start-char (char-after))
+  (let ((start (point))
+       start-char
+       (c-promote-possible-types t)
+       lim
+       ;; Turn off recognition of angle bracket arglists while parsing
+       ;; types here since the protocol reference list might then be
+       ;; considered part of the preceding name or superclass-name.
+       c-recognize-<>-arglists)
+
+    (if (or
+        (when (looking-at
+               (eval-when-compile
+                 (c-make-keywords-re t
+                   (append (c-lang-const c-protection-kwds objc)
+                           '("@end"))
+                   'objc-mode)))
+          (goto-char (match-end 1))
+          t)
+
+        (and
+         (looking-at
+          (eval-when-compile
+            (c-make-keywords-re t
+              '("@interface" "@implementation" "@protocol")
+              'objc-mode)))
+
+         ;; Handle the name of the class itself.
+         (progn
+            ;; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's
+            ;; at EOB.
+           (goto-char (match-end 0))
+           (setq lim (point))
+           (c-skip-ws-forward)
+           (c-forward-type))
+
+         (catch 'break
+           ;; Look for ": superclass-name" or "( category-name )".
+           (when (looking-at "[:\(]")
+             (setq start-char (char-after))
+             (forward-char)
+             (c-forward-syntactic-ws)
+             (unless (c-forward-type) (throw 'break nil))
+             (when (eq start-char ?\()
+               (unless (eq (char-after) ?\)) (throw 'break nil))
                (forward-char)
-               (c-forward-syntactic-ws)
-               (unless (c-forward-type) (throw 'break nil))
-               (when (eq start-char ?\()
-                 (unless (eq (char-after) ?\)) (throw 'break nil))
-                 (forward-char)
-                 (c-forward-syntactic-ws)))
-
-             ;; Look for a protocol reference list.
-             (if (eq (char-after) ?<)
-                 (let ((c-recognize-<>-arglists t)
-                       (c-parse-and-markup-<>-arglists t)
-                       c-restricted-<>-arglists)
-                   (c-forward-<>-arglist t))
-               t))))
+               (c-forward-syntactic-ws)))
 
-         (progn
-           (c-backward-syntactic-ws lim)
-           (c-clear-c-type-property start (1- (point)) 'c-decl-end)
-           (c-put-c-type-property (1- (point)) 'c-decl-end)
-           t)
+           ;; Look for a protocol reference list.
+           (if (eq (char-after) ?<)
+               (let ((c-recognize-<>-arglists t)
+                     (c-parse-and-markup-<>-arglists t)
+                     c-restricted-<>-arglists)
+                 (c-forward-<>-arglist t))
+             t))))
+
+       (progn
+         (c-backward-syntactic-ws lim)
+         (c-clear-c-type-property start (1- (point)) 'c-decl-end)
+         (c-put-c-type-property (1- (point)) 'c-decl-end)
+         t)
 
-       (c-clear-c-type-property start (point) 'c-decl-end)
-       nil)))
+      (c-clear-c-type-property start (point) 'c-decl-end)
+      nil)))
 
 (defun c-beginning-of-inheritance-list (&optional lim)
   ;; Go to the first non-whitespace after the colon that starts a
@@ -7824,7 +7957,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This function might do hidden buffer changes.
 
-  (let ((beg (point)) end id-start)
+  (let ((beg (point)) id-start)
     (and
      (eq (c-beginning-of-statement-1 lim) 'same)
 
@@ -7914,54 +8047,54 @@ comment at the start of cc-engine.el for more info."
                   (throw 'knr nil)))
 
            (if after-rparen
-           ;; We're inside a paren.  Could it be our argument list....?
-             (if
-                 (and
-                  (progn
-                    (goto-char after-rparen)
-                    (unless (c-go-list-backward) (throw 'knr nil)) ;
-               ;; FIXME!!!  What about macros between the parens?  2007/01/20
-                    (setq before-lparen (point)))
+               ;; We're inside a paren.  Could it be our argument list....?
+               (if
+                   (and
+                    (progn
+                      (goto-char after-rparen)
+                      (unless (c-go-list-backward) (throw 'knr nil)) ;
+                      ;; FIXME!!!  What about macros between the parens?  2007/01/20
+                      (setq before-lparen (point)))
 
-                  ;; It can't be the arg list if next token is ; or {
-                  (progn (goto-char after-rparen)
-                         (c-forward-syntactic-ws)
-                         (not (memq (char-after) '(?\; ?\{ ?\=))))
+                    ;; It can't be the arg list if next token is ; or {
+                    (progn (goto-char after-rparen)
+                           (c-forward-syntactic-ws)
+                           (not (memq (char-after) '(?\; ?\{ ?\=))))
 
-                  ;; Is the thing preceding the list an identifier (the
-                  ;; function name), or a macro expansion?
-                  (progn
-                    (goto-char before-lparen)
-                    (eq (c-backward-token-2) 0)
-                    (or (eq (c-on-identifier) (point))
-                        (and (eq (char-after) ?\))
-                             (c-go-up-list-backward)
-                             (eq (c-backward-token-2) 0)
-                             (eq (c-on-identifier) (point)))))
-
-                  ;; Have we got a non-empty list of comma-separated
-                  ;; identifiers?
-                  (progn
-                    (goto-char before-lparen)
-                    (c-forward-token-2) ; to first token inside parens
-                    (and
-                     (c-on-identifier)
-                     (c-forward-token-2)
-                     (catch 'id-list
-                       (while (eq (char-after) ?\,)
-                         (c-forward-token-2)
-                         (unless (c-on-identifier) (throw 'id-list nil))
-                         (c-forward-token-2))
-                       (eq (char-after) ?\))))))
-
-                 ;; ...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))
+                    ;; Is the thing preceding the list an identifier (the
+                    ;; function name), or a macro expansion?
+                    (progn
+                      (goto-char before-lparen)
+                      (eq (c-backward-token-2) 0)
+                      (or (eq (c-on-identifier) (point))
+                          (and (eq (char-after) ?\))
+                               (c-go-up-list-backward)
+                               (eq (c-backward-token-2) 0)
+                               (eq (c-on-identifier) (point)))))
+
+                    ;; Have we got a non-empty list of comma-separated
+                    ;; identifiers?
+                    (progn
+                      (goto-char before-lparen)
+                      (c-forward-token-2) ; to first token inside parens
+                      (and
+                       (c-on-identifier)
+                       (c-forward-token-2)
+                       (catch 'id-list
+                         (while (eq (char-after) ?\,)
+                           (c-forward-token-2)
+                           (unless (c-on-identifier) (throw 'id-list nil))
+                           (c-forward-token-2))
+                         (eq (char-after) ?\))))))
+
+                   ;; ...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))
 
              (or (c-go-list-backward)  ; backwards over [ .... ]
                  (throw 'knr nil)))))))))
@@ -8167,7 +8300,7 @@ comment at the start of cc-engine.el for more info."
                   (and
                    (progn
                      (while  ; keep going back to "[;={"s until we either find
-                           ; no more, or get to one which isn't an "operator ="
+                           ; no more, or get to one which isn't an "operator ="
                          (and (c-syntactic-re-search-forward "[;={]" start t t t)
                               (eq (char-before) ?=)
                               c-overloadable-operators-regexp
@@ -8403,15 +8536,6 @@ comment at the start of cc-engine.el for more info."
          (back-to-indentation)
          (vector (point) open-paren-pos))))))
 
-(defmacro c-pull-open-brace (ps)
-  ;; Pull the next open brace from PS (which has the form of paren-state),
-  ;; skipping over any brace pairs.  Returns NIL when PS is exhausted.
-  `(progn
-     (while (consp (car ,ps))
-       (setq ,ps (cdr ,ps)))
-     (prog1 (car ,ps)
-       (setq ,ps (cdr ,ps)))))
-
 (defun c-most-enclosing-decl-block (paren-state)
   ;; Return the buffer position of the most enclosing decl-block brace (in the
   ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if
@@ -8443,6 +8567,34 @@ comment at the start of cc-engine.el for more info."
                      (not (looking-at "=")))))
       b-pos)))
 
+(defun c-backward-over-enum-header ()
+  ;; We're at a "{".  Move back to the enum-like keyword that starts this
+  ;; declaration and return t, otherwise don't move and return nil.
+  (let ((here (point))
+       up-sexp-pos before-identifier)
+    (while
+       (and
+        (eq (c-backward-token-2) 0)
+        (or (not (looking-at "\\s)"))
+            (c-go-up-list-backward))
+        (cond
+         ((and (looking-at c-symbol-key) (c-on-identifier)
+               (not before-identifier))
+          (setq before-identifier t))
+         ((and before-identifier
+               (or (eq (char-after) ?,)
+                   (looking-at c-postfix-decl-spec-key)))
+          (setq before-identifier nil)
+          t)
+         ((looking-at c-brace-list-key) nil)
+         ((and c-recognize-<>-arglists
+               (eq (char-after) ?<)
+               (looking-at "\\s("))
+          t)
+         (t nil))))
+    (or (looking-at c-brace-list-key)
+       (progn (goto-char here) nil))))
+
 (defun c-inside-bracelist-p (containing-sexp paren-state)
   ;; return the buffer position of the beginning of the brace list
   ;; statement if we're inside a brace list, otherwise return nil.
@@ -8457,18 +8609,9 @@ comment at the start of cc-engine.el for more info."
   ;; This function might do hidden buffer changes.
   (or
    ;; This will pick up brace list declarations.
-   (c-safe
-    (save-excursion
-      (goto-char containing-sexp)
-      (c-forward-sexp -1)
-      (let (bracepos)
-       (if (and (or (looking-at c-brace-list-key)
-                    (progn (c-forward-sexp -1)
-                           (looking-at c-brace-list-key)))
-                (setq bracepos (c-down-list-forward (point)))
-                (not (c-crosses-statement-barrier-p (point)
-                                                    (- bracepos 2))))
-           (point)))))
+   (save-excursion
+     (goto-char containing-sexp)
+     (c-backward-over-enum-header))
    ;; this will pick up array/aggregate init lists, even if they are nested.
    (save-excursion
      (let ((class-key
@@ -8476,106 +8619,122 @@ comment at the start of cc-engine.el for more info."
            ;; check for the class key here.
            (and (c-major-mode-is 'pike-mode)
                 c-decl-block-key))
-          bufpos braceassignp lim next-containing)
+          bufpos braceassignp lim next-containing macro-start)
        (while (and (not bufpos)
                   containing-sexp)
+        (when paren-state
+          (if (consp (car paren-state))
+              (setq lim (cdr (car paren-state))
+                    paren-state (cdr paren-state))
+            (setq lim (car paren-state)))
           (when paren-state
-            (if (consp (car paren-state))
-                (setq lim (cdr (car paren-state))
-                      paren-state (cdr paren-state))
-              (setq lim (car paren-state)))
-            (when paren-state
-              (setq next-containing (car paren-state)
-                    paren-state (cdr paren-state))))
-          (goto-char containing-sexp)
-          (if (c-looking-at-inexpr-block next-containing next-containing)
-              ;; We're in an in-expression block of some kind.  Do not
-              ;; check nesting.  We deliberately set the limit to the
-              ;; containing sexp, so that c-looking-at-inexpr-block
-              ;; doesn't check for an identifier before it.
-              (setq containing-sexp nil)
-            ;; see if the open brace is preceded by = or [...] in
-            ;; this statement, but watch out for operator=
-            (setq braceassignp 'dontknow)
-            (c-backward-token-2 1 t lim)
-            ;; Checks to do only on the first sexp before the brace.
-            (when (and c-opt-inexpr-brace-list-key
-                       (eq (char-after) ?\[))
-              ;; In Java, an initialization brace list may follow
-              ;; directly after "new Foo[]", so check for a "new"
-              ;; earlier.
-              (while (eq braceassignp 'dontknow)
-                (setq braceassignp
-                      (cond ((/= (c-backward-token-2 1 t lim) 0) nil)
-                            ((looking-at c-opt-inexpr-brace-list-key) t)
-                            ((looking-at "\\sw\\|\\s_\\|[.[]")
-                             ;; Carry on looking if this is an
-                             ;; identifier (may contain "." in Java)
-                             ;; or another "[]" sexp.
-                             'dontknow)
-                            (t nil)))))
-            ;; Checks to do on all sexps before the brace, up to the
-            ;; beginning of the statement.
+            (setq next-containing (car paren-state)
+                  paren-state (cdr paren-state))))
+        (goto-char containing-sexp)
+        (if (c-looking-at-inexpr-block next-containing next-containing)
+            ;; We're in an in-expression block of some kind.  Do not
+            ;; check nesting.  We deliberately set the limit to the
+            ;; containing sexp, so that c-looking-at-inexpr-block
+            ;; doesn't check for an identifier before it.
+            (setq containing-sexp nil)
+          ;; see if the open brace is preceded by = or [...] in
+          ;; this statement, but watch out for operator=
+          (setq braceassignp 'dontknow)
+          (c-backward-token-2 1 t lim)
+          ;; Checks to do only on the first sexp before the brace.
+          (when (and c-opt-inexpr-brace-list-key
+                     (eq (char-after) ?\[))
+            ;; In Java, an initialization brace list may follow
+            ;; directly after "new Foo[]", so check for a "new"
+            ;; earlier.
             (while (eq braceassignp 'dontknow)
-              (cond ((eq (char-after) ?\;)
-                     (setq braceassignp nil))
-                    ((and class-key
-                          (looking-at class-key))
-                     (setq braceassignp nil))
-                    ((eq (char-after) ?=)
-                     ;; We've seen a =, but must check earlier tokens so
-                     ;; that it isn't something that should be ignored.
-                     (setq braceassignp 'maybe)
-                     (while (and (eq braceassignp 'maybe)
-                                 (zerop (c-backward-token-2 1 t lim)))
-                       (setq braceassignp
-                             (cond
-                              ;; Check for operator =
-                              ((and c-opt-op-identifier-prefix
-                                    (looking-at c-opt-op-identifier-prefix))
-                               nil)
-                              ;; Check for `<opchar>= in Pike.
-                              ((and (c-major-mode-is 'pike-mode)
-                                    (or (eq (char-after) ?`)
-                                        ;; Special case for Pikes
-                                        ;; `[]=, since '[' is not in
-                                        ;; the punctuation class.
-                                        (and (eq (char-after) ?\[)
-                                             (eq (char-before) ?`))))
-                               nil)
-                              ((looking-at "\\s.") 'maybe)
-                              ;; make sure we're not in a C++ template
-                              ;; argument assignment
-                              ((and
-                                (c-major-mode-is 'c++-mode)
-                                (save-excursion
-                                  (let ((here (point))
-                                        (pos< (progn
-                                                (skip-chars-backward "^<>")
-                                                (point))))
-                                    (and (eq (char-before) ?<)
-                                         (not (c-crosses-statement-barrier-p
-                                               pos< here))
-                                         (not (c-in-literal))
-                                         ))))
-                               nil)
-                              (t t))))))
-              (if (and (eq braceassignp 'dontknow)
-                       (/= (c-backward-token-2 1 t lim) 0))
-                  (setq braceassignp nil)))
-            (if (not braceassignp)
-                (if (eq (char-after) ?\;)
-                    ;; Brace lists can't contain a semicolon, so we're done.
-                    (setq containing-sexp nil)
-                  ;; Go up one level.
-                  (setq containing-sexp next-containing
-                        lim nil
-                        next-containing nil))
-              ;; we've hit the beginning of the aggregate list
-              (c-beginning-of-statement-1
-               (c-most-enclosing-brace paren-state))
-              (setq bufpos (point))))
-          )
+              (setq braceassignp
+                    (cond ((/= (c-backward-token-2 1 t lim) 0) nil)
+                          ((looking-at c-opt-inexpr-brace-list-key) t)
+                          ((looking-at "\\sw\\|\\s_\\|[.[]")
+                           ;; Carry on looking if this is an
+                           ;; identifier (may contain "." in Java)
+                           ;; or another "[]" sexp.
+                           'dontknow)
+                          (t nil)))))
+          ;; Checks to do on all sexps before the brace, up to the
+          ;; beginning of the statement.
+          (while (eq braceassignp 'dontknow)
+            (cond ((eq (char-after) ?\;)
+                   (setq braceassignp nil))
+                  ((and class-key
+                        (looking-at class-key))
+                   (setq braceassignp nil))
+                  ((eq (char-after) ?=)
+                   ;; We've seen a =, but must check earlier tokens so
+                   ;; that it isn't something that should be ignored.
+                   (setq braceassignp 'maybe)
+                   (while (and (eq braceassignp 'maybe)
+                               (zerop (c-backward-token-2 1 t lim)))
+                     (setq braceassignp
+                           (cond
+                            ;; Check for operator =
+                            ((and c-opt-op-identifier-prefix
+                                  (looking-at c-opt-op-identifier-prefix))
+                             nil)
+                            ;; Check for `<opchar>= in Pike.
+                            ((and (c-major-mode-is 'pike-mode)
+                                  (or (eq (char-after) ?`)
+                                      ;; Special case for Pikes
+                                      ;; `[]=, since '[' is not in
+                                      ;; the punctuation class.
+                                      (and (eq (char-after) ?\[)
+                                           (eq (char-before) ?`))))
+                             nil)
+                            ((looking-at "\\s.") 'maybe)
+                            ;; make sure we're not in a C++ template
+                            ;; argument assignment
+                            ((and
+                              (c-major-mode-is 'c++-mode)
+                              (save-excursion
+                                (let ((here (point))
+                                      (pos< (progn
+                                              (skip-chars-backward "^<>")
+                                              (point))))
+                                  (and (eq (char-before) ?<)
+                                       (not (c-crosses-statement-barrier-p
+                                             pos< here))
+                                       (not (c-in-literal))
+                                       ))))
+                             nil)
+                            (t t))))))
+            (if (and (eq braceassignp 'dontknow)
+                     (/= (c-backward-token-2 1 t lim) 0))
+                (setq braceassignp nil)))
+          (cond
+           (braceassignp
+            ;; We've hit the beginning of the aggregate list.
+            (c-beginning-of-statement-1
+             (c-most-enclosing-brace paren-state))
+            (setq bufpos (point)))
+           ((eq (char-after) ?\;)
+            ;; Brace lists can't contain a semicolon, so we're done.
+            (setq containing-sexp nil))
+           ((and (setq macro-start (point))
+                 (c-forward-to-cpp-define-body)
+                 (eq (point) containing-sexp))
+            ;; We've a macro whose expansion starts with the '{'.
+            ;; Heuristically, if we have a ';' in it we've not got a
+            ;; brace list, otherwise we have.
+            (let ((macro-end (progn (c-end-of-macro) (point))))
+              (goto-char containing-sexp)
+              (forward-char)
+              (if (and (c-syntactic-re-search-forward "[;,]" macro-end t t)
+                       (eq (char-before) ?\;))
+                  (setq bufpos nil
+                        containing-sexp nil)
+                (setq bufpos macro-start))))
+           (t
+            ;; Go up one level
+            (setq containing-sexp next-containing
+                  lim nil
+                  next-containing nil)))))
+
        bufpos))
    ))
 
@@ -9066,7 +9225,7 @@ comment at the start of cc-engine.el for more info."
                     (max (c-point 'boi paren-pos) (point))))
                   (t (c-add-syntax 'defun-block-intro nil))))
 
-                (c-add-syntax 'statement-block-intro nil)))
+             (c-add-syntax 'statement-block-intro nil)))
 
          (if (= paren-pos boi)
              ;; Always done if the open brace was at boi.  The
@@ -9263,16 +9422,16 @@ comment at the start of cc-engine.el for more info."
                    (not (looking-at c-<-op-cont-regexp))))))
       (c-with-syntax-table c++-template-syntax-table
        (goto-char placeholder)
-       (c-beginning-of-statement-1 containing-sexp t)
-       (if (save-excursion
-             (c-backward-syntactic-ws containing-sexp)
-             (eq (char-before) ?<))
-           ;; In a nested template arglist.
-           (progn
-             (goto-char placeholder)
-             (c-syntactic-skip-backward "^,;" containing-sexp t)
-             (c-forward-syntactic-ws))
-         (back-to-indentation)))
+       (c-beginning-of-statement-1 containing-sexp t))
+      (if (save-excursion
+           (c-backward-syntactic-ws containing-sexp)
+           (eq (char-before) ?<))
+         ;; In a nested template arglist.
+         (progn
+           (goto-char placeholder)
+           (c-syntactic-skip-backward "^,;" containing-sexp t)
+           (c-forward-syntactic-ws))
+       (back-to-indentation))
       ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
       ;; template aware.
       (c-add-syntax 'template-args-cont (point) placeholder))
@@ -9294,7 +9453,8 @@ comment at the start of cc-engine.el for more info."
     (c-save-buffer-state
        ((indent-point (point))
         (case-fold-search nil)
-        ;; A whole ugly bunch of various temporary variables.  Have
+        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
         ;; following result clauses, and most of this function is a
@@ -9929,16 +10089,16 @@ comment at the start of cc-engine.el for more info."
                            (eq (char-after placeholder) ?<))))))
            (c-with-syntax-table c++-template-syntax-table
              (goto-char placeholder)
-             (c-beginning-of-statement-1 lim t)
-             (if (save-excursion
-                   (c-backward-syntactic-ws lim)
-                   (eq (char-before) ?<))
-                 ;; In a nested template arglist.
-                 (progn
-                   (goto-char placeholder)
-                   (c-syntactic-skip-backward "^,;" lim t)
-                   (c-forward-syntactic-ws))
-               (back-to-indentation)))
+             (c-beginning-of-statement-1 lim t))
+           (if (save-excursion
+                 (c-backward-syntactic-ws lim)
+                 (eq (char-before) ?<))
+               ;; In a nested template arglist.
+               (progn
+                 (goto-char placeholder)
+                 (c-syntactic-skip-backward "^,;" lim t)
+                 (c-forward-syntactic-ws))
+             (back-to-indentation))
            ;; FIXME: Should use c-add-stmt-syntax, but it's not yet
            ;; template aware.
            (c-add-syntax 'template-args-cont (point) placeholder))
@@ -10178,7 +10338,6 @@ comment at the start of cc-engine.el for more info."
          (c-add-syntax 'topmost-intro-cont (c-point 'boi)))
         ))
 
-
        ;; (CASE 6 has been removed.)
 
        ;; CASE 7: line is an expression, not a statement.  Most
@@ -10381,7 +10540,7 @@ comment at the start of cc-engine.el for more info."
          (if (eq (point) (c-point 'boi))
              (c-add-syntax 'brace-list-close (point))
            (setq lim (c-most-enclosing-brace c-state-cache (point)))
-           (c-beginning-of-statement-1 lim)
+           (c-beginning-of-statement-1 lim nil nil t)
            (c-add-stmt-syntax 'brace-list-close nil t lim paren-state)))
 
         (t