Function: c-forward-declarator
c-forward-declarator is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-forward-declarator &optional LIMIT ACCEPT-ANON NOT-TOP)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-forward-declarator (&optional limit accept-anon not-top)
;; Assuming point is at the start of a declarator, move forward over it,
;; leaving point at the next token after it (e.g. a ) or a ; or a ,), or at
;; end of buffer if there is no such token.
;;
;; 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 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
;; declaration. In such a case ID-START and ID-END in the return value are
;; both set to nil. A "null" "anonymous declarator" gives a non-nil result.
;;
;; If no declarator is found, leave point unmoved and return nil. LIMIT is
;; an optional limit for forward searching.
;;
;; Note that the global variable `c-last-identifier-range' is written to, so
;; the caller should bind it if necessary.
;; Inside the following "condition form", we move forward over the
;; declarator's identifier up as far as any opening bracket (for array
;; size) or paren (for parameters of function-type) or brace (for
;; array/struct initialization) or "=" or terminating delimiter
;; (e.g. "," or ";" or "}").
(let ((here (point))
id-start id-end brackets-after-id paren-depth decorated
got-init arglist double-double-quote pos)
(or limit (setq limit (point-max)))
(if (and
(< (point) limit)
;; The following form moves forward over the declarator's
;; identifier (and what precedes it), returning t. If there
;; wasn't one, it returns nil.
(let (got-identifier)
(setq paren-depth 0)
;; Skip over type decl prefix operators, one for each iteration
;; of the while. These are, e.g. "*" in "int *foo" or "(" and
;; "*" in "int (*foo) (void)" (Note similar code in
;; `c-forward-decl-or-cast-1'.)
(while
(cond
((looking-at c-decl-hangon-key)
(c-forward-keyword-clause 1))
((and c-opt-cpp-prefix
(looking-at c-noise-macro-with-parens-name-re))
(c-forward-noise-clause))
;; Special handling for operator<op>.
((and c-opt-op-identifier-prefix
(looking-at c-opt-op-identifier-prefix))
(goto-char (match-end 1))
(c-forward-syntactic-ws limit)
(setq id-start (point))
(if (looking-at c-overloadable-operators-regexp)
(progn
(when (and (c-major-mode-is 'c++-mode)
(eq (char-after) ?\")
(eq (char-after (1+ (point))) ?\"))
(setq double-double-quote t))
(goto-char (match-end 0))
(setq pos (point))
(c-forward-syntactic-ws limit)
(setq got-identifier t)
nil)
t))
((and (looking-at c-type-decl-prefix-key)
(if (and (c-major-mode-is 'c++-mode)
(match-beginning 4)) ; Was 3 - 2021-01-01
;; If the fourth submatch matches in C++ then
;; we're looking at an identifier that's a
;; prefix only if it specifies a member pointer.
(progn
(setq id-start (point))
(when (c-forward-name t)
(setq pos (point))
(c-forward-syntactic-ws limit)
(if (save-match-data
(looking-at "\\(::\\)"))
;; We only check for a trailing "::" and
;; let the "*" that should follow be
;; matched in the next round.
t
;; It turned out to be the real identifier,
;; so flag that and stop.
(setq got-identifier t)
nil)))
t))
(if (save-match-data
(looking-at c-type-decl-operator-prefix-key))
(setq decorated t))
(if (eq (char-after) ?\()
(progn
(setq paren-depth (1+ paren-depth))
(forward-char))
(goto-char (or (match-end 1)
(match-end 2))))
(c-forward-syntactic-ws)
t)))
;; If we haven't passed the identifier already, do it now.
(unless got-identifier
(setq id-start (point)))
(cond
((or got-identifier
(c-forward-name t))
(setq id-end
(or pos
(point)))
(c-forward-syntactic-ws limit)
t)
(accept-anon
(setq id-start nil id-end nil)
t)
(t nil)))
(progn
(c-forward-syntactic-ws limit)
(when (and double-double-quote ; C++'s operator"" _tag
(c-on-identifier))
(c-forward-token-2 1 nil limit))
t)
;; Skip out of the parens surrounding the identifier. If closing
;; parens are missing, this form returns nil.
(or (= paren-depth 0)
(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)
(cond
((save-match-data
(and
(looking-at c-fun-name-substitute-key)
(not (eq (char-after (match-end 0)) ?_))))
(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
;; initializer or function prototype ("=" or "\\s(").
;; Note that square brackets are now not also treated as
;; initializers, since this broke when there were also
;; initializing brace lists.
(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
;; Consider making the next regexp a
;; c-lang-defvar (2023-07-04).
(if (c-major-mode-is 'objc-mode)
"\\(?:@end\\)\\|[;:,]\\|\\(=\\|[[(]\\)"
"[;:,]\\|\\(=\\|\\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)
nil)))