]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 4aff0dc14e094dfa05715b2f18f0bee96527c4da..4d6a1203c257d07c27272f87ab4f6488c82330b7 100644 (file)
 ;; The starting position from where we determined `c-macro-cache'.
 (defvar c-macro-cache-syntactic nil)
 (make-variable-buffer-local 'c-macro-cache-syntactic)
-;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a
-;; syntactic end of macro, not merely an apparent one.
+;; Either nil, or the syntactic end of the macro currently represented by
+;; `c-macro-cache'.
+(defvar c-macro-cache-no-comment nil)
+(make-variable-buffer-local 'c-macro-cache-no-comment)
+;; Either nil, or the last character of the macro currently represented by
+;; `c-macro-cache' which isn't in a comment. */
 
 (defun c-invalidate-macro-cache (beg end)
   ;; Called from a before-change function.  If the change region is before or
    ((< beg (car c-macro-cache))
     (setq c-macro-cache nil
          c-macro-cache-start-pos nil
-         c-macro-cache-syntactic nil))
+         c-macro-cache-syntactic nil
+         c-macro-cache-no-comment nil))
    ((and (cdr c-macro-cache)
         (< beg (cdr c-macro-cache)))
     (setcdr c-macro-cache nil)
     (setq c-macro-cache-start-pos beg
-         c-macro-cache-syntactic nil))))
+         c-macro-cache-syntactic nil
+         c-macro-cache-no-comment nil))))
 
 (defun c-macro-is-genuine-p ()
   ;; Check that the ostensible CPP construct at point is a real one.  In
@@ -288,7 +294,8 @@ comment at the start of cc-engine.el for more info."
                   t))
        (setq c-macro-cache nil
              c-macro-cache-start-pos nil
-             c-macro-cache-syntactic nil)
+             c-macro-cache-syntactic nil
+             c-macro-cache-no-comment nil)
 
        (save-restriction
          (if lim (narrow-to-region lim (point-max)))
@@ -323,7 +330,8 @@ comment at the start of cc-engine.el for more info."
                  (>= (point) (car c-macro-cache)))
        (setq c-macro-cache nil
             c-macro-cache-start-pos nil
-            c-macro-cache-syntactic nil))
+            c-macro-cache-syntactic nil
+            c-macro-cache-no-comment nil))
      (while (progn
              (end-of-line)
              (when (and (eq (char-before) ?\\)
@@ -347,14 +355,38 @@ comment at the start of cc-engine.el for more info."
   (let* ((here (point))
         (there (progn (c-end-of-macro) (point)))
         s)
-    (unless c-macro-cache-syntactic
+    (if c-macro-cache-syntactic
+       (goto-char c-macro-cache-syntactic)
       (setq s (parse-partial-sexp here there))
       (while (and (or (nth 3 s)         ; in a string
                      (nth 4 s)) ; in a comment (maybe at end of line comment)
                  (> there here))       ; No infinite loops, please.
        (setq there (1- (nth 8 s)))
        (setq s (parse-partial-sexp here there)))
-      (setq c-macro-cache-syntactic (car c-macro-cache)))
+      (setq c-macro-cache-syntactic (point)))
+    (point)))
+
+(defun c-no-comment-end-of-macro ()
+  ;; Go to the end of a CPP directive, or a pos just before which isn't in a
+  ;; comment.  For this purpose, open strings are ignored.
+  ;;
+  ;; This function must only be called from the beginning of a CPP construct.
+  ;;
+  ;; Note that this function might do hidden buffer changes.  See the comment
+  ;; at the start of cc-engine.el for more info.
+  (let* ((here (point))
+        (there (progn (c-end-of-macro) (point)))
+        s)
+    (if c-macro-cache-no-comment
+       (goto-char c-macro-cache-no-comment)
+      (setq s (parse-partial-sexp here there))
+      (while (and (nth 3 s)     ; in a string
+                 (> there here))       ; No infinite loops, please.
+       (setq here (1+ (nth 8 s)))
+       (setq s (parse-partial-sexp here there)))
+      (when (nth 4 s)
+       (goto-char (1- (nth 8 s))))
+      (setq c-macro-cache-no-comment (point)))
     (point)))
 
 (defun c-forward-over-cpp-define-id ()
@@ -385,6 +417,25 @@ comment at the start of cc-engine.el for more info."
 \f
 ;;; Basic utility functions.
 
+(defun c-delq-from-dotted-list (elt dlist)
+  ;; If ELT is a member of the (possibly dotted) list DLIST, remove all
+  ;; occurrences of it (except for any in the last cdr of DLIST).
+  ;;
+  ;; Call this as (setq DLIST (c-delq-from-dotted-list ELT DLIST)), as
+  ;; sometimes the original structure is changed, sometimes it's not.
+  ;;
+  ;; This function is needed in Emacs < 24.5, and possibly XEmacs, because
+  ;; `delq' throws an error in these versions when given a dotted list.
+  (let ((tail dlist) prev)
+    (while (consp tail)
+      (if (eq (car tail) elt)
+         (if prev
+             (setcdr prev (cdr tail))
+           (setq dlist (cdr dlist)))
+       (setq prev tail))
+      (setq tail (cdr tail)))
+    dlist))
+
 (defun c-syntactic-content (from to paren-level)
   ;; Return the given region as a string where all syntactic
   ;; whitespace is removed or, where necessary, replaced with a single
@@ -3440,7 +3491,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))))
@@ -3527,7 +3578,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)
@@ -5835,6 +5886,7 @@ 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)))
@@ -6026,7 +6078,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)
@@ -6072,28 +6123,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-strictly)
-                       (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 '<'
 
@@ -6414,9 +6468,7 @@ 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)
-                          (c-last-identifier-range))
+              (when (let (c-last-identifier-range)
                       (c-forward-<>-arglist nil))
 
                 (c-forward-syntactic-ws)
@@ -7019,9 +7071,9 @@ comment at the start of cc-engine.el for more info."
   ;; If a declaration is parsed:
   ;;
   ;;   The point is left at the first token after the first complete
-  ;;   declarator, if there is one.  The return value is a cons where
-  ;;   the car is the position of the first token in the declarator.  (See
-  ;;   below for the cdr.)
+  ;;   declarator, if there is one.  The return value is a list of 4 elements,
+  ;;   where the first is the position of the first token in the declarator.
+  ;;   (See below for the other three.)
   ;;   Some examples:
   ;;
   ;;    void foo (int a, char *b) stuff ...
@@ -7052,7 +7104,7 @@ comment at the start of cc-engine.el for more info."
   ;;
   ;;
   ;;
-  ;;   The cdr of the return value is non-nil when a
+  ;;   The second element 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
   ;;   `c-typedef-kwds' ("typedef") is present, and A is t when some
@@ -7060,6 +7112,10 @@ comment at the start of cc-engine.el for more info."
   ;;   specifier is present.  I.e., (some of) the declared
   ;;   identifier(s) are types.
   ;;
+  ;;   The third element of the return value is non-nil when the declaration
+  ;;   parsed might be an expression.  The fourth element is the position of
+  ;;   the start of the type identifier.
+  ;;
   ;; If a cast is parsed:
   ;;
   ;;   The point is left at the first token after the closing paren of
@@ -7152,12 +7208,27 @@ 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
        ;; that it isn't a declaration or cast.
        (save-rec-type-ids c-record-type-identifiers)
-       (save-rec-ref-ids c-record-ref-identifiers))
+       (save-rec-ref-ids c-record-ref-identifiers)
+       ;; Set when we parse a declaration which might also be an expression,
+       ;; such as "a *b".  See CASE 16 and CASE 17.
+       maybe-expression)
+
+    (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))
@@ -7421,36 +7492,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))
 
-                (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)
+          ((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))))
+
+          (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
@@ -7462,7 +7539,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))
 
@@ -7771,12 +7848,16 @@ 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.
+                (setq maybe-expression t)
                 (throw 'at-decl-or-cast t))
 
               ;; CASE 17
@@ -7788,6 +7869,7 @@ comment at the start of cc-engine.el for more info."
                 ;; 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).
+                (setq maybe-expression t)
                 (throw 'at-decl-or-cast t)))
 
           ;; CASE 18
@@ -7911,9 +7993,11 @@ comment at the start of cc-engine.el for more info."
            (goto-char type-start)
            (c-forward-type))))
 
-      (cons id-start
+      (list id-start
            (and (or at-type-decl at-typedef)
-                (cons at-type-decl at-typedef))))
+                (cons at-type-decl at-typedef))
+           maybe-expression
+           type-start))
 
      (t
       ;; False alarm.  Restore the recorded ranges.
@@ -8847,6 +8931,22 @@ comment at the start of cc-engine.el for more info."
                  (c-syntactic-skip-backward c-block-prefix-charset limit t)
                  (eq (char-before) ?>))))))
 
+    ;; Skip back over noise clauses.
+    (while (and
+           c-opt-cpp-prefix
+           (eq (char-before) ?\))
+           (let ((after-paren (point)))
+             (if (and (c-go-list-backward)
+                      (progn (c-backward-syntactic-ws)
+                             (c-simple-skip-symbol-backward))
+                      (or (looking-at c-paren-nontype-key)
+                          (looking-at c-noise-macro-with-parens-name-re)))
+                 (progn
+                   (c-syntactic-skip-backward c-block-prefix-charset limit t)
+                   t)
+               (goto-char after-paren)
+               nil))))
+
     ;; Note: Can't get bogus hits inside template arglists below since they
     ;; have gotten paren syntax above.
     (when (and
@@ -9003,11 +9103,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
@@ -9016,7 +9116,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)
@@ -9040,7 +9143,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)