]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
Fix fontification of type when followed by "const".
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 368b1fc50dcec272ee603f77921165af8a40ec9c..582f7ef0a54ef823fd013da942aaaf715a605c64 100644 (file)
 (cc-require-when-compile 'cc-langs)
 (cc-require 'cc-vars)
 
-;; Silence the compiler.
-(cc-bytecomp-defun buffer-syntactic-context) ; XEmacs
-
 \f
 ;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
 
@@ -1138,9 +1135,13 @@ comment at the start of cc-engine.el for more info."
                   (not (memq sym '(boundary ignore nil))))
          ;; Need to investigate closer whether we've crossed
          ;; between a substatement and its containing statement.
-         (if (setq saved (if (looking-at c-block-stmt-1-key)
-                             ptok
-                           pptok))
+         (if (setq saved
+                   (cond ((and (looking-at c-block-stmt-1-2-key)
+                               (eq (char-after ptok) ?\())
+                          pptok)
+                         ((looking-at c-block-stmt-1-key)
+                          ptok)
+                         (t pptok)))
              (cond ((> start saved) (setq pos saved))
                    ((= start saved) (setq ret 'up)))))
 
@@ -1270,6 +1271,9 @@ comment at the start of cc-engine.el for more info."
              (throw 'done (point)))))
          ;; In trailing space after an as yet undetected virtual semicolon?
          (c-backward-syntactic-ws from)
+         (when (and (bolp) (not (bobp))) ; Can happen in AWK Mode with an
+                                         ; unterminated string/regexp.
+           (backward-char))
          (if (and (< (point) to)
                   (c-at-vsemi-p))
              (point)
@@ -2180,32 +2184,45 @@ comment at the start of cc-engine.el for more info."
 ;; reduced by buffer changes, and increased by invocations of
 ;; `c-state-literal-at'.  FIXME!!!
 
-(defsubst c-state-pp-to-literal (from to)
+(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter)
   ;; Do a parse-partial-sexp from FROM to TO, returning either
   ;;     (STATE TYPE (BEG . END))     if TO is in a literal; or
   ;;     (STATE)                      otherwise,
   ;; where STATE is the parsing state at TO, TYPE is the type of the literal
   ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
   ;;
+  ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
+  ;; comment opener, this is recognized as being in a comment literal.
+  ;;
   ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote),
   ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
   ;; STATE are valid.
   (save-excursion
     (let ((s (parse-partial-sexp from to))
-         ty)
-      (when (or (nth 3 s) (nth 4 s))   ; in a string or comment
+         ty co-st)
+      (cond
+       ((or (nth 3 s) (nth 4 s))       ; in a string or comment
        (setq ty (cond
                  ((nth 3 s) 'string)
-                 ((eq (nth 7 s) t) 'c++)
+                 ((nth 7 s) 'c++)
                  (t 'c)))
        (parse-partial-sexp (point) (point-max)
-                           nil                  ; TARGETDEPTH
-                           nil                  ; STOPBEFORE
-                           s                    ; OLDSTATE
-                           'syntax-table))      ; stop at end of literal
-      (if ty
-         `(,s ,ty (,(nth 8 s) . ,(point)))
-       `(,s)))))
+                           nil            ; TARGETDEPTH
+                           nil            ; STOPBEFORE
+                           s              ; OLDSTATE
+                           'syntax-table) ; stop at end of literal
+       `(,s ,ty (,(nth 8 s) . ,(point))))
+
+       ((and (not not-in-delimiter)    ; inside a comment starter
+            (not (bobp))
+            (progn (backward-char)
+                   (looking-at c-comment-start-regexp)))
+       (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
+             co-st (point))
+       (forward-comment 1)
+       `(,s ,ty (,co-st . ,(point))))
+
+       (t `(,s))))))
 
 (defun c-state-safe-place (here)
   ;; Return a buffer position before HERE which is "safe", i.e. outside any
@@ -3143,10 +3160,13 @@ comment at the start of cc-engine.el for more info."
   ;; This function is called from c-after-change.
 
   ;; The caches of non-literals:
-  (if (< here c-state-nonlit-pos-cache-limit)
-      (setq c-state-nonlit-pos-cache-limit here))
-  (if (< here c-state-semi-nonlit-pos-cache-limit)
-      (setq c-state-semi-nonlit-pos-cache-limit here))
+  ;; Note that we use "<=" for the possibility of the second char of a two-char
+  ;; comment opener being typed; this would invalidate any cache position at
+  ;; HERE.
+  (if (<= here c-state-nonlit-pos-cache-limit)
+      (setq c-state-nonlit-pos-cache-limit (1- here)))
+  (if (<= here c-state-semi-nonlit-pos-cache-limit)
+      (setq c-state-semi-nonlit-pos-cache-limit (1- here)))
 
   ;; `c-state-cache':
   ;; Case 1: if `here' is in a literal containing point-min, everything
@@ -4444,19 +4464,12 @@ comment at the start of cc-engine.el for more info."
           (lim (or lim (c-state-semi-safe-place pos)))
           (pp-to-lit (save-restriction
                        (widen)
-                       (c-state-pp-to-literal lim pos)))
+                       (c-state-pp-to-literal lim pos not-in-delimiter)))
           (state (car pp-to-lit))
           (lit-limits (car (cddr pp-to-lit))))
 
       (cond
        (lit-limits)
-       ((and (not not-in-delimiter)
-            (not (elt state 5))
-            (eq (char-before) ?/)
-            (looking-at "[/*]")) ; FIXME!!! use c-line/block-comment-starter.  2008-09-28.
-       ;; We're standing in a comment starter.
-       (backward-char 1)
-       (cons (point) (progn (c-forward-single-comment) (point))))
 
        (near
        (goto-char pos)
@@ -6466,6 +6479,61 @@ 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
+  ;; the function's arglist.  Otherwise return nil, leaving point unchanged.
+  (let ((here (point))
+       (paren-state (c-parse-state))
+       res)
+
+    (setq res
+         (catch 'done
+           (if (not (c-at-toplevel-p))
+               (progn
+                 (while (not (c-at-toplevel-p))
+                   (goto-char (c-pull-open-brace paren-state)))
+                 (c-backward-syntactic-ws)
+                 (when (not (c-simple-skip-symbol-backward))
+                   (throw 'done nil))
+                 (c-backward-syntactic-ws))
+             (c-backward-syntactic-ws)
+             (when (memq (char-before) '(?\) ?}))
+               (when (not (c-go-list-backward))
+                 (throw 'done nil))
+               (c-backward-syntactic-ws))
+             (when (c-simple-skip-symbol-backward)
+               (c-backward-syntactic-ws)))
+
+           (while (eq (char-before) ?,)
+             (backward-char)
+             (c-backward-syntactic-ws)
+
+             (when (not (memq (char-before) '(?\) ?})))
+               (throw 'done nil))
+             (when (not (c-go-list-backward))
+               (throw 'done nil))
+             (c-backward-syntactic-ws)
+             (when (not (c-simple-skip-symbol-backward))
+               (throw 'done nil))
+             (c-backward-syntactic-ws))
+
+           (and
+            (eq (char-before) ?:)
+            (c-just-after-func-arglist-p))))
+
+    (or res (goto-char here))
+    res))
+
 \f
 ;; Handling of large scale constructs like statements and declarations.
 
@@ -6837,32 +6905,38 @@ comment at the start of cc-engine.el for more info."
 
       ;; 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 second 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 (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) ?\()
+             (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))
 
@@ -7141,19 +7215,23 @@ comment at the start of cc-engine.el for more info."
        ;; uncommon (e.g. some placements of "const" in C++) it's not worth
        ;; the effort to look for them.)
 
-       (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))
+;;; 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.
@@ -7330,7 +7408,11 @@ 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)))
+      (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)
@@ -7932,7 +8014,8 @@ comment at the start of cc-engine.el for more info."
         (or (looking-at c-block-stmt-1-key)
             (and (eq (char-after) ?\()
                  (zerop (c-backward-token-2 1 t lim))
-                 (looking-at c-block-stmt-2-key)))
+                 (or (looking-at c-block-stmt-2-key)
+                     (looking-at c-block-stmt-1-2-key))))
         (point))))
 
 (defun c-after-special-operator-id (&optional lim)
@@ -8339,15 +8422,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
@@ -8412,10 +8486,10 @@ 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
+        (when paren-state
             (if (consp (car paren-state))
                 (setq lim (cdr (car paren-state))
                       paren-state (cdr paren-state))
@@ -8496,22 +8570,38 @@ comment at the start of cc-engine.el for more info."
                                          ))))
                                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))))
-          )
+            (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))
    ))
 
