From 8c21f8fab915a5dabd7c3d10aae07ff36a3830e4 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Fri, 16 Jun 2017 11:26:59 +0000 Subject: [PATCH] Ensure C++ initializer lists don't get fontified. * lisp/progmodes/cc-cmds.el (c-block-comment-flag): Move declaration to solve compiler warning. * lisp/progmodes/cc-fonts.el (c-get-fontification-context): Add an extra clause to handle C++ member initialization lists. (c-font-lock-single-decl): New function, extracted from c-font-lock-declarations. (c-font-lock-declarations): Call c-font-lock-single-decl in place of inline code. (c-font-lock-cut-off-declarators): Make more rigorous by calling c-get-fontification-context, c-forward-decl-or-cast-1, and c-font-lock-single-decl in place of rather approximate code. --- lisp/progmodes/cc-cmds.el | 10 +-- lisp/progmodes/cc-fonts.el | 177 +++++++++++++++++++++---------------- 2 files changed, 108 insertions(+), 79 deletions(-) diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index 6250725c179..c05200b3898 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -251,6 +251,11 @@ With universal argument, inserts the analysis as a comment on that line." ;; Minor mode functions. +;; `c-block-comment-flag' gets initialized to the current mode's default in +;; c-basic-common-init. +(defvar c-block-comment-flag nil) +(make-variable-buffer-local 'c-block-comment-flag) + (defun c-update-modeline () (let ((fmt (format "/%s%s%s%s%s" (if c-block-comment-flag "*" "/") @@ -360,11 +365,6 @@ left out." (electric-indent-local-mode (if c-electric-flag 1 0))) (c-keep-region-active)) -;; `c-block-comment-flag' gets initialized to the current mode's default in -;; c-basic-common-init. -(defvar c-block-comment-flag nil) -(make-variable-buffer-local 'c-block-comment-flag) - (defun c-toggle-comment-style (&optional arg) "Toggle the comment style between block and line comments. Optional numeric ARG, if supplied, switches to block comment diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index adb1f1a4937..9bae7d9aa2f 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1214,6 +1214,12 @@ casts and declarations are fontified. Used on level 2 and higher." (and (zerop (c-backward-token-2 2)) (looking-at c-arithmetic-op-regexp)))) (cons nil nil)) + ;; In a C++ member initialization list. + ((and (eq (char-before match-pos) ?,) + (c-major-mode-is 'c++-mode) + (save-excursion (c-back-over-member-initializers))) + (c-put-char-property (1- match-pos) 'c-type 'c-not-decl) + (cons 'not-decl nil)) ;; At start of a declaration inside a declaration paren. ((save-excursion (and (memq (char-before match-pos) '(?\( ?\,)) @@ -1235,6 +1241,85 @@ casts and declarations are fontified. Used on level 2 and higher." (cons 'decl nil)) (t (cons 'arglist t))))) +(defun c-font-lock-single-decl (limit decl-or-cast match-pos context toplev) + ;; Try to fontify a single declaration, together with all its declarators. + ;; Return nil if we're successful, non-nil if we fail. POINT should be + ;; positioned at the start of the putative declaration before calling. + ;; POINT is left undefined by this function. + ;; + ;; LIMIT sets a maximum position we'll fontify out to. + ;; DECL-OR-CAST has the form of a result from `c-forward-decl-or-cast-1', + ;; and must indicate a declaration (i.e. not be nil or 'cast). + ;; MATCH-POS is the position after the last symbol before the decl. + ;; CONTEXT is the context of the current decl., as determined by + ;; c-get-fontification-context. + ;; TOPLEV is non-nil if the decl. is at the top level (i.e. outside any + ;; braces, or directly inside a class, namespace, etc.) + + ;; Do we have an expression as the second or third clause of + ;; a "for" paren expression? + (if (save-excursion + (and + (car (cddr decl-or-cast)) ; maybe-expression flag. + (c-go-up-list-backward) + (eq (char-after) ?\() + (progn (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (looking-at c-paren-stmt-key) + (progn (goto-char match-pos) + (while (and (eq (char-before) ?\)) + (c-go-list-backward)) + (c-backward-syntactic-ws)) + (eq (char-before) ?\;)))) + ;; We've got an expression in "for" parens. Remove the + ;; "type" that would spuriously get fontified. + (let ((elt (and (consp c-record-type-identifiers) + (assq (cadr (cddr decl-or-cast)) + c-record-type-identifiers)))) + (when elt + (setq c-record-type-identifiers + (c-delq-from-dotted-list + elt c-record-type-identifiers))) + t) + ;; Back up to the type to fontify the declarator(s). + (goto-char (car decl-or-cast)) + + (let ((decl-list + (if (not (memq context '(nil top))) + ;; Should normally not fontify a list of + ;; declarators inside an arglist, but the first + ;; argument in the ';' separated list of a "for" + ;; statement is an exception. + (when (eq (char-before match-pos) ?\() + (save-excursion + (goto-char (1- match-pos)) + (c-backward-syntactic-ws) + (and (c-simple-skip-symbol-backward) + (looking-at c-paren-stmt-key)))) + t))) + + ;; Fix the `c-decl-id-start' or `c-decl-type-start' property + ;; before the first declarator if it's a list. + ;; `c-font-lock-declarators' handles the rest. + (when decl-list + (save-excursion + (c-backward-syntactic-ws) + (unless (bobp) + (c-put-char-property (1- (point)) 'c-type + (if (cadr decl-or-cast) + 'c-decl-type-start + 'c-decl-id-start))))) + + (c-font-lock-declarators + (min limit (point-max)) decl-list + (cadr decl-or-cast) (not toplev))) + + ;; A declaration has been successfully identified, so do all the + ;; fontification of types and refs that've been recorded. + (c-fontify-recorded-types-and-refs) + nil)) + + (defun c-font-lock-declarations (limit) ;; Fontify all the declarations, casts and labels from the point to LIMIT. ;; Assumes that strings and comments have been fontified already. @@ -1436,70 +1521,9 @@ casts and declarations are fontified. Used on level 2 and higher." (setq max-type-decl-end-before-token (point))) (when (> (point) max-type-decl-end) (setq max-type-decl-end (point)))) - - ;; Do we have an expression as the second or third clause of - ;; a "for" paren expression? - (if (save-excursion - (and - (car (cddr decl-or-cast)) ; maybe-expression flag. - (goto-char start-pos) - (c-go-up-list-backward) - (eq (char-after) ?\() - (progn (c-backward-syntactic-ws) - (c-simple-skip-symbol-backward)) - (looking-at c-paren-stmt-key) - (progn (goto-char match-pos) - (while (and (eq (char-before) ?\)) - (c-go-list-backward)) - (c-backward-syntactic-ws)) - (eq (char-before) ?\;)))) - ;; We've got an expression in "for" parens. Remove the - ;; "type" that would spuriously get fontified. - (let ((elt (and (consp c-record-type-identifiers) - (assq (cadr (cddr decl-or-cast)) - c-record-type-identifiers)))) - (when elt - (setq c-record-type-identifiers - (c-delq-from-dotted-list - elt c-record-type-identifiers))) - t) - ;; Back up to the type to fontify the declarator(s). - (goto-char (car decl-or-cast)) - - (let ((decl-list - (if (not (memq context '(nil top))) - ;; Should normally not fontify a list of - ;; declarators inside an arglist, but the first - ;; argument in the ';' separated list of a "for" - ;; statement is an exception. - (when (eq (char-before match-pos) ?\() - (save-excursion - (goto-char (1- match-pos)) - (c-backward-syntactic-ws) - (and (c-simple-skip-symbol-backward) - (looking-at c-paren-stmt-key)))) - t))) - - ;; Fix the `c-decl-id-start' or `c-decl-type-start' property - ;; before the first declarator if it's a list. - ;; `c-font-lock-declarators' handles the rest. - (when decl-list - (save-excursion - (c-backward-syntactic-ws) - (unless (bobp) - (c-put-char-property (1- (point)) 'c-type - (if (cadr decl-or-cast) - 'c-decl-type-start - 'c-decl-id-start))))) - - (c-font-lock-declarators - (min limit (point-max)) decl-list - (cadr decl-or-cast) (not toplev))) - - ;; A declaration has been successfully identified, so do all the - ;; fontification of types and refs that've been recorded. - (c-fontify-recorded-types-and-refs) - nil)) + (goto-char start-pos) + (c-font-lock-single-decl limit decl-or-cast match-pos + context toplev)) (t t)))) @@ -1584,8 +1608,8 @@ casts and declarations are fontified. Used on level 2 and higher." ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; fontification". (let ((decl-search-lim (c-determine-limit 1000)) - paren-state bod-res is-typedef encl-pos - (here (point)) + 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 @@ -1599,22 +1623,27 @@ casts and declarations are fontified. Used on level 2 and higher." (c-syntactic-skip-backward "^;{}" decl-search-lim t)) (when (or (bobp) (memq (char-before) '(?\; ?{ ?}))) + (setq token-end (point)) (c-forward-syntactic-ws) ;; 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 - (when (looking-at c-typedef-key) ; "typedef" - (setq is-typedef t) - (goto-char (match-end 0)) - (c-forward-syntactic-ws)) - ;; At a real declaration? - (if (memq (c-forward-type t) '(t known found decltype)) - (c-font-lock-declarators - limit t is-typedef (not (c-bs-at-toplevel-p here))))))))) + (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) -- 2.39.2