]> git.eshelyaron.com Git - emacs.git/commitdiff
Optimize for typing characters into long C++ raw strings.
authorAlan Mackenzie <acm@muc.de>
Tue, 23 Apr 2019 09:16:05 +0000 (09:16 +0000)
committerAlan Mackenzie <acm@muc.de>
Tue, 23 Apr 2019 09:16:05 +0000 (09:16 +0000)
* lisp/progmodes/cc-fonts.el (c-font-lock-complex-decl-prepare)
(c-font-lock-objc-methods) (c-font-lock-declarations, c-font-lock-enum-tail)
(c-font-lock-cut-off-declarators, c-font-lock-enclosing-decls): If the chunk
been fontified consists entirely of comments and strings, don't attempt to
perform the function's action.

* lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings): Don't
expand (c-new-BEG c-new-END) unnecessarily to the entire raw string being
fontified.
(c-fl-decl-start, c-fl-decl-end): When in a (raw or otherwise) string, don't
return a position outside of the string (which used to cause unneeded
fontification).

lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-mode.el

index 5832f1f451c30e36ed751cda3a407c5457049dfe..4a5cf5719be372c7b7c84990e54c0e6e5d022c80 100644 (file)
@@ -880,48 +880,51 @@ casts and declarations are fontified.  Used on level 2 and higher."
   (when (bobp)
     (c-clear-found-types))
 
