From 121c3d44be84ad1d4c5cccd629bb6994252950d1 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Tue, 4 Oct 2022 13:22:32 +0000 Subject: [PATCH] CC Mode: Make c-forward-declarator move over a suffix after parens, e.g. const Also tidy up several inaccuracies in the code. * lisp/progmodes/cc-engine.el (c-forward-decl-arglist): Move point for modes other than C++ Mode. (c-forward-declarator): Move over a suffix following arglist parens (e.g. const). Set the ARGLIST element of the return value to non-nil on encountering an unbalanced open parenthesis. Don't move forward out of enclosing parens. * lisp/progmodes/cc-mode.el (c-fl-decl-end): Handle being in a multi-line string. Move forward over token after declarator. --- lisp/progmodes/cc-engine.el | 200 +++++++++++++++++++----------------- lisp/progmodes/cc-mode.el | 79 +++++++------- 2 files changed, 145 insertions(+), 134 deletions(-) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index fc005183604..0ac96219a19 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -9609,40 +9609,38 @@ point unchanged and return nil." (forward-char) (c-forward-syntactic-ws limit) (looking-at "[*&]"))) - (when - (save-excursion - (let (c-last-identifier-range) - (forward-char) - (c-forward-syntactic-ws limit) - (catch 'is-function - (while - ;; Go forward one argument at each iteration. - (progn - (while - (cond - ((looking-at c-decl-hangon-key) - (c-forward-keyword-clause 1)) - ((looking-at - c-noise-macro-with-parens-name-re) - (c-forward-noise-clause)))) - (when (eq (char-after) ?\)) - (forward-char) - (c-forward-syntactic-ws limit) - (throw 'is-function t)) - (setq got-type (c-forward-type)) + (save-excursion + (let (c-last-identifier-range) + (forward-char) + (c-forward-syntactic-ws limit) + (catch 'is-function + (while + ;; Go forward one argument at each iteration. + (progn + (while (cond - ((null got-type) - (throw 'is-function nil)) - ((not (eq got-type 'maybe)) - (throw 'is-function t))) - (c-forward-declarator limit t t) - (eq (char-after) ?,)) - (forward-char) - (c-forward-syntactic-ws)) - t))) - (and (c-go-list-forward (point) limit) - (progn (c-forward-syntactic-ws limit) t))))) - t + ((looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + ((looking-at + c-noise-macro-with-parens-name-re) + (c-forward-noise-clause)))) + (when (eq (char-after) ?\)) + (forward-char) + (c-forward-syntactic-ws limit) + (throw 'is-function t)) + (setq got-type (c-forward-type)) + (cond + ((null got-type) + (throw 'is-function nil)) + ((not (eq got-type 'maybe)) + (throw 'is-function t))) + (c-forward-declarator limit t t) + (eq (char-after) ?,)) + (forward-char) + (c-forward-syntactic-ws)) + t))))) + (and (c-go-list-forward (point) limit) + (progn (c-forward-syntactic-ws limit) t)) (goto-char here) nil))) @@ -9654,10 +9652,11 @@ point unchanged and return nil." ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT DECORATED ;; ARGLIST), where ID-START and ID-END are the bounds of the declarator's ;; identifier, BRACKETS-AFTER-ID is non-nil if a [...] pair is present after - ;; the id, and ARGLIST is non-nil if an arglist has been moved over. - ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(", - ;; DECORATED is non-nil when the identifier is embellished by an operator, - ;; like "*x", or "(*x)". + ;; the id, and ARGLIST is non-nil either when an arglist has been moved + ;; over, or when we have stopped at an unbalanced open-paren. GOT-INIT is + ;; non-nil when the declarator is followed by "=" or "(", DECORATED is + ;; non-nil when the identifier is embellished by an operator, like "*x", or + ;; "(*x)". ;; ;; If ACCEPT-ANON is non-nil, move forward over any "anonymous declarator", ;; i.e. something like the (*) in int (*), such as might be found in a @@ -9707,6 +9706,7 @@ point unchanged and return nil." (if (looking-at c-overloadable-operators-regexp) (progn (goto-char (match-end 0)) + (c-forward-syntactic-ws limit) (setq got-identifier t) nil) t)) @@ -9759,25 +9759,37 @@ point unchanged and return nil." ;; Skip out of the parens surrounding the identifier. If closing ;; parens are missing, this form returns nil. (or (= paren-depth 0) - (c-safe (goto-char (scan-lists (point) 1 paren-depth)))) + (prog1 + (c-safe (goto-char (scan-lists (point) 1 paren-depth))) + (c-forward-syntactic-ws))) (or (eq (point) (point-max)) ; No token after identifier. (< (point) limit)) ;; Skip over any trailing bit, such as "__attribute__". (progn - (while (cond - ((looking-at c-decl-hangon-key) - (c-forward-keyword-clause 1)) - ((looking-at c-type-decl-suffix-key) - (if (save-match-data - (looking-at c-fun-name-substitute-key)) - (c-forward-c++-requires-clause) - (c-forward-keyword-clause 1))) - ((and c-opt-cpp-prefix - (looking-at c-noise-macro-with-parens-name-re)) - (c-forward-noise-clause)))) - (<= (point) limit)) + (while (cond + ((looking-at c-decl-hangon-key) + (c-forward-keyword-clause 1)) + ((looking-at c-type-decl-suffix-key) + (cond + ((save-match-data + (looking-at c-fun-name-substitute-key)) + (c-forward-c++-requires-clause)) + ((eq (char-after) ?\() + (if (c-forward-decl-arglist not-top decorated limit) + (progn (setq arglist t + got-init nil) + t) + (if (c-go-list-forward (point) limit) + t + (setq arglist t) ; For unbalanced (. + nil))) + (t (c-forward-keyword-clause 1)))) + ((and c-opt-cpp-prefix + (looking-at c-noise-macro-with-parens-name-re)) + (c-forward-noise-clause)))) + (<= (point) limit)) ;; Search syntactically to the end of the declarator (";", ;; ",", a closing paren, eob etc) or to the beginning of an @@ -9785,52 +9797,48 @@ point unchanged and return nil." ;; Note that square brackets are now not also treated as ;; initializers, since this broke when there were also ;; initializing brace lists. - (let (found) - (while - (and (< (point) limit) - (progn - ;; In the next loop, we keep searching forward whilst - ;; we find ":"s which aren't single colons inside C++ - ;; "for" statements. - (while - (and - (< (point) limit) - (prog1 - (setq found - (c-syntactic-re-search-forward - "[;:,]\\|\\s)\\|\\(=\\|\\s(\\)" - limit t t)) - (setq got-init - (and found (match-beginning 1)))) - (eq (char-before) ?:) - (if (looking-at c-:-op-cont-regexp) - (progn (goto-char (match-end 0)) t) - (not - (and (c-major-mode-is '(c++-mode java-mode)) - (save-excursion - (and - (c-go-up-list-backward) - (eq (char-after) ?\() - (progn (c-backward-syntactic-ws) - (c-simple-skip-symbol-backward)) - (looking-at c-paren-stmt-key)))))))) - found) - (cond ((eq (char-before) ?\[) - (setq brackets-after-id t) - (prog1 (c-go-up-list-forward) - (c-forward-syntactic-ws))) - ((and (not brackets-after-id) - (eq (char-before) ?\()) - (backward-char) - (if (c-forward-decl-arglist not-top decorated limit) - (setq arglist t - got-init nil) - (forward-char)) - nil)))) ; To end the loop. - (when (and found - (memq (char-before) '(?\; ?\: ?, ?= ?\( ?\[ ?{))) - (backward-char)) - (<= (point) limit))) + (or (eq (char-after) ?\() ; Not an arglist. + (let (found) + (while + (and (< (point) limit) + (progn + ;; In the next loop, we keep searching forward + ;; whilst we find ":"s which aren't single colons + ;; inside C++ "for" statements. + (while + (and + (< (point) limit) + (prog1 + (setq found + (c-syntactic-re-search-forward + "[;:,]\\|\\(=\\|\\s(\\)" + limit 'limit t)) + (setq got-init + (and found (match-beginning 1)))) + (eq (char-before) ?:) + (not + (and (c-major-mode-is '(c++-mode java-mode)) + (save-excursion + (and + (c-go-up-list-backward) + (eq (char-after) ?\() + (progn (c-backward-syntactic-ws) + (c-simple-skip-symbol-backward)) + (looking-at c-paren-stmt-key))))) + (if (looking-at c-:-op-cont-regexp) + (progn (goto-char (match-end 0)) t) + ;; Does this : introduce the class + ;; initialization list, or a bitfield? + (not arglist)))) ; Carry on for a bitfield + found) + (when (eq (char-before) ?\[) + (setq brackets-after-id t) + (prog1 (c-go-up-list-forward) + (c-forward-syntactic-ws))))) + (when (and found + (memq (char-before) '(?\; ?\: ?, ?= ?\( ?\[ ?{))) + (backward-char)) + (<= (point) limit)))) (list id-start id-end brackets-after-id got-init decorated arglist) (goto-char here) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 732b2b10549..2003b09ded2 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -2458,9 +2458,12 @@ with // and /*, not more generic line and block comments." (goto-char pos) (let ((lit-start (c-literal-start)) (lim (c-determine-limit 1000)) - enclosing-attribute pos1) + enclosing-attribute pos1 ml-delim) (if lit-start (goto-char lit-start)) + (when (and lit-start c-ml-string-opener-re + (setq ml-delim (c-ml-string-opener-around-point))) + (goto-char (car ml-delim))) (c-backward-syntactic-ws lim) (when (setq enclosing-attribute (c-enclosing-c++-attribute)) (goto-char (car enclosing-attribute)) ; Only happens in C++ Mode. @@ -2471,43 +2474,43 @@ with // and /*, not more generic line and block comments." (c-backward-syntactic-ws lim)) (when (setq pos1 (c-on-identifier)) (goto-char pos1) - (let* ((lim (save-excursion - (and (c-beginning-of-macro) - (progn (c-end-of-macro) (point))))) - (decl-res (c-forward-declarator lim))) - (if (or (cadr (cddr (cddr decl-res))) ; We scanned an arglist. - (and (eq (char-after) ?\() ; Move over a non arglist (...). - (prog1 (c-go-list-forward nil lim) - (c-forward-syntactic-ws lim)))) - (if (looking-at c-symbol-char-key) - ;; Deal with baz (foo((bar)) type var), where `pos' - ;; was inside foo, but foo((bar)) is not semantically - ;; valid. The result must be after var). - (and - (goto-char pos) - (setq pos1 (c-on-identifier)) - (goto-char pos1) - (progn - (c-backward-syntactic-ws lim) - (eq (char-before) ?\()) - (c-fl-decl-end (1- (point)))) - (c-backward-syntactic-ws lim) - (point)) - (if (progn (c-forward-syntactic-ws lim) - (not (eobp))) - (progn - (c-forward-over-token) - ;; Cope with having POS withing a syntactically invalid - ;; (...), by moving backward out of the parens and trying - ;; again. - (when (and (eq (char-before) ?\)) - (c-go-list-backward (point) lim)) - (c-fl-decl-end (point)))) - (let ((lit-start (c-literal-start))) - (when lit-start - (goto-char lit-start)) - (c-backward-syntactic-ws))) - (and (>= (point) pos) (point))))))) + (let* ((lim1 (save-excursion + (and (c-beginning-of-macro) + (progn (c-end-of-macro) (point))))) + (decl-res (c-forward-declarator))) + (if (or (cadr (cddr (cddr decl-res))) ; We scanned an arglist. + (and (eq (char-after) ?\() ; Move over a non arglist (...). + (prog1 (c-go-list-forward) + (c-forward-syntactic-ws)))) + (if (looking-at c-symbol-char-key) + ;; Deal with baz (foo((bar)) type var), where `pos' + ;; was inside foo, but foo((bar)) is not semantically + ;; valid. The result must be after var). + (and + (goto-char pos) + (setq pos1 (c-on-identifier)) + (goto-char pos1) + (progn + (c-backward-syntactic-ws lim1) + (eq (char-before) ?\()) + (c-fl-decl-end (1- (point)))) + (c-forward-over-token) + (point)) + (if (progn (c-forward-syntactic-ws) + (not (eobp))) + (progn + (c-forward-over-token) + ;; Cope with having POS withing a syntactically invalid + ;; (...), by moving backward out of the parens and trying + ;; again. + (when (and (eq (char-before) ?\)) + (c-go-list-backward (point) lim1)) + (c-fl-decl-end (point)))) + (let ((lit-start (c-literal-start))) + (when lit-start + (goto-char lit-start)) + (c-backward-syntactic-ws))) + (and (>= (point) pos) (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 -- 2.39.2