Function: c-looking-at-decl-block
c-looking-at-decl-block is a byte-compiled function defined in
cc-engine.el.gz.
Signature
(c-looking-at-decl-block GOTO-START &optional LIMIT)
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/cc-engine.el.gz
(defun c-looking-at-decl-block (goto-start &optional limit)
;; Assuming the point is at an open brace, check if it starts a
;; block that contains another declaration level, i.e. that isn't a
;; statement block or a brace list, and if so return non-nil.
;;
;; If the check is successful, the return value is the start of the
;; keyword that tells what kind of construct it is, i.e. typically
;; what `c-decl-block-key' matched. Also, if GOTO-START is set then point
;; will be left at the start of the construct. This is often at the
;; return value, but if there is a template preceding it, point will be
;; left at its start. If there are Java annotations preceding it, point
;; will be left at the last of these.
;;
;; The point is clobbered if the check is unsuccessful.
;;
;; CONTAINING-SEXP is the position of the open of the surrounding
;; paren, or nil if none.
;;
;; The optional LIMIT limits the backward search for the start of
;; the construct. It's assumed to be at a syntactically relevant
;; position.
;;
;; If any template arglists are found in the searched region before
;; the open brace, they get marked with paren syntax.
;;
;; This function might do hidden buffer changes.
(let ((open-brace (point)) kwd-start first-specifier-pos)
(c-syntactic-skip-backward c-block-prefix-charset limit t)
(while
(or
;; Could be after a template arglist....
(and c-recognize-<>-arglists
(eq (char-before) ?>)
(let ((c-parse-and-markup-<>-arglists t))
(c-backward-<>-arglist nil limit)))
;; .... or after a noise clause with parens.
(and c-opt-cpp-prefix
(let ((after-paren (point)))
(if (eq (char-before) ?\))
(and
(c-go-list-backward)
(eq (char-after) ?\()
(progn (c-backward-syntactic-ws)
(c-simple-skip-symbol-backward))
(or (looking-at c-paren-nontype-key) ; e.g. __attribute__
(looking-at c-noise-macro-with-parens-name-re)))
(goto-char after-paren)
nil))))
(c-syntactic-skip-backward c-block-prefix-charset limit t))
;; Note: Can't get bogus hits inside template arglists below since they
;; have gotten paren syntax above.
(when (and
;; If `goto-start' is set we begin by searching for the
;; first possible position of a leading specifier list.
;; The `c-decl-block-key' search continues from there since
;; we know it can't match earlier.
(if goto-start
(progn
(while
(and
(c-syntactic-re-search-forward c-symbol-start
open-brace t t)
(goto-char (match-beginning 0))
(if (or (looking-at c-noise-macro-name-re)
(looking-at c-noise-macro-with-parens-name-re))
(c-forward-noise-clause)
(setq first-specifier-pos (match-beginning 0))
nil)))
first-specifier-pos)
t)
(cond
((c-syntactic-re-search-forward c-decl-block-key open-brace t t t)
(goto-char (setq kwd-start (match-beginning 0)))
(and
;; Exclude cases where we matched what would ordinarily
;; be an enum declaration keyword, except where it's not
;; legal because it's part of a "compound keyword" like
;; "enum class". Of course, if c-after-enum-list-key
;; is nil, we can skip the test.
(or (equal c-after-enum-list-key regexp-unmatchable)
(save-match-data
(save-excursion
(not
(and
(looking-at c-after-enum-list-key)
(= (c-backward-token-2 1 t) 0)
(looking-at c-enum-list-key))))))
(or
;; Found a keyword that can't be a type?
(match-beginning 1)
;; Can be a type too, in which case it's the return type of a
;; function (under the assumption that no declaration level
;; block construct starts with a type).
(not (c-forward-type))
;; Jumped over a type, but it could be a declaration keyword
;; followed by the declared identifier that we've jumped over
;; instead (e.g. in "class Foo {"). If it indeed is a type
;; then we should be at the declarator now, so check for a
;; valid declarator start.
;;
;; Note: This doesn't cope with the case when a declared
;; identifier is followed by e.g. '(' in a language where '('
;; also might be part of a declarator expression. Currently
;; there's no such language.
(not (or (looking-at c-symbol-start)
(looking-at c-type-decl-prefix-key)
(and (eq (char-after) ?{)
(not (c-looking-at-statement-block))))))))
;; In Pike a list of modifiers may be followed by a brace
;; to make them apply to many identifiers. Note that the
;; match data will be empty on return in this case.
((and (c-major-mode-is 'pike-mode)
(progn
(goto-char open-brace)
(= (c-backward-token-2) 0))
(looking-at c-specifier-key)
;; Use this variant to avoid yet another special regexp.
(c-keyword-member (c-keyword-sym (match-string 1))
'c-modifier-kwds))
(setq kwd-start (point))
t)))
;; Got a match.
(if goto-start
;; Back up over any preceding specifiers and their clauses
;; by going forward from `first-specifier-pos', which is the
;; earliest possible position where the specifier list can
;; start.
(progn
(goto-char first-specifier-pos)
(while (< (point) kwd-start)
(cond
((or (looking-at c-noise-macro-name-re)
(looking-at c-noise-macro-with-parens-name-re))
(c-forward-noise-clause))
((looking-at c-symbol-key)
;; Accept any plain symbol token on the ground that
;; it's a specifier masked through a macro (just
;; like `c-forward-decl-or-cast-1' skips forward over
;; such tokens).
;;
;; Could be more restrictive wrt invalid keywords,
;; but that'd only occur in invalid code so there's
;; no use spending effort on it.
(let ((end (match-end 0))
(kwd-sym (c-keyword-sym (match-string 0)))
(annotation (and c-annotation-re
(looking-at c-annotation-re))))
(unless
(and kwd-sym
;; Moving over a protection kwd and the following
;; ":" (in C++ Mode) to the next token could take
;; us all the way up to `kwd-start', leaving us
;; no chance to update `first-specifier-pos'.
(not (c-keyword-member kwd-sym 'c-protection-kwds))
(c-forward-keyword-clause 0))
(goto-char end)
(c-forward-syntactic-ws)
(when annotation
(setq first-specifier-pos (match-beginning 0))
(when (and (eq (char-after) ?\()
(c-go-list-forward (point) kwd-start))
(c-forward-syntactic-ws))))))
((c-syntactic-re-search-forward c-symbol-start
kwd-start 'move t)
;; Can't parse a declaration preamble and is still
;; before `kwd-start'. That means `first-specifier-pos'
;; was in some earlier construct. Search again.
(goto-char (setq first-specifier-pos (match-beginning 0))))
(t
;; Got no preamble before the block declaration keyword.
(setq first-specifier-pos kwd-start))))
(goto-char first-specifier-pos))
(goto-char kwd-start))
kwd-start)))