C++ Mode: handle comma separated brace initializers.

This includes both indentation and fontification.

* lisp/progmodes/cc-engine.el (c-do-declarators): Handle brace initializers
without = correctly.
(c-looking-at-or-maybe-in-bracelist): Use c-do-declarators with a simple
inline function to check that after-type-id-pos points to the start of a
declarator.

* lisp/progmodes/cc-langs.el (c-recognize-bare-brace-inits): New lang
const/variable.
This commit is contained in:
Alan Mackenzie 2020-09-04 19:10:17 +00:00
parent 2b95300cf8
commit 7938713105
2 changed files with 49 additions and 18 deletions

View file

@ -9091,7 +9091,7 @@ This function might do hidden buffer changes."
(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
c-last-identifier-range cdd-exhausted)
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.
@ -9144,23 +9144,25 @@ This function might do hidden buffer changes."
(c-forward-syntactic-ws cdd-limit)
(setq cdd-exhausted t))) ; unbalanced parens
(cdd-got-init ; "=" sign OR opening "(", "[", or "{"
;; Skip an initializer expression. If we're at a '='
;; then accept a brace list directly after it to cope
;; with array initializers. Otherwise stop at braces
;; to avoid going past full function and class blocks.
(if (and (if (and (eq cdd-got-init ?=)
(= (c-forward-token-2 1 nil cdd-limit) 0)
(looking-at "{"))
(c-go-list-forward (point) cdd-limit)
t)
;; FIXME: Should look for c-decl-end markers here;
;; we might go far into the following declarations
;; in e.g. ObjC mode (see e.g. methods-4.m).
(c-syntactic-re-search-forward "[;,{]" cdd-limit 'move t))
(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.
(cond
((and (eq cdd-got-init ?=)
(zerop (c-forward-token-2 1 nil cdd-limit))
(eq (char-after) ?{)
(c-go-list-forward (point) cdd-limit)))
((and (eq cdd-got-init ?{)
c-recognize-bare-brace-inits
(setq cdd-after-block
(save-excursion
(c-go-list-forward (point) cdd-limit)))
(not (c-looking-at-statement-block)))
(goto-char cdd-after-block)))
(if (c-syntactic-re-search-forward "[;,{]" cdd-limit 'move t)
(backward-char)
(setq cdd-exhausted t)
))
(setq cdd-exhausted t)))
(t (c-forward-syntactic-ws cdd-limit)))
@ -11729,7 +11731,22 @@ comment at the start of cc-engine.el for more info."
(save-excursion (c-backward-syntactic-ws) (point))
nil nil))
(and (consp res)
(eq (car res) after-type-id-pos))))))
(cond
((eq (car res) after-type-id-pos))
((> (car res) after-type-id-pos) nil)
(t
(catch 'find-decl
(save-excursion
(goto-char (car res))
(c-do-declarators
(point-max) t nil nil
(lambda (id-start id-end tok not-top func init)
(cond
((> id-start after-type-id-pos)
(throw 'find-decl nil))
((eq id-start after-type-id-pos)
(throw 'find-decl t)))))
nil)))))))))
(cons bufpos (or in-paren inexpr-brace-list)))
((or (eq (char-after) ?\;)
;; Brace lists can't contain a semicolon, so we're done.

View file

@ -3684,6 +3684,20 @@ Foo bar = gnu;"
c++ t)
(c-lang-defvar c-recognize-paren-inits (c-lang-const c-recognize-paren-inits))
(c-lang-defconst c-recognize-bare-brace-inits
"Non-nil means that brace initializers without \"=\" exist,
i.e. constructs like
int foo[] {1, 2, 3};
in addition to the more classic
int foo[] = {1, 2, 3};"
t nil
c++ t)
(c-lang-defvar c-recognize-bare-brace-inits
(c-lang-const c-recognize-bare-brace-inits))
(c-lang-defconst c-recognize-paren-inexpr-blocks
"Non-nil to recognize gcc style in-expression blocks,
i.e. compound statements surrounded by parentheses inside expressions."