summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2021-03-02 20:31:36 +0000
committerAlan Mackenzie <acm@muc.de>2021-03-02 20:31:36 +0000
commit8dd588b1fb51bb9178bf34a6be9f35de84e95045 (patch)
treee42564b6f27d055c16d70bd3b33595ba7b8585ed
parentaa14398aa14362095f1a42845015b9bab141c7d6 (diff)
downloademacs-8dd588b1fb51bb9178bf34a6be9f35de84e95045.tar.gz
CC Mode: Fix analysis of brace lists, particularly in C++ Mode
Fix some alignment functionality in cc-align.el. * lisp/progmodes/cc-align.el (c-lineup-arglist-intro-after-paren): Align the next line under the previous entry rather than one to the right of the paren. (c-lineup-2nd-brace-entry-in-arglist): Take the anchor point from the brace-list-entry element, not the brace-list-intro one. * lisp/progmodes/cc-engine.el (c-looking-at-decl-block): Use c-looking-at-statement-block to test whether "struct A {" begins a brace list or a struct declaration. (c-looking-at-or-maybe-in-bracelist): Several detailed amendments, correctly to recognize brace lists. (c-looking-at-statement-block): No longer search for commas, as they are not reliable indicators of a brace list. Search now for a restricted set of keywords, since some can appear in brace lists in C++ mode. * lisp/progmodes/cc-langs.el (c-stmt-block-only-keywords) (c-stmt-block-only-keywords-regexp): New lang consts/vars. (c-pre-id-bracelist-kwds): New lang const. (c-pre-id-bracelist-key): Derive now from the above. (c-pre-brace-non-bracelist-key): New lang const/var.
-rw-r--r--lisp/progmodes/cc-align.el7
-rw-r--r--lisp/progmodes/cc-engine.el125
-rw-r--r--lisp/progmodes/cc-langs.el50
3 files changed, 122 insertions, 60 deletions
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index d14ef1744af..51d51deef71 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -274,8 +274,10 @@ statement-block-intro, statement-case-intro, arglist-intro."
(save-excursion
(beginning-of-line)
(backward-up-list 1)
+ (forward-char)
(skip-chars-forward " \t" (c-point 'eol))
- (vector (1+ (current-column)))))
+ (if (eolp) (skip-chars-backward " \t"))
+ (vector (current-column))))
(defun c-lineup-arglist-close-under-paren (langelem)
"Line up a line under the enclosing open paren.
@@ -1145,7 +1147,8 @@ Works with brace-list-intro."
; the line.
(save-excursion ; "{" earlier on the line
(goto-char (c-langelem-pos
- (assq 'brace-list-intro c-syntactic-context)))
+ (assq 'brace-list-entry
+ c-syntactic-context)))
(and
(eq (c-backward-token-2
1 nil
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 4cf7af843b7..079985a6bc5 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -11410,7 +11410,9 @@ comment at the start of cc-engine.el for more info."
;; 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))))))
+ (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
@@ -11817,15 +11819,17 @@ comment at the start of cc-engine.el for more info."
;; POINT, or nil if there is no such position, or we do not know it. LIM is
;; a backward search limit.
;;
- ;; The determination of whether the brace starts a brace list is solely by
- ;; the context of the brace, not by its contents.
+ ;; The determination of whether the brace starts a brace list is mainly by
+ ;; the context of the brace, not by its contents. In exceptional
+ ;; circumstances (e.g. "struct A {" in C++ Mode), the contents are examined,
+ ;; too.
;;
;; Here, "brace list" does not include the body of an enum.
(save-excursion
(let ((start (point))
(braceassignp 'dontknow)
inexpr-brace-list bufpos macro-start res pos after-type-id-pos
- in-paren parens-before-brace
+ pos2 in-paren parens-before-brace
paren-state paren-pos)
(setq res (c-backward-token-2 1 t lim))
@@ -11841,12 +11845,16 @@ comment at the start of cc-engine.el for more info."
(goto-char paren-pos)
(setq braceassignp 'c++-noassign
in-paren 'in-paren))
- ((looking-at c-pre-id-bracelist-key)
+ ((looking-at c-pre-brace-non-bracelist-key)
(setq braceassignp nil))
((looking-at c-return-key))
((and (looking-at c-symbol-start)
(not (looking-at c-keywords-regexp)))
- (setq after-type-id-pos (point)))
+ (if (save-excursion
+ (and (zerop (c-backward-token-2 1 t lim))
+ (looking-at c-pre-id-bracelist-key)))
+ (setq braceassignp 'c++-noassign)
+ (setq after-type-id-pos (point))))
((eq (char-after) ?\()
(setq parens-before-brace t)
nil)
@@ -11860,8 +11868,13 @@ comment at the start of cc-engine.el for more info."
(eq (char-after paren-pos) ?\()
(setq in-paren 'in-paren)
(goto-char paren-pos)))
- ((looking-at c-pre-id-bracelist-key))
+ ((looking-at c-pre-brace-non-bracelist-key))
((looking-at c-return-key))
+ ((and (looking-at c-symbol-start)
+ (not (looking-at c-keywords-regexp))
+ (save-excursion
+ (and (zerop (c-backward-token-2 1 t lim))
+ (looking-at c-pre-id-bracelist-key)))))
(t (setq after-type-id-pos (point))
nil))))
(setq braceassignp 'c++-noassign))
@@ -11946,8 +11959,12 @@ comment at the start of cc-engine.el for more info."
(cond
(braceassignp
;; We've hit the beginning of the aggregate list.
- (c-beginning-of-statement-1 containing-sexp)
- (cons (point) (or in-paren inexpr-brace-list)))
+ (setq pos2 (point))
+ (cons
+ (if (eq (c-beginning-of-statement-1 containing-sexp) 'same)
+ (point)
+ pos2)
+ (or in-paren inexpr-brace-list)))
((and after-type-id-pos
(save-excursion
(when (eq (char-after) ?\;)
@@ -11959,34 +11976,36 @@ comment at the start of cc-engine.el for more info."
(c-get-char-property (point) 'syntax-table))
(c-go-list-forward nil after-type-id-pos)
(c-forward-syntactic-ws)))
- (and
- (or (not (looking-at c-class-key))
- (save-excursion
- (goto-char (match-end 1))
- (c-forward-syntactic-ws)
- (not (eq (point) after-type-id-pos))))
- (progn
- (setq res
- (c-forward-decl-or-cast-1
- (save-excursion (c-backward-syntactic-ws) (point))
- nil nil))
- (and (consp res)
- (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)))))))))
+ (if (and (not (eq (point) after-type-id-pos))
+ (or (not (looking-at c-class-key))
+ (save-excursion
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws)
+ (not (eq (point) after-type-id-pos)))))
+ (progn
+ (setq res
+ (c-forward-decl-or-cast-1 (c-point 'bosws)
+ nil nil))
+ (and (consp res)
+ (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))))))
+ (save-excursion
+ (goto-char start)
+ (not (c-looking-at-statement-block))))))
(cons bufpos (or in-paren inexpr-brace-list)))
((or (eq (char-after) ?\;)
;; Brace lists can't contain a semicolon, so we're done.
@@ -12136,33 +12155,31 @@ comment at the start of cc-engine.el for more info."
(defun c-looking-at-statement-block ()
;; Point is at an opening brace. If this is a statement block (i.e. the
;; elements in the block are terminated by semicolons, or the block is
- ;; empty, or the block contains a keyword) return non-nil. Otherwise,
- ;; return nil.
+ ;; empty, or the block contains a characteristic keyword, or there is a
+ ;; nested statement block) return non-nil. Otherwise, return nil.
(let ((here (point)))
(prog1
(if (c-go-list-forward)
(let ((there (point)))
(backward-char)
- (c-syntactic-skip-backward "^;," here t)
+ (c-syntactic-skip-backward "^;" here t)
(cond
- ((eq (char-before) ?\;) t)
- ((eq (char-before) ?,) nil)
- (t ; We're at (1+ here).
- (cond
- ((progn (c-forward-syntactic-ws)
- (eq (point) (1- there))))
- ((c-syntactic-re-search-forward c-keywords-regexp there t))
- ((c-syntactic-re-search-forward "{" there t t)
- (backward-char)
- (c-looking-at-statement-block))
- (t nil)))))
+ ((eq (char-before) ?\;))
+ ((progn (c-forward-syntactic-ws)
+ (eq (point) (1- there))))
+ ((c-syntactic-re-search-forward
+ c-stmt-block-only-keywords-regexp there t))
+ ((c-syntactic-re-search-forward "{" there t t)
+ (backward-char)
+ (c-looking-at-statement-block))
+ (t nil)))
(forward-char)
(cond
- ((c-syntactic-re-search-forward "[;,]" nil t t)
- (eq (char-before) ?\;))
+ ((c-syntactic-re-search-forward ";" nil t t))
((progn (c-forward-syntactic-ws)
(eobp)))
- ((c-syntactic-re-search-forward c-keywords-regexp nil t t))
+ ((c-syntactic-re-search-forward c-stmt-block-only-keywords-regexp
+ nil t t))
((c-syntactic-re-search-forward "{" nil t t)
(backward-char)
(c-looking-at-statement-block))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 07479389c62..fa4e73087ef 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3098,6 +3098,36 @@ Note that Java specific rules are currently applied to tell this from
t (c-make-keywords-re t (c-lang-const c-keywords)))
(c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp))
+(c-lang-defconst c-stmt-block-only-keywords
+ "All keywords which unambiguously signify a statement block (as opposed to
+ a brace list) when occurring inside braces."
+ t (c--set-difference
+ (c-lang-const c-keywords)
+ (append (c-lang-const c-primary-expr-kwds)
+ (c-lang-const c-constant-kwds)
+ `(,@(when (c-major-mode-is 'c++-mode)
+ '("typeid" "dynamic_cast" "static_cast" "const_cast"
+ "reinterpret_cast" "alignof")))
+ (c-lang-const c-type-modifier-prefix-kwds)
+ (c-lang-const c-overloadable-operators)
+ (c-lang-const c-template-typename-kwds)
+ `(,@(when (c-major-mode-is 'c++-mode)
+ '("reflexpr")))
+ `(,@(when (c-major-mode-is '(c-mode c++-mode))
+ '("sizeof")))
+ (c-lang-const c-pre-lambda-tokens)
+ (c-lang-const c-block-decls-with-vars)
+ (c-lang-const c-primitive-type-kwds))
+ :test 'string-equal))
+
+(c-lang-defconst c-stmt-block-only-keywords-regexp
+ ;; A regexp matching a keyword in `c-stmt-block-only-keywords'. Such a
+ ;; match can start and end only at token boundaries.
+ t (concat "\\(^\\|\\=\\|[^" (c-lang-const c-symbol-chars) "]\\)"
+ (c-make-keywords-re t (c-lang-const c-stmt-block-only-keywords))))
+(c-lang-defvar c-stmt-block-only-keywords-regexp
+ (c-lang-const c-stmt-block-only-keywords-regexp))
+
(c-lang-defconst c-keyword-member-alist
;; An alist with all the keywords in the cars. The cdr for each
;; keyword is a list of the symbols for the `*-kwds' lists that
@@ -3650,13 +3680,25 @@ list."
c t)
(c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p))
+(c-lang-defconst c-pre-id-bracelist-kwds
+ "Keywords which, preceding an identifier and brace, signify a bracelist.
+This is only used in c++-mode."
+ t nil
+ c++ '("new" "throw"))
+
(c-lang-defconst c-pre-id-bracelist-key
- "A regexp matching tokens which, preceding an identifier, signify a bracelist.
-"
- t regexp-unmatchable
- c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)")
+ ;; A regexp matching keywords which, preceding an identifier and brace,
+ ;; signify a bracelist. Only used in c++-mode.
+ t (c-make-keywords-re t (c-lang-const c-pre-id-bracelist-kwds)))
(c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key))
+(c-lang-defconst c-pre-brace-non-bracelist-key
+ "A regexp matching tokens which, preceding a brace, make it a non-bracelist."
+ t regexp-unmatchable
+ c++ "&&?\\(\\S.\\|$\\)")
+(c-lang-defvar c-pre-brace-non-bracelist-key
+ (c-lang-const c-pre-brace-non-bracelist-key))
+
(c-lang-defconst c-recognize-typeless-decls
"Non-nil means function declarations without return type should be
recognized. That can introduce an ambiguity with parenthesized macro