(goto-char here)
nil)))
-(defun c-forward-declarator (&optional limit accept-anon)
+(defun c-forward-decl-arglist (not-top id-in-parens &optional limit)
+ ;; Point is at an open parenthesis, assumed to be the arglist of a function
+ ;; declaration. Move over this arglist and following syntactic whitespace,
+ ;; and return non-nil. If the construct isn't such an arglist, leave point
+ ;; unmoved and return nil.
+ ;;
+ ;; Note that point is assumed to be at a place where an arglist is expected.
+ ;; Only for C++, where there are other possibilities, is any actual
+ ;; processing done. Otherwise, t is simply returned.
+ (let ((here (point)) got-type)
+ (if (or
+ (not (c-major-mode-is 'c++-mode))
+ (and
+ (or (not not-top)
+ id-in-parens ; Id is in parens, etc.
+ (save-excursion
+ (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))
+ (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
+ (goto-char here)
+ nil)))
+
+(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),
- ;; 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.
+ ;; 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)".
;; array/struct initialization) or "=" or terminating delimiter
;; (e.g. "," or ";" or "}").
(let ((here (point))
- id-start id-end brackets-after-id paren-depth decorated)
+ id-start id-end brackets-after-id paren-depth decorated
+ got-init arglist)
(or limit (setq limit (point-max)))
(if (and
(< (point) limit)
((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
+ (goto-char (match-end 0))
+ (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
;; 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))
+ (when (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))
(accept-anon
(setq id-start nil id-end nil)
t)
- (t (/= (point) here))))
+ (t nil)))
;; Skip out of the parens surrounding the identifier. If closing
;; parens are missing, this form returns nil.
(while
(and
(< (point) limit)
- (setq found
- (c-syntactic-re-search-forward
- "[;:,]\\|\\s)\\|\\(=\\|\\s(\\)"
- limit t t))
+ (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)
(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))
+ (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)))
- (list id-start id-end brackets-after-id (match-beginning 1) decorated)
+ (list id-start id-end brackets-after-id got-init decorated arglist)
(goto-char here)
nil)))
(defun c-do-declarators
- (cdd-limit cdd-list cdd-not-top cdd-comma-prop cdd-function)
+ (cdd-limit cdd-list cdd-not-top cdd-comma-prop cdd-function
+ &optional cdd-accept-anon)
"Assuming point is at the start of a comma separated list of declarators,
apply CDD-FUNCTION to each declarator (when CDD-LIST is non-nil) or just the
first declarator (when CDD-LIST is nil). When CDD-FUNCTION is nil, no
If CDD-NOT-TOP is non-nil, we are not at the top-level (\"top-level\" includes
being directly inside a class or namespace, etc.).
+If CDD-ACCEPT-ANON is non-nil, we also process declarators without names,
+e.g. \"int (*)(int)\" in a function prototype.
+
Return non-nil if we've reached the token after the last declarator (often a
semicolon, or a comma when CDD-LIST is nil); otherwise (when we hit CDD-LIMIT,
or fail otherwise) return nil, leaving point at the beginning of the putative
;; CDD-FUNCTION.
(let
((cdd-pos (point)) cdd-next-pos cdd-id-start cdd-id-end
- cdd-decl-res cdd-got-func cdd-got-type cdd-got-init
+ cdd-decl-res cdd-got-func cdd-got-init
c-last-identifier-range cdd-exhausted cdd-after-block)
;; The following `while' applies `cdd-function' to a single declarator id
;; each time round. It loops only when CDD-LIST is non-nil.
(while
(and (not cdd-exhausted)
- (setq cdd-decl-res (c-forward-declarator cdd-limit)))
+ (setq cdd-decl-res (c-forward-declarator
+ cdd-limit cdd-accept-anon cdd-not-top)))
+
(setq cdd-next-pos (point)
cdd-id-start (car cdd-decl-res)
cdd-id-end (cadr cdd-decl-res)
- cdd-got-func (and (eq (char-after) ?\()
- (or (not (c-major-mode-is 'c++-mode))
- (not cdd-not-top)
- (car (cddr (cddr cdd-decl-res))) ; Id is in
- ; parens, etc.
- (save-excursion
- (forward-char)
- (c-forward-syntactic-ws)
- (looking-at "[*&]")))
- (not (car (cddr cdd-decl-res)))
- (or (not (c-major-mode-is 'c++-mode))
- (save-excursion
- (let (c-last-identifier-range)
- (forward-char)
- (c-forward-syntactic-ws)
- (catch 'is-function
- (while
- (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))))
- (if (eq (char-after) ?\))
- (throw 'is-function t))
- (setq cdd-got-type (c-forward-type))
- (cond
- ((null cdd-got-type)
- (throw 'is-function nil))
- ((not (eq cdd-got-type 'maybe))
- (throw 'is-function t)))
- (c-forward-declarator nil t)
- (eq (char-after) ?,))
- (forward-char)
- (c-forward-syntactic-ws))
- t)))))
- cdd-got-init (and (cadr (cddr cdd-decl-res))
- (char-after)))
+ cdd-got-func (cadr (cddr (cddr cdd-decl-res)))
+ cdd-got-init (and (cadr (cddr cdd-decl-res)) (char-after)))
;; Jump past any initializer or function prototype to see if
;; there's a ',' to continue at.
- (cond (cdd-got-func
- ;; Skip a parenthesized initializer (C++) or a function
- ;; prototype.
- (if (c-go-list-forward (point) cdd-limit) ; over the parameter list.
- (c-forward-syntactic-ws cdd-limit)
- (setq cdd-exhausted t))) ; unbalanced parens
-
- (cdd-got-init ; "=" sign OR opening "(", "[", or "("
+ (cond (cdd-got-init ; "=" sign OR opening "(", "[", or "("
;; Skip an initializer expression in braces, whether or not (in
;; C++ Mode) preceded by an "=". Be careful that the brace list
;; isn't a code block or a struct (etc.) block.
(t (c-forward-syntactic-ws cdd-limit)))
(if cdd-function
- (funcall cdd-function cdd-id-start cdd-id-end cdd-next-pos
- cdd-not-top cdd-got-func cdd-got-init))
+ (save-excursion
+ (funcall cdd-function cdd-id-start cdd-id-end cdd-next-pos
+ cdd-not-top cdd-got-func cdd-got-init)))
;; If a ',' is found we set cdd-pos to the next declarator and iterate.
(if (and cdd-list (< (point) cdd-limit) (looking-at ","))
nil)
(defun c-font-lock-declarators (limit list types not-top
- &optional template-class)
+ &optional template-class accept-anon)
;; Assuming the point is at the start of a declarator in a declaration,
;; fontify the identifier it declares. (If TYPES is t, it does this via the
;; macro `c-fontify-types-and-refs'.)
;; a default (introduced by "="), it will be fontified as a type.
;; E.g. "<class X = Y>".
;;
+ ;; ACCEPT-ANON is non-nil when we accept anonymous declarators.
+ ;;
;; Nil is always returned. The function leaves point at the delimiter after
;; the last declarator it processes.
;;
limit list not-top
(cond ((eq types t) 'c-decl-type-start)
((null types) 'c-decl-id-start))
- (lambda (id-start _id-end end-pos _not-top is-function init-char)
+ (lambda (id-start id-end end-pos _not-top is-function init-char)
(if (eq types t)
- ;; Register and fontify the identifier as a type.
- (let ((c-promote-possible-types t))
- (goto-char id-start)
- (c-forward-type))
- ;; The following doesn't work properly (yet, 2018-09-22).
- ;; (c-put-font-lock-face id-start id-end
- ;; (if is-function
- ;; 'font-lock-function-name-face
- ;; 'font-lock-variable-name-face))
- (when (and c-last-identifier-range
- (not (get-text-property (car c-last-identifier-range)
- 'face)))
- ;; We use `c-last-identifier-range' rather than `id-start' and
- ;; `id-end', since the latter two can be erroneous. E.g. in
- ;; "~Foo", `id-start' is at the tilde. This is a bug in
- ;; `c-forward-declarator'.
- (c-put-font-lock-face (car c-last-identifier-range)
- (cdr c-last-identifier-range)
- (cond
- ((not (memq types '(nil t))) types)
- (is-function 'font-lock-function-name-face)
- (t 'font-lock-variable-name-face)))))
+ (when id-start
+ ;; Register and fontify the identifier as a type.
+ (let ((c-promote-possible-types t))
+ (goto-char id-start)
+ (c-forward-type)))
+ (when id-start
+ (goto-char id-start)
+ (when c-opt-identifier-prefix-key
+ (unless (and (looking-at c-opt-identifier-prefix-key) ; For operator~
+ (eq (match-end 1) id-end))
+ (while (and (< (point) id-end)
+ (re-search-forward c-opt-identifier-prefix-key id-end t))
+ (c-forward-syntactic-ws limit))))
+ (when (not (get-text-property (point) 'face))
+ (c-put-font-lock-face (point) id-end
+ (cond
+ ((not (memq types '(nil t))) types)
+ (is-function 'font-lock-function-name-face)
+ (t 'font-lock-variable-name-face))))))
(and template-class
(eq init-char ?=) ; C++ "<class X = Y>"?
(progn
(goto-char end-pos)
(c-forward-token-2 1 nil limit) ; Over "="
(let ((c-promote-possible-types t))
- (c-forward-type t))))))
+ (c-forward-type t)))))
+ accept-anon) ; Last argument to c-do-declarators.
nil))
(defun c-get-fontification-context (match-pos not-front-decl &optional toplev)
'c-decl-type-start
'c-decl-id-start)))))
(c-font-lock-declarators
- (min limit (point-max)) decl-list
+ (min limit (point-max))
+ decl-list
(not (null (cadr decl-or-cast)))
- (not toplev) template-class))
+ (not toplev)
+ template-class
+ (memq context '(decl <>))))
;; A declaration has been successfully identified, so do all the
;; fontification of types and refs that've been recorded.
(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))))))
- (and (c-forward-declarator lim)
- (if (and (eq (char-after) ?\()
- (c-go-list-forward nil lim))
+ (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
- (progn (c-forward-syntactic-ws lim)
- (not (eobp)))
+ (goto-char pos)
+ (setq pos1 (c-on-identifier))
+ (goto-char pos1)
(progn
- (if (looking-at c-symbol-char-key)
- ;; Deal with baz (foo((bar)) type var), where
- ;; 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)))
- (c-forward-over-token)
- (let ((lit-start (c-literal-start)))
- (when lit-start
- (goto-char lit-start))
- (c-backward-syntactic-ws)))
- (and (>= (point) pos) (point))))))))
+ (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)))))))
(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