From ca3cc92e14a6bdaf6fb817fff9e633f30d461359 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 17 Nov 2022 10:34:41 +0000 Subject: [PATCH] CC Mode: Make implicit int types following specifiers fontify correctly This fixes bug #59267. It applies to C Mode only, and refers to constructs like "register count;" which are implicitly of int type. * lisp/progmodes/cc-engine.el (c-forward-type): Use the new regexp c-maybe-typeless-specifier-re in place of c-opt-type-modifier-prefix-key. Add an extra arm to the main cond form to handle the construct, and another to handle "extern "C" foo_t my_foo;". (c-forward-decl-or-cast-1): Adapt to handle the result no-id from c-forward-type. * lisp/progmodes/cc-langs.el (c-maybe-typeless-specifier-re): New lang const/var. --- lisp/progmodes/cc-engine.el | 44 ++++++++++++++++++++++++++++--------- lisp/progmodes/cc-langs.el | 8 +++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index df8387905f6..8813ec4686b 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -9036,7 +9036,8 @@ multi-line strings (but not C++, for example)." ;; o - 'found if it's a type that matches one in `c-found-types'; ;; o - 'maybe if it's an identifier that might be a type; ;; o - 'decltype if it's a decltype(variable) declaration; - or - ;; o - 'no-id if "auto" precluded parsing a type identifier. + ;; o - 'no-id if "auto" precluded parsing a type identifier (C++) + ;; or the type int was implicit (C). ;; o - nil if it can't be a type (the point isn't moved then). ;; ;; The point is assumed to be at the beginning of a token. @@ -9060,10 +9061,11 @@ multi-line strings (but not C++, for example)." ;; Skip leading type modifiers. If any are found we know it's a ;; prefix of a type. - (when c-opt-type-modifier-prefix-key ; e.g. "const" "volatile", but NOT "typedef" - (while (looking-at c-opt-type-modifier-prefix-key) - (when (looking-at c-no-type-key) - (setq res 'no-id)) + (when c-maybe-typeless-specifier-re + (while (looking-at c-maybe-typeless-specifier-re) + (save-match-data + (when (looking-at c-no-type-key) + (setq res 'no-id))) (goto-char (match-end 1)) (c-forward-syntactic-ws) (or (eq res 'no-id) @@ -9128,6 +9130,9 @@ multi-line strings (but not C++, for example)." (not (eq res 'no-id)) (progn (setq pos nil) + (while (and c-opt-cpp-prefix + (looking-at c-noise-macro-with-parens-name-re)) + (c-forward-noise-clause)) (if (looking-at c-identifier-start) (save-excursion (setq id-start (point) @@ -9187,6 +9192,18 @@ multi-line strings (but not C++, for example)." (goto-char (match-end 1)) (c-forward-syntactic-ws))))) + ((and (eq name-res t) + (eq res 'prefix) + (c-major-mode-is 'c-mode) + (save-excursion + (goto-char id-end) + (and (not (looking-at c-symbol-start)) + (not (looking-at c-type-decl-prefix-key))))) + ;; A C specifier followed by an implicit int, e.g. + ;; "register count;" + (goto-char id-start) + (setq res 'no-id)) + (name-res (cond ((eq name-res t) ;; A normal identifier. @@ -9224,7 +9241,11 @@ multi-line strings (but not C++, for example)." (t ;; Otherwise it's an operator identifier, which is not a type. (goto-char start) - (setq res nil))))) + (setq res nil)))) + + ((eq res 'prefix) + ;; Deal with "extern "C" foo_t my_foo;" + (setq res nil))) (when (not (memq res '(nil no-id))) ;; Skip trailing type modifiers. If any are found we know it's @@ -10012,9 +10033,11 @@ This function might do hidden buffer changes." got-suffix-after-parens id-start paren-depth 0)) - (if (setq at-type (if (eq backup-at-type 'prefix) - t - backup-at-type)) + (if (not (memq + (setq at-type (if (eq backup-at-type 'prefix) + t + backup-at-type)) + '(nil no-id))) (setq type-start backup-type-start id-start backup-id-start) (setq type-start start-pos @@ -11219,7 +11242,8 @@ This function might do hidden buffer changes." ;; Record the type's coordinates in `c-record-type-identifiers' for ;; later fontification. - (when (and c-record-type-identifiers at-type ;; (not (eq at-type t)) + (when (and c-record-type-identifiers + (not (memq at-type '(nil no-id))) ;; 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. diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 291af038b79..94c84a6a702 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -3869,6 +3869,14 @@ possible for good performance." t) "\\>"))) +(c-lang-defconst c-maybe-typeless-specifier-re + "Regexp matching keywords which might, but needn't, declare variables with +no explicit type given, or nil in languages without such specifiers." + t (c-lang-const c-opt-type-modifier-prefix-key) + c (c-lang-const c-type-decl-prefix-keywords-key)) +(c-lang-defvar c-maybe-typeless-specifier-re + (c-lang-const c-maybe-typeless-specifier-re)) + (c-lang-defconst c-type-decl-prefix-key "Regexp matching any declarator operator that might precede the identifier in a declaration, e.g. the \"*\" in \"char *argv\". This -- 2.39.2