]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Merge from origin/emacs-25
[gnu-emacs] / lisp / progmodes / cc-engine.el
index d19d2dacda12ab9d1c1a7e573763a9a16277a059..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
@@ -7020,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 ...
@@ -7053,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
@@ -7061,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
@@ -7161,7 +7216,10 @@ comment at the start of cc-engine.el for more info."
        ;; 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)
@@ -7799,6 +7857,7 @@ comment at the start of cc-engine.el for more info."
                 ;; 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
@@ -7810,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
@@ -7933,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.
@@ -8869,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