@@ -9303,10 +9393,6 @@ comment at the start of cc-engine.el for more info."
                          containing-sexp nil)))
              (setq lim (1+ containing-sexp))))
        (setq lim (point-min)))
-      (when (c-beginning-of-macro)
-       (goto-char indent-point)
-       (let ((lim1 (c-determine-limit 2000)))
-         (setq lim (max lim lim1))))
 
       ;; If we're in a parenthesis list then ',' delimits the
       ;; "statements" rather than being an operator (with the
@@ -9668,18 +9754,13 @@ comment at the start of cc-engine.el for more info."
              ;; 2007-11-09)
              ))))
 
-        ;; CASE 5B: After a function header but before the body (or
-        ;; the ending semicolon if there's no body).
+        ;; CASE 5R: Member init list.  (Used to be part of CASE  5B.1)
+        ;; Note there is no limit on the backward search here, since member
+        ;; init lists can, in practice, be very large.
         ((save-excursion
-           (when (setq placeholder (c-just-after-func-arglist-p
-                                    (max lim (c-determine-limit 500))))
+           (when (setq placeholder (c-back-over-member-initializers))
              (setq tmp-pos (point))))
-         (cond
-
-          ;; CASE 5B.1: Member init list.
-          ((eq (char-after tmp-pos) ?:)
-           (if (or (>= tmp-pos indent-point)
-                   (= (c-point 'bosws) (1+ tmp-pos)))
+         (if (= (c-point 'bosws) (1+ tmp-pos))
                (progn
                  ;; There is no preceding member init clause.
                  ;; Indent relative to the beginning of indentation
@@ -9692,6 +9773,23 @@ comment at the start of cc-engine.el for more info."
              (c-forward-syntactic-ws)
              (c-add-syntax 'member-init-cont (point))))
 
+        ;; CASE 5B: After a function header but before the body (or
+        ;; the ending semicolon if there's no body).
+        ((save-excursion
+           (when (setq placeholder (c-just-after-func-arglist-p
+                                    (max lim (c-determine-limit 500))))
+             (setq tmp-pos (point))))
+         (cond
+
+          ;; CASE 5B.1: Member init list.
+          ((eq (char-after tmp-pos) ?:)
+           ;; There is no preceding member init clause.
+           ;; Indent relative to the beginning of indentation
+           ;; for the topmost-intro line that contains the
+           ;; prototype's open paren.
+           (goto-char placeholder)
+           (c-add-syntax 'member-init-intro (c-point 'boi)))
+
           ;; CASE 5B.2: K&R arg decl intro
           ((and c-recognize-knr-p
                 (c-in-knr-argdecl lim))
@@ -9727,12 +9825,12 @@ comment at the start of cc-engine.el for more info."
                              (not (eq (char-after) ?:))
                              )))
                   (save-excursion
-                    (c-backward-syntactic-ws lim)
-                    (if (eq char-before-ip ?:)
-                        (progn
-                          (forward-char -1)
-                          (c-backward-syntactic-ws lim)))
-                    (back-to-indentation)
+                    (c-beginning-of-statement-1 lim)
+                    (when (looking-at c-opt-<>-sexp-key)
+                      (goto-char (match-end 1))
+                      (c-forward-syntactic-ws)
+                      (c-forward-<>-arglist nil)
+                      (c-forward-syntactic-ws))
                     (looking-at c-class-key)))
              ;; for Java
              (and (c-major-mode-is 'java-mode)