From 4cb8696e4754d815efd5fd5e26f2b6b2567a11fe Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Wed, 13 Dec 2017 20:55:03 +0000 Subject: [PATCH] Don't misfontify "foo ()" inside C++ initialization parentheses as a type Also recognize and handle function names introduced by "extern" inside a function. * lisp/progmodes/cc-engine.el (c-forward-decl-or-cast-1): Add a new element to the result list which is t when our declaration is, or is to be treated as, being at top level. * lisp/progmodes/cc-fonts.el (c-get-fontification-context): Detect being inside a C++ uniform initialization and return (not-decl nil) for this case. (c-font-lock-declarations): Use the new element 4 of the result of c-forward-decl-or-cast-1. * lisp/progmodes/cc-langs.el (c-make-top-level-kwds, c-make-top-level-key): New lang consts/vars. --- lisp/progmodes/cc-engine.el | 25 +++++++++++++++++-------- lisp/progmodes/cc-fonts.el | 14 +++++++++++++- lisp/progmodes/cc-langs.el | 10 ++++++++++ 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index ab0204cb961..138a0e5da21 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -8167,9 +8167,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 list of 4 elements, + ;; declarator, if there is one. The return value is a list of 5 elements, ;; where the first is the position of the first token in the declarator. - ;; (See below for the other three.) + ;; (See below for the other four.) ;; Some examples: ;; ;; void foo (int a, char *b) stuff ... @@ -8210,7 +8210,9 @@ comment at the start of cc-engine.el for more info." ;; ;; 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. + ;; the start of the type identifier. The fifth element is t if either + ;; CONTEXT was 'top, or the declaration is detected to be treated as top + ;; level (e.g. with the keyword "extern"). ;; ;; If a cast is parsed: ;; @@ -8308,6 +8310,9 @@ comment at the start of cc-engine.el for more info." ;; Set when the symbol before `preceding-token-end' is known to ;; terminate the previous construct, or when we're at point-min. at-decl-start + ;; Set when we have encountered a keyword (e.g. "extern") which + ;; causes the following declaration to be treated as though top-level. + make-top ;; Save `c-record-type-identifiers' and ;; `c-record-ref-identifiers' since ranges are recorded ;; speculatively and should be thrown away if it turns out @@ -8339,7 +8344,9 @@ comment at the start of cc-engine.el for more info." (cond ;; Look for a specifier keyword clause. - ((or (looking-at c-prefix-spec-kwds-re) + ((or (and (looking-at c-make-top-level-key) + (setq make-top t)) + (looking-at c-prefix-spec-kwds-re) (and (c-major-mode-is 'java-mode) (looking-at "@[A-Za-z0-9]+"))) (save-match-data @@ -8609,7 +8616,7 @@ comment at the start of cc-engine.el for more info." ;; construct here in C, since we want to recognize this as a ;; typeless function declaration. (not (and (c-major-mode-is 'c-mode) - (eq context 'top) + (or (eq context 'top) make-top) (eq (char-after) ?\))))) (if (eq (char-after) ?\)) (when (> paren-depth 0) @@ -8657,7 +8664,7 @@ comment at the start of cc-engine.el for more info." ;; Recognize a top-level typeless ;; function declaration in C. (and (c-major-mode-is 'c-mode) - (eq context 'top) + (or (eq context 'top) make-top) (eq (char-after) ?\)))))))) (setq pos (c-up-list-forward (point))) (eq (char-before pos) ?\))) @@ -8914,6 +8921,7 @@ comment at the start of cc-engine.el for more info." (when (and got-identifier (looking-at c-after-suffixed-type-decl-key) (or (eq context 'top) + make-top (and (eq context nil) (match-beginning 1))) (if (and got-parens @@ -9080,7 +9088,7 @@ comment at the start of cc-engine.el for more info." ;; CASE 19 (or (eq context 'decl) (and (c-major-mode-is 'c-mode) - (eq context 'top)))))) + (or (eq context 'top) make-top)))))) ;; The point is now after the type decl expression. @@ -9185,7 +9193,8 @@ comment at the start of cc-engine.el for more info." (and (or at-type-decl at-typedef) (cons at-type-decl at-typedef)) maybe-expression - type-start)) + type-start + (or (eq context 'top) make-top))) (t ;; False alarm. Restore the recorded ranges. diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index d352e5b08c9..7b99c2f54e5 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1251,6 +1251,17 @@ casts and declarations are fontified. Used on level 2 and higher." ;; Got a cached hit in some other type of arglist. (type (cons 'arglist t)) + ;; We're at a C++ uniform initialization. + ((and (c-major-mode-is 'c++-mode) + (eq (char-before match-pos) ?\() + (save-excursion + (goto-char match-pos) + (and + (zerop (c-backward-token-2 2)) + (looking-at c-identifier-start) + (c-got-face-at (point) + '(font-lock-variable-name-face))))) + (cons 'not-decl nil)) ((and not-front-decl ;; The point is within the range of a previously ;; encountered type decl expression, so the arglist @@ -1589,7 +1600,8 @@ casts and declarations are fontified. Used on level 2 and higher." (setq max-type-decl-end (point)))) (goto-char start-pos) (c-font-lock-single-decl limit decl-or-cast match-pos - context toplev)) + context + (or toplev (nth 4 decl-or-cast)))) (t t)))) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 227b3e16485..869048bee31 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -2355,6 +2355,16 @@ construct it's part of continues." t nil (c c++ objc) '("extern")) +(c-lang-defconst c-make-top-level-kwds + "Keywords which make declarations they introduce be handled as top-level." + t nil + (c c++ objc) '("extern")) + +(c-lang-defconst c-make-top-level-key + ;; A regexp which matches any `c-make-top-level-kwds' keyword. + t (c-make-keywords-re t (c-lang-const c-make-top-level-kwds))) +(c-lang-defvar c-make-top-level-key (c-lang-const c-make-top-level-key)) + (c-lang-defconst c-type-list-kwds "Keywords that may be followed by a comma separated list of type identifiers, where each optionally can be prefixed by keywords. (Can -- 2.39.2