]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 39600cf28f87401b7b71d39722e3f9a6875f9cbb..d19d2dacda12ab9d1c1a7e573763a9a16277a059 100644 (file)
@@ -1543,7 +1543,7 @@ comment at the start of cc-engine.el for more info."
 ;;    two newlines with horizontal whitespace between them.
 ;;
 ;;    The reason to include the first following char is to cope with
-;;    "rung positions" that doesn't have any ordinary whitespace.  If
+;;    "rung positions" that don't have any ordinary whitespace.  If
 ;;    `c-is-sws' is put on a token character it does not have
 ;;    `c-in-sws' set simultaneously.  That's the only case when that
 ;;    can occur, and the reason for not extending the `c-in-sws'
@@ -1714,7 +1714,9 @@ comment at the start of cc-engine.el for more info."
     ;; if it's anything that can't start syntactic ws, so we can bail out
     ;; early in the majority of cases when there just are a few ws chars.
     (skip-chars-forward " \t\n\r\f\v")
-    (when (looking-at c-syntactic-ws-start)
+    (when (or (looking-at c-syntactic-ws-start)
+             (and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re)))
 
       (setq rung-end-pos (min (1+ (point)) (point-max)))
       (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
@@ -1733,6 +1735,10 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; In the following while form, we move over a "ladder" and
+           ;; following simple WS each time round the loop, appending the WS
+           ;; onto the ladder, joining adjacent ladders, and terminating when
+           ;; there is no more WS or we reach EOB.
            (while
                (when (and rung-is-marked
                           (get-text-property (point) 'c-in-sws))
@@ -1776,6 +1782,7 @@ comment at the start of cc-engine.el for more info."
                            (setq rung-pos (point)
                                  last-put-in-sws-pos rung-pos)))
 
+           ;; Now move over any comments (x)or a CPP construct.
            (setq simple-ws-end (point))
            (c-forward-comments)
 
@@ -1801,6 +1808,13 @@ comment at the start of cc-engine.el for more info."
              (forward-line 1)
              (setq safe-start t)
              ;; Don't cache at eob in case the buffer is narrowed.
+             (not (eobp)))
+
+            ((and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re))
+             ;; Skip over a noise macro.
+             (goto-char (match-end 1))
+             (setq safe-start t)
              (not (eobp)))))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -1907,8 +1921,11 @@ comment at the start of cc-engine.el for more info."
     (when (and (not (bobp))
               (save-excursion
                 (backward-char)
-                (looking-at c-syntactic-ws-end)))
-
+                (or (looking-at c-syntactic-ws-end)
+                    (and c-opt-cpp-prefix
+                         (looking-at c-symbol-char-key)
+                         (progn (c-beginning-of-current-token)
+                                (looking-at c-noise-macro-name-re))))))
       ;; Try to find a rung position in the simple ws preceding point, so that
       ;; we can get a cache hit even if the last bit of the simple ws has
       ;; changed recently.
@@ -1927,6 +1944,9 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; Each time round the next while form, we move back over a ladder
+           ;; and append any simple WS preceding it, if possible joining with
+           ;; the previous ladder.
            (while
                (when (and rung-is-marked
                           (not (bobp))
@@ -2035,6 +2055,15 @@ comment at the start of cc-engine.el for more info."
              ;; narrowed out, and we can't risk marking the simple ws
              ;; at the end of it.
              (goto-char next-rung-pos)
+             t)
+
+            ((and c-opt-cpp-prefix
+                  (save-excursion
+                    (and (< (skip-syntax-backward "w_") 0)
+                         (progn (setq next-rung-pos (point))
+                                (looking-at c-noise-macro-name-re)))))
+             ;; Skipped over a noise macro
+             (goto-char next-rung-pos)
              t)))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -3241,7 +3270,7 @@ comment at the start of cc-engine.el for more info."
   ;; pair element into an open paren element.  Doing that would mean that the
   ;; new open paren wouldn't have the required preceding paren pair element.
   ;;
-  ;; This function is called from c-after-change.
+  ;; This function is called from c-before-change.
 
   ;; The caches of non-literals:
   ;; Note that we use "<=" for the possibility of the second char of a two-char
@@ -3265,7 +3294,7 @@ comment at the start of cc-engine.el for more info."
     ;; below `here'.  To maintain its consistency, we may need to insert a new
     ;; brace pair.
     (let ((here-bol (c-point 'bol here))
-         too-high-pa             ; recorded {/(/[ next above here, or nil.
+         too-high-pa  ; recorded {/(/[ next above or just below here, or nil.
          dropped-cons            ; was the last removed element a brace pair?
          pa)
       ;; The easy bit - knock over-the-top bits off `c-state-cache'.
@@ -3277,7 +3306,7 @@ comment at the start of cc-engine.el for more info."
 
       ;; Do we need to add in an earlier brace pair, having lopped one off?
       (if (and dropped-cons
-              (< too-high-pa (+ here c-state-cache-too-far)))
+              (<= too-high-pa here))
          (c-append-lower-brace-pair-to-state-cache too-high-pa here here-bol))
       (setq c-state-cache-good-pos (or (c-state-cache-after-top-paren)
                                       (c-state-get-min-scan-pos)))))
@@ -3411,7 +3440,7 @@ comment at the start of cc-engine.el for more info."
                (< c-state-old-cpp-beg here))
           (c-with-all-but-one-cpps-commented-out
            c-state-old-cpp-beg
-           (min c-state-old-cpp-end here)
+           c-state-old-cpp-end
            (c-invalidate-state-cache-1 here))
         (c-with-cpps-commented-out
          (c-invalidate-state-cache-1 here))))
@@ -3472,6 +3501,9 @@ comment at the start of cc-engine.el for more info."
 (make-variable-buffer-local 'c-parse-state-state)
 (defun c-record-parse-state-state ()
   (setq c-parse-state-point (point))
+  (when (markerp (cdr (assq 'c-state-old-cpp-beg c-parse-state-state)))
+    (move-marker (cdr (assq 'c-state-old-cpp-beg c-parse-state-state)) nil)
+    (move-marker (cdr (assq 'c-state-old-cpp-end c-parse-state-state)) nil))
   (setq c-parse-state-state
        (mapcar
         (lambda (arg)
@@ -3495,7 +3527,7 @@ comment at the start of cc-engine.el for more info."
           c-state-old-cpp-end
           c-parse-state-point))))
 (defun c-replay-parse-state-state ()
-  (message
+  (message "%s"
    (concat "(setq "
     (mapconcat
      (lambda (arg)
@@ -4259,8 +4291,7 @@ comment at the start of cc-engine.el for more info."
        (setq safe-pos-list (cdr safe-pos-list)))
       (unless (setq safe-pos (car-safe safe-pos-list))
        (setq safe-pos (max (or (c-safe-position
-                                (point) (or c-state-cache
-                                            (c-parse-state)))
+                                (point) (c-parse-state))
                                0)
                            (point-min))
              safe-pos-list (list safe-pos)))
@@ -4308,107 +4339,108 @@ Non-nil is returned if the point moved, nil otherwise.
 Note that this function might do hidden buffer changes.  See the
 comment at the start of cc-engine.el for more info."
 
-  (let ((start (point))
-       state-2
-       ;; A list of syntactically relevant positions in descending
-       ;; order.  It's used to avoid scanning repeatedly over
-       ;; potentially large regions with `parse-partial-sexp' to verify
-       ;; each position.  Used in `c-ssb-lit-begin'
-       safe-pos-list
-       ;; The result from `c-beginning-of-macro' at the start position or the
-       ;; start position itself if it isn't within a macro.  Evaluated on
-       ;; demand.
-       start-macro-beg
-       ;; The earliest position after the current one with the same paren
-       ;; level.  Used only when `paren-level' is set.
-       lit-beg
-       (paren-level-pos (point)))
-
-    (while
-       (progn
-         ;; The next loop "tries" to find the end point each time round,
-         ;; loops when it hasn't succeeded.
-         (while
-             (and
-              (let ((pos (point)))
-                (while (and
-                        (< (skip-chars-backward skip-chars limit) 0)
-                        ;; Don't stop inside a literal.
-                        (when (setq lit-beg (c-ssb-lit-begin))
-                          (goto-char lit-beg)
-                          t)))
-                (< (point) pos))
+  (c-self-bind-state-cache
+   (let ((start (point))
+        state-2
+        ;; A list of syntactically relevant positions in descending
+        ;; order.  It's used to avoid scanning repeatedly over
+        ;; potentially large regions with `parse-partial-sexp' to verify
+        ;; each position.  Used in `c-ssb-lit-begin'
+        safe-pos-list
+        ;; The result from `c-beginning-of-macro' at the start position or the
+        ;; start position itself if it isn't within a macro.  Evaluated on
+        ;; demand.
+        start-macro-beg
+        ;; The earliest position after the current one with the same paren
+        ;; level.  Used only when `paren-level' is set.
+        lit-beg
+        (paren-level-pos (point)))
+
+     (while
+        (progn
+          ;; The next loop "tries" to find the end point each time round,
+          ;; loops when it hasn't succeeded.
+          (while
+              (and
+               (let ((pos (point)))
+                 (while (and
+                         (< (skip-chars-backward skip-chars limit) 0)
+                         ;; Don't stop inside a literal.
+                         (when (setq lit-beg (c-ssb-lit-begin))
+                           (goto-char lit-beg)
+                           t)))
+                 (< (point) pos))
+
+               (let ((pos (point)) state-2 pps-end-pos)
 
-              (let ((pos (point)) state-2 pps-end-pos)
+                 (cond
+                  ((and paren-level
+                        (save-excursion
+                          (setq state-2 (parse-partial-sexp
+                                         pos paren-level-pos -1)
+                                pps-end-pos (point))
+                          (/= (car state-2) 0)))
+                   ;; Not at the right level.
+
+                   (if (and (< (car state-2) 0)
+                            ;; We stop above if we go out of a paren.
+                            ;; Now check whether it precedes or is
+                            ;; nested in the starting sexp.
+                            (save-excursion
+                              (setq state-2
+                                    (parse-partial-sexp
+                                     pps-end-pos paren-level-pos
+                                     nil nil state-2))
+                              (< (car state-2) 0)))
+
+                       ;; We've stopped short of the starting position
+                       ;; so the hit was inside a nested list.  Go up
+                       ;; until we are at the right level.
+                       (condition-case nil
+                           (progn
+                             (goto-char (scan-lists pos -1
+                                                    (- (car state-2))))
+                             (setq paren-level-pos (point))
+                             (if (and limit (>= limit paren-level-pos))
+                                 (progn
+                                   (goto-char limit)
+                                   nil)
+                               t))
+                         (error
+                          (goto-char (or limit (point-min)))
+                          nil))
+
+                     ;; The hit was outside the list at the start
+                     ;; position.  Go to the start of the list and exit.
+                     (goto-char (1+ (elt state-2 1)))
+                     nil))
+
+                  ((c-beginning-of-macro limit)
+                   ;; Inside a macro.
+                   (if (< (point)
+                          (or start-macro-beg
+                              (setq start-macro-beg
+                                    (save-excursion
+                                      (goto-char start)
+                                      (c-beginning-of-macro limit)
+                                      (point)))))
+                       t
+
+                     ;; It's inside the same macro we started in so it's
+                     ;; a relevant match.
+                     (goto-char pos)
+                     nil))))))
 
-                (cond
-                 ((and paren-level
-                       (save-excursion
-                         (setq state-2 (parse-partial-sexp
-                                        pos paren-level-pos -1)
-                               pps-end-pos (point))
-                         (/= (car state-2) 0)))
-                  ;; Not at the right level.
-
-                  (if (and (< (car state-2) 0)
-                           ;; We stop above if we go out of a paren.
-                           ;; Now check whether it precedes or is
-                           ;; nested in the starting sexp.
-                           (save-excursion
-                             (setq state-2
-                                   (parse-partial-sexp
-                                    pps-end-pos paren-level-pos
-                                    nil nil state-2))
-                             (< (car state-2) 0)))
-
-                      ;; We've stopped short of the starting position
-                      ;; so the hit was inside a nested list.  Go up
-                      ;; until we are at the right level.
-                      (condition-case nil
-                          (progn
-                            (goto-char (scan-lists pos -1
-                                                   (- (car state-2))))
-                            (setq paren-level-pos (point))
-                            (if (and limit (>= limit paren-level-pos))
-                                (progn
-                                  (goto-char limit)
-                                  nil)
-                              t))
-                        (error
-                         (goto-char (or limit (point-min)))
-                         nil))
-
-                    ;; The hit was outside the list at the start
-                    ;; position.  Go to the start of the list and exit.
-                    (goto-char (1+ (elt state-2 1)))
-                    nil))
-
-                 ((c-beginning-of-macro limit)
-                  ;; Inside a macro.
-                  (if (< (point)
-                         (or start-macro-beg
-                             (setq start-macro-beg
-                                   (save-excursion
-                                     (goto-char start)
-                                     (c-beginning-of-macro limit)
-                                     (point)))))
-                      t
-
-                    ;; It's inside the same macro we started in so it's
-                    ;; a relevant match.
-                    (goto-char pos)
-                    nil))))))
-
-         (> (point)
-            (progn
-              ;; Skip syntactic ws afterwards so that we don't stop at the
-              ;; end of a comment if `skip-chars' is something like "^/".
-              (c-backward-syntactic-ws)
-              (point)))))
+          (> (point)
+             (progn
+               ;; Skip syntactic ws afterwards so that we don't stop at the
+               ;; end of a comment if `skip-chars' is something like "^/".
+               (c-backward-syntactic-ws)
+               (point)))))
 
-    ;; We might want to extend this with more useful return values in
-    ;; the future.
-    (/= (point) start)))
+     ;; We might want to extend this with more useful return values in
+     ;; the future.
+     (/= (point) start))))
 
 ;; The following is an alternative implementation of
 ;; `c-syntactic-skip-backward' that uses backward movement to keep
@@ -5803,16 +5835,21 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;; This macro might do hidden buffer changes.
   `(let (res)
+     (setq c-last-identifier-range nil)
      (while (if (setq res ,(if (eq type 'type)
                               `(c-forward-type)
                             `(c-forward-name)))
                nil
-             (and (looking-at c-keywords-regexp)
-                  (c-forward-keyword-clause 1))))
-     (when (memq res '(t known found prefix))
-       ,(when (eq type 'ref)
-         `(when c-record-type-identifiers
-            (c-record-ref-id c-last-identifier-range)))
+             (cond ((looking-at c-keywords-regexp)
+                    (c-forward-keyword-clause 1))
+                   ((and c-opt-cpp-prefix
+                         (looking-at c-noise-macro-with-parens-name-re))
+                    (c-forward-noise-clause)))))
+     (when (memq res '(t known found prefix maybe))
+       (when c-record-type-identifiers
+        ,(if (eq type 'type)
+             `(c-record-type-id c-last-identifier-range)
+           `(c-record-ref-id c-last-identifier-range)))
        t)))
 
 (defmacro c-forward-id-comma-list (type update-safe-pos)
@@ -5830,6 +5867,17 @@ comment at the start of cc-engine.el for more info."
                 (c-forward-syntactic-ws)
                 (c-forward-keyword-prefixed-id ,type)))))
 
+(defun c-forward-noise-clause ()
+  ;; Point is at a c-noise-macro-with-parens-names macro identifier.  Go
+  ;; forward over this name, any parenthesis expression which follows it, and
+  ;; any syntactic WS, ending up at the next token.  If there is an unbalanced
+  ;; paren expression, leave point at it.  Always Return t.
+  (c-forward-token-2)
+  (if (and (eq (char-after) ?\()
+          (c-go-list-forward))
+      (c-forward-syntactic-ws))
+  t)
+
 (defun c-forward-keyword-clause (match)
   ;; Submatch MATCH in the current match data is assumed to surround a
   ;; token.  If it's a keyword, move over it and any immediately
@@ -5979,7 +6027,6 @@ comment at the start of cc-engine.el for more info."
                  ;; `nconc' doesn't mind that the tail of
                  ;; `c-record-found-types' is t.
                  (nconc c-record-found-types c-record-type-identifiers)))
-           (if (c-major-mode-is 'java-mode) (c-fontify-recorded-types-and-refs))
          t)
 
       (goto-char start)
@@ -6025,28 +6072,31 @@ comment at the start of cc-engine.el for more info."
                (progn
                  (c-forward-syntactic-ws)
                  (when (or (and c-record-type-identifiers all-types)
-                           (c-major-mode-is 'java-mode))
-                   ;; All encountered identifiers are types, so set the
-                   ;; promote flag and parse the type.
-                   (progn
-                     (c-forward-syntactic-ws)
-                     (if (looking-at "\\?")
-                         (forward-char)
-                       (when (looking-at c-identifier-start)
+                           (not (equal c-inside-<>-type-key "\\(\\<\\>\\)")))
+                   (c-forward-syntactic-ws)
+                   (cond
+                    ((eq (char-after) ??)
+                     (forward-char))
+                    ((and (looking-at c-identifier-start)
+                          (not (looking-at c-keywords-regexp)))
+                     (if (or (and all-types c-record-type-identifiers)
+                             (c-major-mode-is 'java-mode))
+                         ;; All encountered identifiers are types, so set the
+                         ;; promote flag and parse the type.
                          (let ((c-promote-possible-types t)
                                (c-record-found-types t))
-                           (c-forward-type))))
+                           (c-forward-type))
+                       (c-forward-token-2))))
 
-                     (c-forward-syntactic-ws)
+                   (c-forward-syntactic-ws)
 
-                     (when (or (looking-at "extends")
-                               (looking-at "super"))
-                       (forward-word)
-                       (c-forward-syntactic-ws)
-                       (let ((c-promote-possible-types t)
-                             (c-record-found-types t))
-                         (c-forward-type)
-                         (c-forward-syntactic-ws)))))
+                   (when (looking-at c-inside-<>-type-key)
+                     (goto-char (match-end 1))
+                     (c-forward-syntactic-ws)
+                     (let ((c-promote-possible-types t)
+                           (c-record-found-types t))
+                       (c-forward-type))
+                     (c-forward-syntactic-ws)))
 
                  (setq pos (point))    ; e.g. first token inside the '<'
 
@@ -6056,7 +6106,10 @@ comment at the start of cc-engine.el for more info."
                   ;; Stop on ',', '|', '&', '+' and '-' to catch
                   ;; common binary operators that could be between
                   ;; two comparison expressions "a<b" and "c>d".
-                  "[<;{},|+&-]\\|[>)]"
+                  ;; 2016-02-11: C++11 templates can now contain arithmetic
+                  ;; expressions, so template detection in C++ is now less
+                  ;; robust than it was.
+                  c-<>-notable-chars-re
                   nil t t))
 
                (cond
@@ -6064,7 +6117,9 @@ comment at the start of cc-engine.el for more info."
                  ;; Either an operator starting with '>' or the end of
                  ;; the angle bracket arglist.
 
-                 (if (looking-at c->-op-without->-cont-regexp)
+                 (if (save-excursion
+                       (c-backward-token-2)
+                       (looking-at c-multichar->-op-not->>-regexp))
                      (progn
                        (goto-char (match-end 0))
                        t)              ; Continue the loop.
@@ -6134,6 +6189,11 @@ comment at the start of cc-engine.el for more info."
                      )))
                  t)                    ; carry on looping.
 
+                ((and
+                  (eq (char-before) ?\()
+                  (c-go-up-list-forward)
+                  (eq (char-before) ?\))))
+
                 ((and (not c-restricted-<>-arglists)
                       (or (and (eq (char-before) ?&)
                                (not (eq (char-after) ?&)))
@@ -6357,14 +6417,14 @@ comment at the start of cc-engine.el for more info."
              ((and c-recognize-<>-arglists
                    (eq (char-after) ?<))
               ;; Maybe an angle bracket arglist.
-              (when (let ((c-record-type-identifiers t)
-                          (c-record-found-types t))
+              (when (let (c-last-identifier-range)
                       (c-forward-<>-arglist nil))
 
-                (c-add-type start (1+ pos))
                 (c-forward-syntactic-ws)
-                (setq pos (point)
-                      c-last-identifier-range nil)
+                (unless (eq (char-after) ?\()
+                  (setq c-last-identifier-range nil)
+                  (c-add-type start (1+ pos)))
+                (setq pos (point))
 
                 (if (and c-opt-identifier-concat-key
                          (looking-at c-opt-identifier-concat-key))
@@ -6378,7 +6438,8 @@ comment at the start of cc-engine.el for more info."
                       (c-forward-syntactic-ws)
                       t)
 
-                  (when (and c-record-type-identifiers id-start)
+                  (when (and c-record-type-identifiers id-start
+                             (not (eq (char-after) ?\()))
                     (c-record-type-id (cons id-start id-end)))
                   (setq res 'template)
                   nil)))
@@ -6450,6 +6511,14 @@ comment at the start of cc-engine.el for more info."
                                     ; "typedef".
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
+
+      (while (cond
+             ((looking-at c-decl-hangon-key)
+              (c-forward-keyword-clause 1))
+             ((and c-opt-cpp-prefix
+                   (looking-at c-noise-macro-with-parens-name-re))
+              (c-forward-noise-clause))))
+
       (setq pos (point))
 
       (setq name-res (c-forward-name))
@@ -6552,9 +6621,18 @@ comment at the start of cc-engine.el for more info."
                           ;; It's an identifier that might be a type.
                           'maybe))))
            ((eq name-res 'template)
-            ;; A template is a type.
+            ;; A template is sometimes a type.
             (goto-char id-end)
-            (setq res t))
+            (c-forward-syntactic-ws)
+            (setq res
+                  (if (eq (char-after) ?\()
+                      (if (c-check-type id-start id-end)
+                          ;; It's an identifier that has been used as
+                          ;; a type somewhere else.
+                          'found
+                        ;; It's an identifier that might be a type.
+                        'maybe)
+                    t)))
            (t
             ;; Otherwise it's an operator identifier, which is not a type.
             (goto-char start)
@@ -6739,6 +6817,9 @@ comment at the start of cc-engine.el for more info."
                      (c-backward-syntactic-ws))
                    (c-back-over-list-of-member-inits)
                    (and (eq (char-before) ?:)
+                        (save-excursion
+                          (c-backward-token-2)
+                          (not (looking-at c-:$-multichar-token-regexp)))
                         (c-just-after-func-arglist-p))))
 
            (while (and (not (and level-plausible
@@ -6753,6 +6834,9 @@ comment at the start of cc-engine.el for more info."
                      (c-backward-syntactic-ws)
                      (c-back-over-list-of-member-inits)
                      (and (eq (char-before) ?:)
+                          (save-excursion
+                            (c-backward-token-2)
+                            (not (looking-at c-:$-multichar-token-regexp)))
                           (c-just-after-func-arglist-p)))))
 
            (and at-top-level level-plausible)))
@@ -6842,31 +6926,39 @@ comment at the start of cc-engine.el for more info."
           ;; of the while.  These are, e.g. "*" in "int *foo" or "(" and
           ;; "*" in "int (*foo) (void)" (Note similar code in
           ;; `c-forward-decl-or-cast-1'.)
-          (while (and (looking-at c-type-decl-prefix-key)
-                      (if (and (c-major-mode-is 'c++-mode)
-                               (match-beginning 3))
-                          ;; If the third submatch matches in C++ then
-                          ;; we're looking at an identifier that's a
-                          ;; prefix only if it specifies a member pointer.
-                          (progn
-                            (setq id-start (point))
-                            (c-forward-name)
-                            (if (looking-at "\\(::\\)")
-                                ;; We only check for a trailing "::" and
-                                ;; let the "*" that should follow be
-                                ;; matched in the next round.
-                                t
-                              ;; It turned out to be the real identifier,
-                              ;; so flag that and stop.
-                              (setq got-identifier t)
-                              nil))
-                        t))
-            (if (eq (char-after) ?\()
-                (progn
-                  (setq paren-depth (1+ paren-depth))
-                  (forward-char))
-              (goto-char (match-end 1)))
-            (c-forward-syntactic-ws))
+             (while
+                 (cond
+                  ((looking-at c-decl-hangon-key)
+                   (c-forward-keyword-clause 1))
+                  ((and c-opt-cpp-prefix
+                        (looking-at c-noise-macro-with-parens-name-re))
+                   (c-forward-noise-clause))
+                  ((and (looking-at c-type-decl-prefix-key)
+                        (if (and (c-major-mode-is 'c++-mode)
+                                 (match-beginning 3))
+                            ;; If the third submatch matches in C++ then
+                            ;; we're looking at an identifier that's a
+                            ;; prefix only if it specifies a member pointer.
+                            (progn
+                              (setq id-start (point))
+                              (c-forward-name)
+                              (if (looking-at "\\(::\\)")
+                                  ;; We only check for a trailing "::" and
+                                  ;; let the "*" that should follow be
+                                  ;; matched in the next round.
+                                  t
+                                ;; It turned out to be the real identifier,
+                                ;; so flag that and stop.
+                                (setq got-identifier t)
+                                nil))
+                          t))
+                   (if (eq (char-after) ?\()
+                       (progn
+                         (setq paren-depth (1+ paren-depth))
+                         (forward-char))
+                     (goto-char (match-end 1)))
+                   (c-forward-syntactic-ws)
+                   t)))
 
           ;; If we haven't passed the identifier already, do it now.
           (unless got-identifier
@@ -6891,9 +6983,13 @@ comment at the start of cc-engine.el for more info."
 
         ;; Skip over any trailing bit, such as "__attribute__".
         (progn
-          (when (looking-at c-decl-hangon-key)
-            (c-forward-keyword-clause 1))
-          (<= (point) limit))
+             (while (cond
+                     ((looking-at c-decl-hangon-key)
+                      (c-forward-keyword-clause 1))
+                     ((and c-opt-cpp-prefix
+                           (looking-at c-noise-macro-with-parens-name-re))
+                      (c-forward-noise-clause))))
+             (<= (point) limit))
 
         ;; Search syntactically to the end of the declarator (";",
         ;; ",", a closing paren, eob etc) or to the beginning of an
@@ -7057,6 +7153,9 @@ comment at the start of cc-engine.el for more info."
        cast-end
        ;; Have we got a new-style C++11 "auto"?
        new-style-auto
+       ;; Set when the symbol before `preceding-token-end' is known to
+       ;; terminate the previous construct, or when we're at point-min.
+       at-decl-start
        ;; Save `c-record-type-identifiers' and
        ;; `c-record-ref-identifiers' since ranges are recorded
        ;; speculatively and should be thrown away if it turns out
@@ -7064,6 +7163,15 @@ comment at the start of cc-engine.el for more info."
        (save-rec-type-ids c-record-type-identifiers)
        (save-rec-ref-ids c-record-ref-identifiers))
 
+    (save-excursion
+      (goto-char preceding-token-end)
+      (setq at-decl-start
+           (or (bobp)
+               (let ((tok-end (point)))
+                 (c-backward-token-2)
+                 (member (buffer-substring-no-properties (point) tok-end)
+                         c-pre-start-tokens)))))
+
     (while (c-forward-annotation)
       (c-forward-syntactic-ws))
 
@@ -7072,18 +7180,25 @@ comment at the start of cc-engine.el for more info."
     ;; macros like __INLINE__, so we recognize both types and known
     ;; specifiers after them too.
     (while
-       (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+       (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
 
+         (cond
          ;; Look for a specifier keyword clause.
-         (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto
-                   (and (c-major-mode-is 'java-mode)
-                        (looking-at "@[A-Za-z0-9]+")))
-           (if (save-match-data (looking-at c-typedef-key))
-               (setq at-typedef t))
+          ((or (looking-at c-prefix-spec-kwds-re)
+               (and (c-major-mode-is 'java-mode)
+                (looking-at "@[A-Za-z0-9]+")))
+           (save-match-data
+             (if (looking-at c-typedef-key)
+                 (setq at-typedef t)))
            (setq kwd-sym (c-keyword-sym (match-string 1)))
            (save-excursion
              (c-forward-keyword-clause 1)
              (setq kwd-clause-end (point))))
+          ((and c-opt-cpp-prefix
+                (looking-at c-noise-macro-with-parens-name-re))
+           (setq noise-start (point))
+           (c-forward-noise-clause)
+           (setq kwd-clause-end (point))))
 
          (when (setq found-type (c-forward-type t)) ; brace-block-too
            ;; Found a known or possible type or a prefix of a known type.
@@ -7121,16 +7236,17 @@ comment at the start of cc-engine.el for more info."
                  backup-at-type-decl nil
                  backup-maybe-typeless nil))
 
-         (if kwd-sym
+         (if (or kwd-sym noise-start)
              (progn
                ;; Handle known specifier keywords and
                ;; `c-decl-hangon-kwds' which can occur after known
                ;; types.
 
-               (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
-                   ;; It's a hang-on keyword that can occur anywhere.
+               (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+                       noise-start)
+                   ;; It's a hang-on keyword or noise clause that can occur
+                   ;; anywhere.
                    (progn
-                     (setq at-decl-or-cast t)
                      (if at-type
                          ;; Move the identifier start position if
                          ;; we've passed a type.
@@ -7182,8 +7298,12 @@ comment at the start of cc-engine.el for more info."
       ;; If a known type was found, we still need to skip over any
       ;; hangon keyword clauses after it.  Otherwise it has already
       ;; been done in the loop above.
-      (while (looking-at c-decl-hangon-key)
-       (c-forward-keyword-clause 1))
+      (while
+         (cond ((looking-at c-decl-hangon-key)
+                (c-forward-keyword-clause 1))
+               ((and c-opt-cpp-prefix
+                     (looking-at c-noise-macro-with-parens-name-re))
+                (c-forward-noise-clause))))
       (setq id-start (point)))
 
      ((eq at-type 'prefix)
@@ -7314,36 +7434,42 @@ comment at the start of cc-engine.el for more info."
               (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)
+      ;; Skip over type decl suffix operators and trailing noise macros.
+      (while
+         (cond
+          ((and c-opt-cpp-prefix
+                (looking-at c-noise-macro-with-parens-name-re))
+           (c-forward-noise-clause))
+
+          ((looking-at c-type-decl-suffix-key)
+           (if (eq (char-after) ?\))
+               (when (> paren-depth 0)
+                 (setq paren-depth (1- paren-depth))
+                 (forward-char)
+                 t)
+             (when (if (save-match-data (looking-at "\\s("))
+                       (c-safe (c-forward-sexp 1) t)
+                     (goto-char (match-end 1))
+                     t)
+               (when (and (not got-suffix-after-parens)
+                          (= paren-depth 0))
+                 (setq got-suffix-after-parens (match-beginning 0)))
+               (setq got-suffix t))))
 
-                (if (eq (char-after) ?\))
-                    (when (> paren-depth 0)
-                      (setq paren-depth (1- paren-depth))
-                      (forward-char)
-                      t)
-                  (when (if (save-match-data (looking-at "\\s("))
-                            (c-safe (c-forward-sexp 1) t)
-                          (goto-char (match-end 1))
-                          t)
-                    (when (and (not got-suffix-after-parens)
-                               (= paren-depth 0))
-                      (setq got-suffix-after-parens (match-beginning 0)))
-                    (setq got-suffix t)))
-
-              ;; No suffix matched.  We might have matched the
-              ;; identifier as a type and the open paren of a
-              ;; function arglist as a type decl prefix.  In that
-              ;; case we should "backtrack": Reinterpret the last
-              ;; type as the identifier, move out of the arglist and
-              ;; continue searching for suffix operators.
-              ;;
-              ;; Do this even if there's no preceding type, to cope
-              ;; with old style function declarations in K&R C,
-              ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
-              ;; style declarations.  That isn't applicable in an
-              ;; arglist context, though.
-              (when (and (= paren-depth 1)
+          (t
+           ;; No suffix matched.  We might have matched the
+           ;; identifier as a type and the open paren of a
+           ;; function arglist as a type decl prefix.  In that
+           ;; case we should "backtrack": Reinterpret the last
+           ;; type as the identifier, move out of the arglist and
+           ;; continue searching for suffix operators.
+           ;;
+           ;; Do this even if there's no preceding type, to cope
+           ;; with old style function declarations in K&R C,
+           ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
+           ;; style declarations.  That isn't applicable in an
+           ;; arglist context, though.
+           (when (and (= paren-depth 1)
                          (not got-prefix-before-parens)
                          (not (eq at-type t))
                          (or backup-at-type
@@ -7355,7 +7481,7 @@ comment at the start of cc-engine.el for more info."
                          (eq (char-before pos) ?\)))
                 (c-fdoc-shift-type-backward)
                 (goto-char pos)
-                t))
+                t)))
 
        (c-forward-syntactic-ws))
 
@@ -7664,12 +7790,15 @@ comment at the start of cc-engine.el for more info."
                          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.
+                         (or (not got-suffix)
+                             at-decl-start))
+                ;; 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.  We only allow a suffix (which makes
+                ;; the construct look like a function call) when
+                ;; `at-decl-start' provides additional evidence that we do
+                ;; have a declaration.
                 (throw 'at-decl-or-cast t))
 
               ;; CASE 17
@@ -8896,11 +9025,11 @@ comment at the start of cc-engine.el for more info."
                      (not (looking-at "=")))))
       b-pos)))
 
-(defun c-backward-colon-prefixed-type ()
-  ;; We're at the token after what might be a type prefixed with a colon.  Try
-  ;; moving backward over this type and the colon.  On success, return t and
-  ;; leave point before colon; on failure, leave point unchanged.  Will clobber
-  ;; match data.
+(defun c-backward-typed-enum-colon ()
+  ;; We're at a "{" which might be the opening brace of a enum which is
+  ;; strongly typed (by a ":" followed by a type).  If this is the case, leave
+  ;; point before the colon and return t.  Otherwise leave point unchanged and return nil.
+  ;; Match data will be clobbered.
   (let ((here (point))
        (colon-pos nil))
     (save-excursion
@@ -8909,7 +9038,10 @@ comment at the start of cc-engine.el for more info."
               (or (not (looking-at "\\s)"))
                   (c-go-up-list-backward))
               (cond
-               ((eql (char-after) ?:)
+               ((and (eql (char-after) ?:)
+                     (save-excursion
+                       (c-backward-syntactic-ws)
+                       (c-on-identifier)))
                 (setq colon-pos (point))
                 (forward-char)
                 (c-forward-syntactic-ws)
@@ -8933,7 +9065,7 @@ comment at the start of cc-engine.el for more info."
   (let ((here (point))
        up-sexp-pos before-identifier)
     (when c-recognize-post-brace-list-type-p
-      (c-backward-colon-prefixed-type))
+      (c-backward-typed-enum-colon))
     (while
        (and
         (eq (c-backward-token-2) 0)
@@ -8950,6 +9082,12 @@ comment at the start of cc-engine.el for more info."
           t)
          ((looking-at c-after-brace-list-key) t)
          ((looking-at c-brace-list-key) nil)
+         ((eq (char-after) ?\()
+          (and (eq (c-backward-token-2) 0)
+               (or (looking-at c-decl-hangon-key)
+                   (and c-opt-cpp-prefix
+                        (looking-at c-noise-macro-with-parens-name-re)))))
+
          ((and c-recognize-<>-arglists
                (eq (char-after) ?<)
                (looking-at "\\s("))
@@ -10210,9 +10348,12 @@ comment at the start of cc-engine.el for more info."
           ;; CASE 5A.3: brace list open
           ((save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((and c-opt-cpp-prefix
+                           (looking-at c-noise-macro-with-parens-name-re))
+                      (c-forward-noise-clause))))
              (setq placeholder (c-point 'boi))
              (or (consp special-brace-list)
                  (and (or (save-excursion
@@ -10264,9 +10405,12 @@ comment at the start of cc-engine.el for more info."
           (t
            (save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((and c-opt-cpp-prefix
+                           (looking-at c-noise-macro-with-parens-name-re))
+                      (c-forward-noise-clause))))
              (c-add-syntax 'defun-open (c-point 'boi))
              ;; Bogus to use bol here, but it's the legacy.  (Resolved,
              ;; 2007-11-09)
@@ -10897,9 +11041,12 @@ comment at the start of cc-engine.el for more info."
            (c-beginning-of-statement-1
             (c-safe-position (1- containing-sexp) paren-state))
            (c-forward-token-2 0)
-           (while (looking-at c-specifier-key)
-             (goto-char (match-end 1))
-             (c-forward-syntactic-ws))
+           (while (cond
+                   ((looking-at c-specifier-key)
+                    (c-forward-keyword-clause 1))
+                   ((and c-opt-cpp-prefix
+                         (looking-at c-noise-macro-with-parens-name-re))
+                    (c-forward-noise-clause))))
            (c-add-syntax 'brace-list-open (c-point 'boi))))
 
         ;; CASE 9B: brace-list-close brace