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)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
;; Handling of large scale constructs like statements and declarations.
(defun c-forward-declarator (&optional limit accept-anon)
;; 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 ,).
;;
;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT DECORATED),
;; where ID-START and ID-END are the bounds of the declarator's identifier,
;; and BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id.
;; 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)
(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))
((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 third 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))
(c-forward-name)
(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))
(save-excursion
(c-backward-syntactic-ws)
(setq id-end (point))))
(accept-anon
(setq id-start nil id-end nil)
t)
(t (/= (point) here))))
;; 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))))
(<= (point) limit)
;; Skip over any trailing bit, such as "__attribute__".
(progn
(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))))
(<= (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.
(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)
(setq found
(c-syntactic-re-search-forward
"[;:,]\\|\\s)\\|\\(=\\|\\s(\\)"
limit t t))
(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)
(eq (char-before) ?\[)
(c-go-up-list-forward))
(setq brackets-after-id t))
(when found (backward-char))
(<= (point) limit)))
(list id-start id-end brackets-after-id (match-beginning 1) decorated)
(goto-char here)
nil)))