From: Alan Mackenzie Date: Mon, 16 May 2016 11:27:39 +0000 (+0000) Subject: Fix spurious fontification of "for (; a * b;)" in CC Mode. X-Git-Tag: emacs-26.0.90~1940 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=116acebfbd28649b6ccf34e5c9046738d57aa28e;p=emacs.git Fix spurious fontification of "for (; a * b;)" in CC Mode. This fixes bug #7918 (again). * lisp/progmodes/cc-engine.el (c-delq-from-dotted-list): New function. (c-forward-decl-or-cast-1): Return a 4 element list in place of the previous cons cell - additionally, return a flag indicating whether the declaration parsed might have been an expression, and the position of the type identifier in the said declaration. * lisp/progmodes/cc-fonts.el (c-font-lock-declarations): When c-forward-decl-or-cast-1 has indicated it might have parsed an expression, check for it being a spurious declaration in a "for" statement. --- diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index d19d2dacda1..2450a5db8b9 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -385,6 +385,25 @@ comment at the start of cc-engine.el for more info." ;;; 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 +7039,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 +7072,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 +7080,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 +7184,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 +7825,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 +7837,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 +7961,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. diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index e171b20f328..4e83d6df620 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1336,6 +1336,32 @@ casts and declarations are fontified. Used on level 2 and higher." (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)) @@ -1361,17 +1387,17 @@ casts and declarations are fontified. Used on level 2 and higher." (c-backward-syntactic-ws) (unless (bobp) (c-put-char-property (1- (point)) 'c-type - (if (cdr decl-or-cast) + (if (cadr decl-or-cast) 'c-decl-type-start 'c-decl-id-start))))) (c-font-lock-declarators - (point-max) decl-list (cdr decl-or-cast))) + (point-max) decl-list (cadr decl-or-cast))) ;; 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) + nil)) ;; Restore point, since at this point in the code it has been ;; left undefined by c-forward-decl-or-cast-1 above.