-  ;; Clear the c-type char properties which mark the region, to recalculate
-  ;; them properly.  The most interesting properties are those put on the
-  ;; closest token before the region.
-  (save-excursion
-    (let ((pos (point)))
-      (c-backward-syntactic-ws)
-      (c-clear-char-properties
-       (if (and (not (bobp))
-               (memq (c-get-char-property (1- (point)) 'c-type)
-                     '(c-decl-arg-start
-                       c-decl-end
-                       c-decl-id-start
-                       c-decl-type-start)))
-          (1- (point))
-        pos)
-       limit 'c-type)))
-
-  ;; Update `c-state-cache' to the beginning of the region.  This will
-  ;; make `c-beginning-of-syntax' go faster when it's used later on,
-  ;; and it's near the point most of the time.
-  (c-parse-state)
-
-  ;; Check if the fontified region starts inside a declarator list so
-  ;; that `c-font-lock-declarators' should be called at the start.
-  ;; The declared identifiers are font-locked correctly as types, if
-  ;; that is what they are.
-  (let ((prop (save-excursion
-               (c-backward-syntactic-ws)
-               (unless (bobp)
-                 (c-get-char-property (1- (point)) 'c-type)))))
-    (when (memq prop '(c-decl-id-start c-decl-type-start))
-      (c-forward-syntactic-ws limit)
-      (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)
-                              (not (c-bs-at-toplevel-p (point))))))
-
-  (setq c-font-lock-context ;; (c-guess-font-lock-context)
-       (save-excursion
-         (if (and c-cpp-expr-intro-re
-                  (c-beginning-of-macro)
-                  (looking-at c-cpp-expr-intro-re))
-             'in-cpp-expr)))
-  nil)
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
+
+    ;; Clear the c-type char properties which mark the region, to recalculate
+    ;; them properly.  The most interesting properties are those put on the
+    ;; closest token before the region.
+    (save-excursion
+      (let ((pos (point)))
+       (c-backward-syntactic-ws)
+       (c-clear-char-properties
+        (if (and (not (bobp))
+                 (memq (c-get-char-property (1- (point)) 'c-type)
+                       '(c-decl-arg-start
+                         c-decl-end
+                         c-decl-id-start
+                         c-decl-type-start)))
+            (1- (point))
+          pos)
+        limit 'c-type)))
+
+    ;; Update `c-state-cache' to the beginning of the region.  This will
+    ;; make `c-beginning-of-syntax' go faster when it's used later on,
+    ;; and it's near the point most of the time.
+    (c-parse-state)
+
+    ;; Check if the fontified region starts inside a declarator list so
+    ;; that `c-font-lock-declarators' should be called at the start.
+    ;; The declared identifiers are font-locked correctly as types, if
+    ;; that is what they are.
+    (let ((prop (save-excursion
+                 (c-backward-syntactic-ws)
+                 (unless (bobp)
+                   (c-get-char-property (1- (point)) 'c-type)))))
+      (when (memq prop '(c-decl-id-start c-decl-type-start))
+       (c-forward-syntactic-ws limit)
+       (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)
+                                (not (c-bs-at-toplevel-p (point))))))
+
+    (setq c-font-lock-context ;; (c-guess-font-lock-context)
+         (save-excursion
+           (if (and c-cpp-expr-intro-re
+                    (c-beginning-of-macro)
+                    (looking-at c-cpp-expr-intro-re))
+               'in-cpp-expr)))
+    nil))
 
 (defun c-font-lock-<>-arglists (limit)
   ;; This function will be called from font-lock for a region bounded by POINT
@@ -936,73 +939,76 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;;
   ;; This function might do hidden buffer changes.
 
-  (let (;; The font-lock package in Emacs is known to clobber
-       ;; `parse-sexp-lookup-properties' (when it exists).
-       (parse-sexp-lookup-properties
-        (cc-eval-when-compile
-          (boundp 'parse-sexp-lookup-properties)))
-       (c-parse-and-markup-<>-arglists t)
-       c-restricted-<>-arglists
-       id-start id-end id-face pos kwd-sym)
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
 
-    (while (and (< (point) limit)
-               (re-search-forward c-opt-<>-arglist-start limit t))
+    (let (;; The font-lock package in Emacs is known to clobber
+         ;; `parse-sexp-lookup-properties' (when it exists).
+         (parse-sexp-lookup-properties
+          (cc-eval-when-compile
+            (boundp 'parse-sexp-lookup-properties)))
+         (c-parse-and-markup-<>-arglists t)
+         c-restricted-<>-arglists
+         id-start id-end id-face pos kwd-sym)
 
-      (setq id-start (match-beginning 1)
-           id-end (match-end 1)
-           pos (point))
+      (while (and (< (point) limit)
+                 (re-search-forward c-opt-<>-arglist-start limit t))
 
-      (goto-char id-start)
-      (unless (c-skip-comments-and-strings limit)
-       (setq kwd-sym nil
-             c-restricted-<>-arglists nil
-             id-face (get-text-property id-start 'face))
-
-       (if (cond
-            ((eq id-face 'font-lock-type-face)
-             ;; The identifier got the type face so it has already been
-             ;; handled in `c-font-lock-declarations'.
-             nil)
-
-            ((eq id-face 'font-lock-keyword-face)
-             (when (looking-at c-opt-<>-sexp-key)
-               ;; There's a special keyword before the "<" that tells
-               ;; that it's an angle bracket arglist.
-               (setq kwd-sym (c-keyword-sym (match-string 1)))))
-
-            (t
-             ;; There's a normal identifier before the "<".  If we're not in
-             ;; a declaration context then we set `c-restricted-<>-arglists'
-             ;; to avoid recognizing templates in function calls like "foo (a
-             ;; < b, c > d)".
-             (c-backward-syntactic-ws)
-             (when (and (memq (char-before) '(?\( ?,))
-                        (not (eq (get-text-property (1- (point)) 'c-type)
-                                 'c-decl-arg-start)))
-               (setq c-restricted-<>-arglists t))
-             t))
+       (setq id-start (match-beginning 1)
+             id-end (match-end 1)
+             pos (point))
 
-           (progn
-             (goto-char (1- pos))
-             ;; Check for comment/string both at the identifier and
-             ;; at the "<".
-             (unless (c-skip-comments-and-strings limit)
-
-               (c-fontify-types-and-refs ()
-                 (when (c-forward-<>-arglist (c-keyword-member
-                                              kwd-sym 'c-<>-type-kwds))
-                   (when (and c-opt-identifier-concat-key
-                              (not (get-text-property id-start 'face)))
-                     (c-forward-syntactic-ws)
-                     (cond ((looking-at c-opt-identifier-concat-key)
-                            (c-put-font-lock-face id-start id-end
-                                               c-reference-face-name))
-                           ((eq (char-after) ?\())
-                           (t (c-put-font-lock-face id-start id-end
-                                             'font-lock-type-face))))))
-
-               (goto-char pos)))
-         (goto-char pos)))))
+       (goto-char id-start)
+       (unless (c-skip-comments-and-strings limit)
+         (setq kwd-sym nil
+               c-restricted-<>-arglists nil
+               id-face (get-text-property id-start 'face))
+
+         (if (cond
+              ((eq id-face 'font-lock-type-face)
+               ;; The identifier got the type face so it has already been
+               ;; handled in `c-font-lock-declarations'.
+               nil)
+
+              ((eq id-face 'font-lock-keyword-face)
+               (when (looking-at c-opt-<>-sexp-key)
+                 ;; There's a special keyword before the "<" that tells
+                 ;; that it's an angle bracket arglist.
+                 (setq kwd-sym (c-keyword-sym (match-string 1)))))
+
+              (t
+               ;; There's a normal identifier before the "<".  If we're not in
+               ;; a declaration context then we set `c-restricted-<>-arglists'
+               ;; to avoid recognizing templates in function calls like "foo (a
+               ;; < b, c > d)".
+               (c-backward-syntactic-ws)
+               (when (and (memq (char-before) '(?\( ?,))
+                          (not (eq (get-text-property (1- (point)) 'c-type)
+                                   'c-decl-arg-start)))
+                 (setq c-restricted-<>-arglists t))
+               t))
+
+             (progn
+               (goto-char (1- pos))
+               ;; Check for comment/string both at the identifier and
+               ;; at the "<".
+               (unless (c-skip-comments-and-strings limit)
+
+                 (c-fontify-types-and-refs ()
+                   (when (c-forward-<>-arglist (c-keyword-member
+                                                kwd-sym 'c-<>-type-kwds))
+                     (when (and c-opt-identifier-concat-key
+                                (not (get-text-property id-start 'face)))
+                       (c-forward-syntactic-ws)
+                       (cond ((looking-at c-opt-identifier-concat-key)
+                              (c-put-font-lock-face id-start id-end
+                                                    c-reference-face-name))
+                             ((eq (char-after) ?\())
+                             (t (c-put-font-lock-face id-start id-end
+                                                      'font-lock-type-face))))))
+
+                 (goto-char pos)))
+           (goto-char pos))))))
   nil)
 
 (defun c-font-lock-declarators (limit list types not-top
@@ -1311,227 +1317,229 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;; This function might do hidden buffer changes.
 
   ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
+  
+    (save-restriction
+      (let (;; The position where `c-find-decl-spots' last stopped.
+           start-pos
+           ;; o - 'decl if we're in an arglist containing declarations
+           ;;   (but if `c-recognize-paren-inits' is set it might also be
+           ;;   an initializer arglist);
+           ;; o - '<> if the arglist is of angle bracket type;
+           ;; o - 'arglist if it's some other arglist;
+           ;; o - nil, if not in an arglist at all.  This includes the
+           ;;   parenthesized condition which follows "if", "while", etc.
+           context
+           ;; A list of starting positions of possible type declarations, or of
+           ;; the typedef preceding one, if any.
+           last-cast-end
+           ;; The result from `c-forward-decl-or-cast-1'.
+           decl-or-cast
+           ;; The maximum of the end positions of all the checked type
+           ;; decl expressions in the successfully identified
+           ;; declarations.  The position might be either before or
+           ;; after the syntactic whitespace following the last token
+           ;; in the type decl expression.
+           (max-type-decl-end 0)
+           ;; Same as `max-type-decl-*', but used when we're before
+           ;; `token-pos'.
+           (max-type-decl-end-before-token 0)
+           ;; End of <..> construct which has had c-<>-arg-sep c-type
+           ;; properties set within it.
+           (max-<>-end 0)
+           ;; Set according to the context to direct the heuristics for
+           ;; recognizing C++ templates.
+           c-restricted-<>-arglists
+           ;; Turn on recording of identifier ranges in
+           ;; `c-forward-decl-or-cast-1' and `c-forward-label' for
+           ;; later fontification.
+           (c-record-type-identifiers t)
+           label-type
+           c-record-ref-identifiers
+           ;; Make `c-forward-type' calls mark up template arglists if
+           ;; it finds any.  That's necessary so that we later will
+           ;; stop inside them to fontify types there.
+           (c-parse-and-markup-<>-arglists t)
+           ;; The font-lock package in Emacs is known to clobber
+           ;; `parse-sexp-lookup-properties' (when it exists).
+           (parse-sexp-lookup-properties
+            (cc-eval-when-compile
+              (boundp 'parse-sexp-lookup-properties))
+            ))
+
+       ;; Below we fontify a whole declaration even when it crosses the limit,
+       ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
+       ;; time.  That is however annoying during editing, e.g. the following is
+       ;; a common situation while the first line is being written:
+       ;;
+       ;;     my_variable
+       ;;     some_other_variable = 0;
+       ;;
+       ;; font-lock will put the limit at the beginning of the second line
+       ;; here, and if we go past it we'll fontify "my_variable" as a type and
+       ;; "some_other_variable" as an identifier, and the latter will not
+       ;; correct itself until the second line is changed.  To avoid that we
+       ;; narrow to the limit if the region to fontify is a single line.
+       (if (<= limit (c-point 'bonl))
+           (narrow-to-region
+            (point-min)
+            (save-excursion
+              ;; Narrow after any operator chars following the limit though,
+              ;; since those characters can be useful in recognizing a
+              ;; declaration (in particular the '{' that opens a function body
+              ;; after the header).
+              (goto-char limit)
+              (skip-chars-forward c-nonsymbol-chars)
+              (point))))
+
+       (c-find-decl-spots
+        limit
+        c-decl-start-re
+        (eval c-maybe-decl-faces)
+
+        (lambda (match-pos inside-macro &optional toplev)
+          ;; Note to maintainers: don't use `limit' inside this lambda form;
+          ;; c-find-decl-spots sometimes narrows to less than `limit'.
+          (setq start-pos (point))
+          (when
+              ;; The result of the form below is true when we don't recognize a
+              ;; declaration or cast, and we don't recognize a "non-decl",
+              ;; typically a brace list.
+              (if (or (and (eq (get-text-property (point) 'face)
+                               'font-lock-keyword-face)
+                           (looking-at c-not-decl-init-keywords))
+                      (and c-macro-with-semi-re
+                           (looking-at c-macro-with-semi-re))) ; 2008-11-04
+                  ;; Don't do anything more if we're looking at a keyword that
+                  ;; can't start a declaration.
+                  t
+
+                ;; Set `context' and `c-restricted-<>-arglists'.  Look for
+                ;; "<" for the sake of C++-style template arglists.
+                ;; Ignore "(" when it's part of a control flow construct
+                ;; (e.g. "for (").
+                (let ((got-context
+                       (c-get-fontification-context
+                        match-pos
+                        (< match-pos (if inside-macro
+                                         max-type-decl-end-before-token
+                                       max-type-decl-end))
+                        toplev)))
+                  (setq context (car got-context)
+                        c-restricted-<>-arglists (cdr got-context)))
+
+                ;; Check we haven't missed a preceding "typedef".
+                (when (not (looking-at c-typedef-key))
+                  (c-backward-syntactic-ws)
+                  (c-backward-token-2)
+                  (or (looking-at c-typedef-key)
+                      (goto-char start-pos)))
+
+                ;; In QT, "more" is an irritating keyword that expands to nothing.
+                ;; We skip over it to prevent recognition of "more slots: <symbol>"
+                ;; as a bitfield declaration.
+                (when (and (c-major-mode-is 'c++-mode)
+                           (looking-at
+                            (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
+                  (goto-char (match-end 1))
+                  (c-forward-syntactic-ws))
 
-  (save-restriction
-    (let (;; The position where `c-find-decl-spots' last stopped.
-         start-pos
-         ;; o - 'decl if we're in an arglist containing declarations
-         ;;   (but if `c-recognize-paren-inits' is set it might also be
-         ;;   an initializer arglist);
-         ;; o - '<> if the arglist is of angle bracket type;
-         ;; o - 'arglist if it's some other arglist;
-         ;; o - nil, if not in an arglist at all.  This includes the
-         ;;   parenthesized condition which follows "if", "while", etc.
-         context
-         ;; A list of starting positions of possible type declarations, or of
-         ;; the typedef preceding one, if any.
-         last-cast-end
-         ;; The result from `c-forward-decl-or-cast-1'.
-         decl-or-cast
-         ;; The maximum of the end positions of all the checked type
-         ;; decl expressions in the successfully identified
-         ;; declarations.  The position might be either before or
-         ;; after the syntactic whitespace following the last token
-         ;; in the type decl expression.
-         (max-type-decl-end 0)
-         ;; Same as `max-type-decl-*', but used when we're before
-         ;; `token-pos'.
-         (max-type-decl-end-before-token 0)
-         ;; End of <..> construct which has had c-<>-arg-sep c-type
-         ;; properties set within it.
-         (max-<>-end 0)
-         ;; Set according to the context to direct the heuristics for
-         ;; recognizing C++ templates.
-         c-restricted-<>-arglists
-         ;; Turn on recording of identifier ranges in
-         ;; `c-forward-decl-or-cast-1' and `c-forward-label' for
-         ;; later fontification.
-         (c-record-type-identifiers t)
-         label-type
-         c-record-ref-identifiers
-         ;; Make `c-forward-type' calls mark up template arglists if
-         ;; it finds any.  That's necessary so that we later will
-         ;; stop inside them to fontify types there.
-         (c-parse-and-markup-<>-arglists t)
-         ;; The font-lock package in Emacs is known to clobber
-         ;; `parse-sexp-lookup-properties' (when it exists).
-         (parse-sexp-lookup-properties
-          (cc-eval-when-compile
-            (boundp 'parse-sexp-lookup-properties))
-          ))
-
-      ;; Below we fontify a whole declaration even when it crosses the limit,
-      ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
-      ;; time.  That is however annoying during editing, e.g. the following is
-      ;; a common situation while the first line is being written:
-      ;;
-      ;;     my_variable
-      ;;     some_other_variable = 0;
-      ;;
-      ;; font-lock will put the limit at the beginning of the second line
-      ;; here, and if we go past it we'll fontify "my_variable" as a type and
-      ;; "some_other_variable" as an identifier, and the latter will not
-      ;; correct itself until the second line is changed.  To avoid that we
-      ;; narrow to the limit if the region to fontify is a single line.
-      (if (<= limit (c-point 'bonl))
-         (narrow-to-region
-          (point-min)
-          (save-excursion
-            ;; Narrow after any operator chars following the limit though,
-            ;; since those characters can be useful in recognizing a
-            ;; declaration (in particular the '{' that opens a function body
-            ;; after the header).
-            (goto-char limit)
-            (skip-chars-forward c-nonsymbol-chars)
-            (point))))
-
-      (c-find-decl-spots
-       limit
-       c-decl-start-re
-       (eval c-maybe-decl-faces)
-
-       (lambda (match-pos inside-macro &optional toplev)
-        ;; Note to maintainers: don't use `limit' inside this lambda form;
-        ;; c-find-decl-spots sometimes narrows to less than `limit'.
-        (setq start-pos (point))
-        (when
-         ;; The result of the form below is true when we don't recognize a
-         ;; declaration or cast, and we don't recognize a "non-decl",
-         ;; typically a brace list.
-         (if (or (and (eq (get-text-property (point) 'face)
-                          'font-lock-keyword-face)
-                      (looking-at c-not-decl-init-keywords))
-                 (and c-macro-with-semi-re
-                      (looking-at c-macro-with-semi-re))) ; 2008-11-04
-             ;; Don't do anything more if we're looking at a keyword that
-             ;; can't start a declaration.
-             t
-
-           ;; Set `context' and `c-restricted-<>-arglists'.  Look for
-           ;; "<" for the sake of C++-style template arglists.
-           ;; Ignore "(" when it's part of a control flow construct
-           ;; (e.g. "for (").
-           (let ((got-context
-                  (c-get-fontification-context
-                   match-pos
-                   (< match-pos (if inside-macro
-                                    max-type-decl-end-before-token
-                                  max-type-decl-end))
-                   toplev)))
-             (setq context (car got-context)
-                   c-restricted-<>-arglists (cdr got-context)))
-
-           ;; Check we haven't missed a preceding "typedef".
-           (when (not (looking-at c-typedef-key))
-             (c-backward-syntactic-ws)
-             (c-backward-token-2)
-             (or (looking-at c-typedef-key)
-                 (goto-char start-pos)))
-
-           ;; In QT, "more" is an irritating keyword that expands to nothing.
-           ;; We skip over it to prevent recognition of "more slots: <symbol>"
-           ;; as a bitfield declaration.
-           (when (and (c-major-mode-is 'c++-mode)
-                      (looking-at
-                       (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)")))
-             (goto-char (match-end 1))
-             (c-forward-syntactic-ws))
-
-           ;; Now analyze the construct.
-           (if (eq context 'not-decl)
-               (progn
-                 (setq decl-or-cast nil)
-                 (if (c-syntactic-re-search-forward
-                      "," (min limit (point-max)) 'at-limit t)
-                     (c-put-char-property (1- (point)) 'c-type 'c-not-decl))
-                 nil)
-             (setq decl-or-cast
-                   (c-forward-decl-or-cast-1
-                    match-pos context last-cast-end))
-
-             ;; Ensure that c-<>-arg-sep c-type properties are in place on the
-             ;; commas separating the arguments inside template/generic <..>s.
-             (when (and (eq (char-before match-pos) ?<)
-                        (> match-pos max-<>-end))
-               (save-excursion
-                 (goto-char match-pos)
-                 (c-backward-token-2)
-                 (if (and
-                      (eq (char-after) ?<)
-                      (let ((c-restricted-<>-arglists
-                             (save-excursion
-                               (c-backward-token-2)
-                               (and
-                                (not (looking-at c-opt-<>-sexp-key))
-                                (progn (c-backward-syntactic-ws)
-                                       (memq (char-before) '(?\( ?,)))
-                                (not (eq (c-get-char-property (1- (point))
-                                                              'c-type)
-                                         'c-decl-arg-start))))))
-                        (c-forward-<>-arglist nil)))
-                     (setq max-<>-end (point)))))
-
-             (cond
-              ((eq decl-or-cast 'cast)
-               ;; Save the position after the previous cast so we can feed
-               ;; it to `c-forward-decl-or-cast-1' in the next round.  That
-               ;; helps it discover cast chains like "(a) (b) c".
-               (setq last-cast-end (point))
-               (c-fontify-recorded-types-and-refs)
-               nil)
-
-              (decl-or-cast
-               ;; We've found a declaration.
-
-               ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
-               ;; under the assumption that we're after the first type decl
-               ;; expression in the declaration now.  That's not really true;
-               ;; we could also be after a parenthesized initializer
-               ;; expression in C++, but this is only used as a last resort
-               ;; to slant ambiguous expression/declarations, and overall
-               ;; it's worth the risk to occasionally fontify an expression
-               ;; as a declaration in an initializer expression compared to
-               ;; getting ambiguous things in normal function prototypes
-               ;; fontified as expressions.
-               (if inside-macro
-                   (when (> (point) max-type-decl-end-before-token)
-                     (setq max-type-decl-end-before-token (point)))
-                 (when (> (point) max-type-decl-end)
-                   (setq max-type-decl-end (point))))
-               (goto-char start-pos)
-               (c-font-lock-single-decl limit decl-or-cast match-pos
-                                        context
-                                        (or toplev (nth 4 decl-or-cast))))
-
-              (t t))))
-
-         ;; It was a false alarm.  Check if we're in a label (or other
-         ;; construct with `:' except bitfield) instead.
-         (goto-char start-pos)
-         (when (setq label-type (c-forward-label t match-pos nil))
-           ;; Can't use `c-fontify-types-and-refs' here since we
-           ;; use the label face at times.
-           (cond ((eq label-type 'goto-target)
-                  (c-put-font-lock-face (caar c-record-ref-identifiers)
-                                        (cdar c-record-ref-identifiers)
-                                        c-label-face-name))
-                 ((eq label-type 'qt-1kwd-colon)
-                  (c-put-font-lock-face (caar c-record-ref-identifiers)
-                                        (cdar c-record-ref-identifiers)
-                                        'font-lock-keyword-face))
-                 ((eq label-type 'qt-2kwds-colon)
-                  (mapc
-                   (lambda (kwd)
-                     (c-put-font-lock-face (car kwd) (cdr kwd)
+                ;; Now analyze the construct.
+                (if (eq context 'not-decl)
+                    (progn
+                      (setq decl-or-cast nil)
+                      (if (c-syntactic-re-search-forward
+                           "," (min limit (point-max)) 'at-limit t)
+                          (c-put-char-property (1- (point)) 'c-type 'c-not-decl))
+                      nil)
+                  (setq decl-or-cast
+                        (c-forward-decl-or-cast-1
+                         match-pos context last-cast-end))
+
+                  ;; Ensure that c-<>-arg-sep c-type properties are in place on the
+                  ;; commas separating the arguments inside template/generic <..>s.
+                  (when (and (eq (char-before match-pos) ?<)
+                             (> match-pos max-<>-end))
+                    (save-excursion
+                      (goto-char match-pos)
+                      (c-backward-token-2)
+                      (if (and
+                           (eq (char-after) ?<)
+                           (let ((c-restricted-<>-arglists
+                                  (save-excursion
+                                    (c-backward-token-2)
+                                    (and
+                                     (not (looking-at c-opt-<>-sexp-key))
+                                     (progn (c-backward-syntactic-ws)
+                                            (memq (char-before) '(?\( ?,)))
+                                     (not (eq (c-get-char-property (1- (point))
+                                                                   'c-type)
+                                              'c-decl-arg-start))))))
+                             (c-forward-<>-arglist nil)))
+                          (setq max-<>-end (point)))))
+
+                  (cond
+                   ((eq decl-or-cast 'cast)
+                    ;; Save the position after the previous cast so we can feed
+                    ;; it to `c-forward-decl-or-cast-1' in the next round.  That
+                    ;; helps it discover cast chains like "(a) (b) c".
+                    (setq last-cast-end (point))
+                    (c-fontify-recorded-types-and-refs)
+                    nil)
+
+                   (decl-or-cast
+                    ;; We've found a declaration.
+
+                    ;; Set `max-type-decl-end' or `max-type-decl-end-before-token'
+                    ;; under the assumption that we're after the first type decl
+                    ;; expression in the declaration now.  That's not really true;
+                    ;; we could also be after a parenthesized initializer
+                    ;; expression in C++, but this is only used as a last resort
+                    ;; to slant ambiguous expression/declarations, and overall
+                    ;; it's worth the risk to occasionally fontify an expression
+                    ;; as a declaration in an initializer expression compared to
+                    ;; getting ambiguous things in normal function prototypes
+                    ;; fontified as expressions.
+                    (if inside-macro
+                        (when (> (point) max-type-decl-end-before-token)
+                          (setq max-type-decl-end-before-token (point)))
+                      (when (> (point) max-type-decl-end)
+                        (setq max-type-decl-end (point))))
+                    (goto-char start-pos)
+                    (c-font-lock-single-decl limit decl-or-cast match-pos
+                                             context
+                                             (or toplev (nth 4 decl-or-cast))))
+
+                   (t t))))
+
+            ;; It was a false alarm.  Check if we're in a label (or other
+            ;; construct with `:' except bitfield) instead.
+            (goto-char start-pos)
+            (when (setq label-type (c-forward-label t match-pos nil))
+              ;; Can't use `c-fontify-types-and-refs' here since we
+              ;; use the label face at times.
+              (cond ((eq label-type 'goto-target)
+                     (c-put-font-lock-face (caar c-record-ref-identifiers)
+                                           (cdar c-record-ref-identifiers)
+                                           c-label-face-name))
+                    ((eq label-type 'qt-1kwd-colon)
+                     (c-put-font-lock-face (caar c-record-ref-identifiers)
+                                           (cdar c-record-ref-identifiers)
                                            'font-lock-keyword-face))
-                   c-record-ref-identifiers)))
-           (setq c-record-ref-identifiers nil)
-           ;; `c-forward-label' has probably added a `c-decl-end'
-           ;; marker, so return t to `c-find-decl-spots' to signal
-           ;; that.
-           t))))
-
-      nil)))
+                    ((eq label-type 'qt-2kwds-colon)
+                     (mapc
+                      (lambda (kwd)
+                        (c-put-font-lock-face (car kwd) (cdr kwd)
+                                              'font-lock-keyword-face))
+                      c-record-ref-identifiers)))
+              (setq c-record-ref-identifiers nil)
+              ;; `c-forward-label' has probably added a `c-decl-end'
+              ;; marker, so return t to `c-find-decl-spots' to signal
+              ;; that.
+              t))))
+
+       nil))))
 
 (defun c-font-lock-enum-body (limit)
   ;; Fontify the identifiers of each enum we find by searching forward.
@@ -1561,19 +1569,21 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;;
   ;; Note that this function won't attempt to fontify beyond the end of the
   ;; current enum block, if any.
-  (let* ((paren-state (c-parse-state))
-        (encl-pos (c-most-enclosing-brace paren-state)))
-    (when (and
-          encl-pos
-          (eq (char-after encl-pos) ?\{)
-          (save-excursion
-            (goto-char encl-pos)
-            (c-backward-over-enum-header)))
-      (c-syntactic-skip-backward "^{," nil t)
-      (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start)
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
+    (let* ((paren-state (c-parse-state))
+          (encl-pos (c-most-enclosing-brace paren-state)))
+      (when (and
+            encl-pos
+            (eq (char-after encl-pos) ?\{)
+            (save-excursion
+              (goto-char encl-pos)
+              (c-backward-over-enum-header)))
+       (c-syntactic-skip-backward "^{," nil t)
+       (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start)
 
-      (c-forward-syntactic-ws)
-      (c-font-lock-declarators limit t nil t)))
+       (c-forward-syntactic-ws)
+       (c-font-lock-declarators limit t nil t))))
   nil)
 
 (defun c-font-lock-cut-off-declarators (limit)
@@ -1585,46 +1595,48 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
   ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
   ;; fontification".
-  (let ((here (point))
-       (decl-search-lim (c-determine-limit 1000))
-       paren-state encl-pos token-end context decl-or-cast
-       start-pos top-level c-restricted-<>-arglists
-       c-recognize-knr-p)              ; Strictly speaking, bogus, but it
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
+    (let ((here (point))
+         (decl-search-lim (c-determine-limit 1000))
+         paren-state encl-pos token-end context decl-or-cast
+         start-pos top-level c-restricted-<>-arglists
+         c-recognize-knr-p)            ; Strictly speaking, bogus, but it
                                        ; speeds up lisp.h tremendously.
-    (save-excursion
-      (when (not (c-back-over-member-initializers))
-       (unless (or (eobp)
-                   (looking-at "\\s(\\|\\s)"))
-         (forward-char))
-       (c-syntactic-skip-backward "^;{}" decl-search-lim t)
-       (when (eq (char-before) ?})
-         (c-go-list-backward)  ; brace block of struct, etc.?
-         (c-syntactic-skip-backward "^;{}" decl-search-lim t))
-       (when (or (bobp)
-                 (memq (char-before) '(?\; ?{ ?})))
-         (setq token-end (point))
-         (c-forward-syntactic-ws here)
-         (when (< (point) here)
-           ;; We're now putatively at the declaration.
-           (setq start-pos (point))
-           (setq paren-state (c-parse-state))
-           ;; At top level or inside a "{"?
-           (if (or (not (setq encl-pos
-                              (c-most-enclosing-brace paren-state)))
-                   (eq (char-after encl-pos) ?\{))
-               (progn
-                 (setq top-level (c-at-toplevel-p))
-                 (let ((got-context (c-get-fontification-context
-                                     token-end nil top-level)))
-                   (setq context (car got-context)
-                         c-restricted-<>-arglists (cdr got-context)))
-                 (setq decl-or-cast
-                       (c-forward-decl-or-cast-1 token-end context nil))
-                 (when (consp decl-or-cast)
-                   (goto-char start-pos)
-                   (c-font-lock-single-decl limit decl-or-cast token-end
-                                            context top-level))))))))
-    nil))
+      (save-excursion
+       (when (not (c-back-over-member-initializers))
+         (unless (or (eobp)
+                     (looking-at "\\s(\\|\\s)"))
+           (forward-char))
+         (c-syntactic-skip-backward "^;{}" decl-search-lim t)
+         (when (eq (char-before) ?})
+           (c-go-list-backward)        ; brace block of struct, etc.?
+           (c-syntactic-skip-backward "^;{}" decl-search-lim t))
+         (when (or (bobp)
+                   (memq (char-before) '(?\; ?{ ?})))
+           (setq token-end (point))
+           (c-forward-syntactic-ws here)
+           (when (< (point) here)
+             ;; We're now putatively at the declaration.
+             (setq start-pos (point))
+             (setq paren-state (c-parse-state))
+             ;; At top level or inside a "{"?
+             (if (or (not (setq encl-pos
+                                (c-most-enclosing-brace paren-state)))
+                     (eq (char-after encl-pos) ?\{))
+                 (progn
+                   (setq top-level (c-at-toplevel-p))
+                   (let ((got-context (c-get-fontification-context
+                                       token-end nil top-level)))
+                     (setq context (car got-context)
+                           c-restricted-<>-arglists (cdr got-context)))
+                   (setq decl-or-cast
+                         (c-forward-decl-or-cast-1 token-end context nil))
+                   (when (consp decl-or-cast)
+                     (goto-char start-pos)
+                     (c-font-lock-single-decl limit decl-or-cast token-end
+                                              context top-level))))))))
+      nil)))
 
 (defun c-font-lock-enclosing-decls (limit)
   ;; Fontify the declarators of (nested) declarations we're in the middle of.
@@ -1636,27 +1648,29 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;; font-lock-keyword-face.  It always returns NIL to inhibit this and
   ;; prevent a repeat invocation.  See elisp/lispref page "Search-based
   ;; Fontification".
-  (let* ((paren-state (c-parse-state))
-        (decl-search-lim (c-determine-limit 1000))
-        in-typedef ps-elt)
-    ;; Are we in any nested struct/union/class/etc. braces?
-    (while paren-state
-      (setq ps-elt (car paren-state)
-           paren-state (cdr paren-state))
-      (when (and (atom ps-elt)
-                (eq (char-after ps-elt) ?\{))
-       (goto-char ps-elt)
-       (c-syntactic-skip-backward "^;{}" decl-search-lim)
-       (c-forward-syntactic-ws)
-       (setq in-typedef (looking-at c-typedef-key))
-       (if in-typedef (c-forward-over-token-and-ws))
-       (when (and c-opt-block-decls-with-vars-key
-                  (looking-at c-opt-block-decls-with-vars-key))
+  (c-skip-comments-and-strings limit)
+  (when (< (point) limit)
+    (let* ((paren-state (c-parse-state))
+          (decl-search-lim (c-determine-limit 1000))
+          in-typedef ps-elt)
+      ;; Are we in any nested struct/union/class/etc. braces?
+      (while paren-state
+       (setq ps-elt (car paren-state)
+             paren-state (cdr paren-state))
+       (when (and (atom ps-elt)
+                  (eq (char-after ps-elt) ?\{))
          (goto-char ps-elt)
-         (when (c-safe (c-forward-sexp))
-           (c-forward-syntactic-ws)
-           (c-font-lock-declarators limit t in-typedef
-                                    (not (c-bs-at-toplevel-p (point))))))))))
+         (c-syntactic-skip-backward "^;{}" decl-search-lim)
+         (c-forward-syntactic-ws)
+         (setq in-typedef (looking-at c-typedef-key))
+         (if in-typedef (c-forward-over-token-and-ws))
+         (when (and c-opt-block-decls-with-vars-key
+                    (looking-at c-opt-block-decls-with-vars-key))
+           (goto-char ps-elt)
+           (when (c-safe (c-forward-sexp))
+             (c-forward-syntactic-ws)
+             (c-font-lock-declarators limit t in-typedef
+                                      (not (c-bs-at-toplevel-p (point)))))))))))
 
 (defun c-font-lock-raw-strings (limit)
   ;; Fontify C++ raw strings.
index 35de7566c789ecc9fb07a189a22f9f5732010ad8..27ed04fea52439681fa4b5d88c39b9c05f805f19 100644 (file)
@@ -1192,8 +1192,6 @@ Note that the style variables are always made local to the buffer."
        (beg-literal-type (and beg-limits
                                       (c-literal-type beg-limits))))
 
-    (when (eq end-literal-type 'string)
-      (setq c-new-END (max c-new-END (cdr end-limits))))
     ;; It is possible the buffer change will include inserting a string quote.
     ;; This could have the effect of flipping the meaning of any following
     ;; quotes up until the next unescaped EOL.  Also guard against the change
@@ -1282,7 +1280,6 @@ Note that the style variables are always made local to the buffer."
 
       (when (and (eq beg-literal-type 'string)
                 (memq (char-after (car beg-limits)) c-string-delims))
-       (setq c-new-BEG (min c-new-BEG (car beg-limits)))
        (c-clear-char-property (car beg-limits) 'syntax-table)
        (c-truncate-semi-nonlit-pos-cache (car beg-limits))))))
 
@@ -1832,6 +1829,9 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
   ;; declaration is one which does not start outside of struct braces (and
   ;; similar) enclosing POS.  Brace list braces here are not "similar".
   ;;
+  ;; POS being in a literal does not count as being in a declaration (on
+  ;; pragmatic grounds).
+  ;;
   ;; This function is called indirectly from font locking stuff - either from
   ;; c-after-change (to prepare for after-change font-locking) or from font
   ;; lock context (etc.) fontification.
@@ -1842,92 +1842,92 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
        capture-opener
        bod-lim bo-decl)
     (goto-char (c-point 'bol new-pos))
-    (when lit-start                    ; Comment or string.
-      (goto-char lit-start))
-    (setq bod-lim (c-determine-limit 500))
-
-    ;; In C++ Mode, first check if we are within a (possibly nested) lambda
-    ;; form capture list.
-    (when (c-major-mode-is 'c++-mode)
-      (let ((paren-state (c-parse-state))
-           opener)
-       (save-excursion
-         (while (setq opener (c-pull-open-brace paren-state))
-           (goto-char opener)
-           (if (c-looking-at-c++-lambda-capture-list)
-               (setq capture-opener (point)))))))
-
-    (while
-       ;; Go to a less nested declaration each time round this loop.
-       (and
-        (setq old-pos (point))
-        (let (pseudo)
-          (while
-              (progn
-                (c-syntactic-skip-backward "^;{}" bod-lim t)
-                (and (eq (char-before) ?})
-                     (save-excursion
-                       (backward-char)
-                       (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state))))))
-            (goto-char pseudo))
-          t)
-        (> (point) bod-lim)
-        (progn (c-forward-syntactic-ws)
-               ;; Have we got stuck in a comment at EOB?
-               (not (and (eobp)
-                         (c-literal-start))))
-        (< (point) old-pos)
-        (progn (setq bo-decl (point))
-               (or (not (looking-at c-protection-key))
-                   (c-forward-keyword-clause 1)))
-        (progn
-          ;; Are we looking at a keyword such as "template" or
-          ;; "typedef" which can decorate a type, or the type itself?
-          (when (or (looking-at c-prefix-spec-kwds-re)
-                    (c-forward-type t))
-            ;; We've found another candidate position.
-            (setq new-pos (min new-pos bo-decl))
-            (goto-char bo-decl))
-          t)
-        ;; Try and go out a level to search again.
-        (progn
-          (c-backward-syntactic-ws bod-lim)
-          (and (> (point) bod-lim)
-               (or (memq (char-before) '(?\( ?\[))
-                   (and (eq (char-before) ?\<)
-                        (eq (c-get-char-property
-                             (1- (point)) 'syntax-table)
-                            c-<-as-paren-syntax))
-                   (and (eq (char-before) ?{)
-                        (save-excursion
-                          (backward-char)
-                          (consp (c-looking-at-or-maybe-in-bracelist))))
-                   )))
-        (not (bobp)))
-      (backward-char))                 ; back over (, [, <.
-    (when (and capture-opener (< capture-opener new-pos))
-      (setq new-pos capture-opener))
-    (and (/= new-pos pos) new-pos)))
+    (unless lit-start
+      (setq bod-lim (c-determine-limit 500))
+
+      ;; In C++ Mode, first check if we are within a (possibly nested) lambda
+      ;; form capture list.
+      (when (c-major-mode-is 'c++-mode)
+       (let ((paren-state (c-parse-state))
+             opener)
+         (save-excursion
+           (while (setq opener (c-pull-open-brace paren-state))
+             (goto-char opener)
+             (if (c-looking-at-c++-lambda-capture-list)
+                 (setq capture-opener (point)))))))
+
+      (while
+         ;; Go to a less nested declaration each time round this loop.
+         (and
+          (setq old-pos (point))
+          (let (pseudo)
+            (while
+                (progn
+                  (c-syntactic-skip-backward "^;{}" bod-lim t)
+                  (and (eq (char-before) ?})
+                       (save-excursion
+                         (backward-char)
+                         (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state))))))
+              (goto-char pseudo))
+            t)
+          (> (point) bod-lim)
+          (progn (c-forward-syntactic-ws)
+                 ;; Have we got stuck in a comment at EOB?
+                 (not (and (eobp)
+                           (c-literal-start))))
+          (< (point) old-pos)
+          (progn (setq bo-decl (point))
+                 (or (not (looking-at c-protection-key))
+                     (c-forward-keyword-clause 1)))
+          (progn
+            ;; Are we looking at a keyword such as "template" or
+            ;; "typedef" which can decorate a type, or the type itself?
+            (when (or (looking-at c-prefix-spec-kwds-re)
+                      (c-forward-type t))
+              ;; We've found another candidate position.
+              (setq new-pos (min new-pos bo-decl))
+              (goto-char bo-decl))
+            t)
+          ;; Try and go out a level to search again.
+          (progn
+            (c-backward-syntactic-ws bod-lim)
+            (and (> (point) bod-lim)
+                 (or (memq (char-before) '(?\( ?\[))
+                     (and (eq (char-before) ?\<)
+                          (eq (c-get-char-property
+                               (1- (point)) 'syntax-table)
+                              c-<-as-paren-syntax))
+                     (and (eq (char-before) ?{)
+                          (save-excursion
+                            (backward-char)
+                            (consp (c-looking-at-or-maybe-in-bracelist))))
+                     )))
+          (not (bobp)))
+       (backward-char))                ; back over (, [, <.
+      (when (and capture-opener (< capture-opener new-pos))
+       (setq new-pos capture-opener))
+      (and (/= new-pos pos) new-pos))))
 
 (defun c-fl-decl-end (pos)
   ;; If POS is inside a declarator, return the end of the token that follows
-  ;; the declarator, otherwise return nil.
+  ;; the declarator, otherwise return nil.  POS being in a literal does not
+  ;; count as being in a declarator (on pragmatic grounds).
   (goto-char pos)
   (let ((lit-start (c-literal-start))
        pos1)
-    (if lit-start (goto-char lit-start))
-    (c-backward-syntactic-ws)
-    (when (setq pos1 (c-on-identifier))
-      (goto-char pos1)
-      (let ((lim (save-excursion
-                  (and (c-beginning-of-macro)
-                       (progn (c-end-of-macro) (point))))))
-       (when (and (c-forward-declarator lim)
-                  (or (not (eq (char-after) ?\())
-                      (c-go-list-forward nil lim))
-                  (eq (c-forward-token-2 1 nil lim) 0))
-         (c-backward-syntactic-ws)
-         (point))))))
+    (unless lit-start
+      (c-backward-syntactic-ws)
+      (when (setq pos1 (c-on-identifier))
+       (goto-char pos1)
+       (let ((lim (save-excursion
+                    (and (c-beginning-of-macro)
+                         (progn (c-end-of-macro) (point))))))
+         (when (and (c-forward-declarator lim)
+                    (or (not (eq (char-after) ?\())
+                        (c-go-list-forward nil lim))
+                    (eq (c-forward-token-2 1 nil lim) 0))
+           (c-backward-syntactic-ws)
+           (point)))))))
 
 (defun c-change-expand-fl-region (_beg _end _old-len)
   ;; Expand the region (c-new-BEG c-new-END) to an after-change font-lock