aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2021-03-02 20:31:36 +0000
committerAlan Mackenzie2021-03-02 20:31:36 +0000
commit8dd588b1fb51bb9178bf34a6be9f35de84e95045 (patch)
treee42564b6f27d055c16d70bd3b33595ba7b8585ed
parentaa14398aa14362095f1a42845015b9bab141c7d6 (diff)
downloademacs-8dd588b1fb51bb9178bf34a6be9f35de84e95045.tar.gz
emacs-8dd588b1fb51bb9178bf34a6be9f35de84e95045.zip
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."
274 (save-excursion 274 (save-excursion
275 (beginning-of-line) 275 (beginning-of-line)
276 (backward-up-list 1) 276 (backward-up-list 1)
277 (forward-char)
277 (skip-chars-forward " \t" (c-point 'eol)) 278 (skip-chars-forward " \t" (c-point 'eol))
278 (vector (1+ (current-column))))) 279 (if (eolp) (skip-chars-backward " \t"))
280 (vector (current-column))))
279 281
280(defun c-lineup-arglist-close-under-paren (langelem) 282(defun c-lineup-arglist-close-under-paren (langelem)
281 "Line up a line under the enclosing open paren. 283 "Line up a line under the enclosing open paren.
@@ -1145,7 +1147,8 @@ Works with brace-list-intro."
1145 ; the line. 1147 ; the line.
1146 (save-excursion ; "{" earlier on the line 1148 (save-excursion ; "{" earlier on the line
1147 (goto-char (c-langelem-pos 1149 (goto-char (c-langelem-pos
1148 (assq 'brace-list-intro c-syntactic-context))) 1150 (assq 'brace-list-entry
1151 c-syntactic-context)))
1149 (and 1152 (and
1150 (eq (c-backward-token-2 1153 (eq (c-backward-token-2
1151 1 nil 1154 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."
11410 ;; also might be part of a declarator expression. Currently 11410 ;; also might be part of a declarator expression. Currently
11411 ;; there's no such language. 11411 ;; there's no such language.
11412 (not (or (looking-at c-symbol-start) 11412 (not (or (looking-at c-symbol-start)
11413 (looking-at c-type-decl-prefix-key)))))) 11413 (looking-at c-type-decl-prefix-key)
11414 (and (eq (char-after) ?{)
11415 (not (c-looking-at-statement-block))))))))
11414 11416
11415 ;; In Pike a list of modifiers may be followed by a brace 11417 ;; In Pike a list of modifiers may be followed by a brace
11416 ;; to make them apply to many identifiers. Note that the 11418 ;; 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."
11817 ;; POINT, or nil if there is no such position, or we do not know it. LIM is 11819 ;; POINT, or nil if there is no such position, or we do not know it. LIM is
11818 ;; a backward search limit. 11820 ;; a backward search limit.
11819 ;; 11821 ;;
11820 ;; The determination of whether the brace starts a brace list is solely by 11822 ;; The determination of whether the brace starts a brace list is mainly by
11821 ;; the context of the brace, not by its contents. 11823 ;; the context of the brace, not by its contents. In exceptional
11824 ;; circumstances (e.g. "struct A {" in C++ Mode), the contents are examined,
11825 ;; too.
11822 ;; 11826 ;;
11823 ;; Here, "brace list" does not include the body of an enum. 11827 ;; Here, "brace list" does not include the body of an enum.
11824 (save-excursion 11828 (save-excursion
11825 (let ((start (point)) 11829 (let ((start (point))
11826 (braceassignp 'dontknow) 11830 (braceassignp 'dontknow)
11827 inexpr-brace-list bufpos macro-start res pos after-type-id-pos 11831 inexpr-brace-list bufpos macro-start res pos after-type-id-pos
11828 in-paren parens-before-brace 11832 pos2 in-paren parens-before-brace
11829 paren-state paren-pos) 11833 paren-state paren-pos)
11830 11834
11831 (setq res (c-backward-token-2 1 t lim)) 11835 (setq res (c-backward-token-2 1 t lim))
@@ -11841,12 +11845,16 @@ comment at the start of cc-engine.el for more info."
11841 (goto-char paren-pos) 11845 (goto-char paren-pos)
11842 (setq braceassignp 'c++-noassign 11846 (setq braceassignp 'c++-noassign
11843 in-paren 'in-paren)) 11847 in-paren 'in-paren))
11844 ((looking-at c-pre-id-bracelist-key) 11848 ((looking-at c-pre-brace-non-bracelist-key)
11845 (setq braceassignp nil)) 11849 (setq braceassignp nil))
11846 ((looking-at c-return-key)) 11850 ((looking-at c-return-key))
11847 ((and (looking-at c-symbol-start) 11851 ((and (looking-at c-symbol-start)
11848 (not (looking-at c-keywords-regexp))) 11852 (not (looking-at c-keywords-regexp)))
11849 (setq after-type-id-pos (point))) 11853 (if (save-excursion
11854 (and (zerop (c-backward-token-2 1 t lim))
11855 (looking-at c-pre-id-bracelist-key)))
11856 (setq braceassignp 'c++-noassign)
11857 (setq after-type-id-pos (point))))
11850 ((eq (char-after) ?\() 11858 ((eq (char-after) ?\()
11851 (setq parens-before-brace t) 11859 (setq parens-before-brace t)
11852 nil) 11860 nil)
@@ -11860,8 +11868,13 @@ comment at the start of cc-engine.el for more info."
11860 (eq (char-after paren-pos) ?\() 11868 (eq (char-after paren-pos) ?\()
11861 (setq in-paren 'in-paren) 11869 (setq in-paren 'in-paren)
11862 (goto-char paren-pos))) 11870 (goto-char paren-pos)))
11863 ((looking-at c-pre-id-bracelist-key)) 11871 ((looking-at c-pre-brace-non-bracelist-key))
11864 ((looking-at c-return-key)) 11872 ((looking-at c-return-key))
11873 ((and (looking-at c-symbol-start)
11874 (not (looking-at c-keywords-regexp))
11875 (save-excursion
11876 (and (zerop (c-backward-token-2 1 t lim))
11877 (looking-at c-pre-id-bracelist-key)))))
11865 (t (setq after-type-id-pos (point)) 11878 (t (setq after-type-id-pos (point))
11866 nil)))) 11879 nil))))
11867 (setq braceassignp 'c++-noassign)) 11880 (setq braceassignp 'c++-noassign))
@@ -11946,8 +11959,12 @@ comment at the start of cc-engine.el for more info."
11946 (cond 11959 (cond
11947 (braceassignp 11960 (braceassignp
11948 ;; We've hit the beginning of the aggregate list. 11961 ;; We've hit the beginning of the aggregate list.
11949 (c-beginning-of-statement-1 containing-sexp) 11962 (setq pos2 (point))
11950 (cons (point) (or in-paren inexpr-brace-list))) 11963 (cons
11964 (if (eq (c-beginning-of-statement-1 containing-sexp) 'same)
11965 (point)
11966 pos2)
11967 (or in-paren inexpr-brace-list)))
11951 ((and after-type-id-pos 11968 ((and after-type-id-pos
11952 (save-excursion 11969 (save-excursion
11953 (when (eq (char-after) ?\;) 11970 (when (eq (char-after) ?\;)
@@ -11959,34 +11976,36 @@ comment at the start of cc-engine.el for more info."
11959 (c-get-char-property (point) 'syntax-table)) 11976 (c-get-char-property (point) 'syntax-table))
11960 (c-go-list-forward nil after-type-id-pos) 11977 (c-go-list-forward nil after-type-id-pos)
11961 (c-forward-syntactic-ws))) 11978 (c-forward-syntactic-ws)))
11962 (and 11979 (if (and (not (eq (point) after-type-id-pos))
11963 (or (not (looking-at c-class-key)) 11980 (or (not (looking-at c-class-key))
11964 (save-excursion 11981 (save-excursion
11965 (goto-char (match-end 1)) 11982 (goto-char (match-end 1))
11966 (c-forward-syntactic-ws) 11983 (c-forward-syntactic-ws)
11967 (not (eq (point) after-type-id-pos)))) 11984 (not (eq (point) after-type-id-pos)))))
11968 (progn 11985 (progn
11969 (setq res 11986 (setq res
11970 (c-forward-decl-or-cast-1 11987 (c-forward-decl-or-cast-1 (c-point 'bosws)
11971 (save-excursion (c-backward-syntactic-ws) (point)) 11988 nil nil))
11972 nil nil)) 11989 (and (consp res)
11973 (and (consp res) 11990 (cond
11974 (cond 11991 ((eq (car res) after-type-id-pos))
11975 ((eq (car res) after-type-id-pos)) 11992 ((> (car res) after-type-id-pos) nil)
11976 ((> (car res) after-type-id-pos) nil) 11993 (t
11977 (t 11994 (catch 'find-decl
11978 (catch 'find-decl 11995 (save-excursion
11979 (save-excursion 11996 (goto-char (car res))
11980 (goto-char (car res)) 11997 (c-do-declarators
11981 (c-do-declarators 11998 (point-max) t nil nil
11982 (point-max) t nil nil 11999 (lambda (id-start _id-end _tok _not-top _func _init)
11983 (lambda (id-start _id-end _tok _not-top _func _init) 12000 (cond
11984 (cond 12001 ((> id-start after-type-id-pos)
11985 ((> id-start after-type-id-pos) 12002 (throw 'find-decl nil))
11986 (throw 'find-decl nil)) 12003 ((eq id-start after-type-id-pos)
11987 ((eq id-start after-type-id-pos) 12004 (throw 'find-decl t)))))
11988 (throw 'find-decl t))))) 12005 nil))))))
11989 nil))))))))) 12006 (save-excursion
12007 (goto-char start)
12008 (not (c-looking-at-statement-block))))))
11990 (cons bufpos (or in-paren inexpr-brace-list))) 12009 (cons bufpos (or in-paren inexpr-brace-list)))
11991 ((or (eq (char-after) ?\;) 12010 ((or (eq (char-after) ?\;)
11992 ;; Brace lists can't contain a semicolon, so we're done. 12011 ;; 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."
12136(defun c-looking-at-statement-block () 12155(defun c-looking-at-statement-block ()
12137 ;; Point is at an opening brace. If this is a statement block (i.e. the 12156 ;; Point is at an opening brace. If this is a statement block (i.e. the
12138 ;; elements in the block are terminated by semicolons, or the block is 12157 ;; elements in the block are terminated by semicolons, or the block is
12139 ;; empty, or the block contains a keyword) return non-nil. Otherwise, 12158 ;; empty, or the block contains a characteristic keyword, or there is a
12140 ;; return nil. 12159 ;; nested statement block) return non-nil. Otherwise, return nil.
12141 (let ((here (point))) 12160 (let ((here (point)))
12142 (prog1 12161 (prog1
12143 (if (c-go-list-forward) 12162 (if (c-go-list-forward)
12144 (let ((there (point))) 12163 (let ((there (point)))
12145 (backward-char) 12164 (backward-char)
12146 (c-syntactic-skip-backward "^;," here t) 12165 (c-syntactic-skip-backward "^;" here t)
12147 (cond 12166 (cond
12148 ((eq (char-before) ?\;) t) 12167 ((eq (char-before) ?\;))
12149 ((eq (char-before) ?,) nil) 12168 ((progn (c-forward-syntactic-ws)
12150 (t ; We're at (1+ here). 12169 (eq (point) (1- there))))
12151 (cond 12170 ((c-syntactic-re-search-forward
12152 ((progn (c-forward-syntactic-ws) 12171 c-stmt-block-only-keywords-regexp there t))
12153 (eq (point) (1- there)))) 12172 ((c-syntactic-re-search-forward "{" there t t)
12154 ((c-syntactic-re-search-forward c-keywords-regexp there t)) 12173 (backward-char)
12155 ((c-syntactic-re-search-forward "{" there t t) 12174 (c-looking-at-statement-block))
12156 (backward-char) 12175 (t nil)))
12157 (c-looking-at-statement-block))
12158 (t nil)))))
12159 (forward-char) 12176 (forward-char)
12160 (cond 12177 (cond
12161 ((c-syntactic-re-search-forward "[;,]" nil t t) 12178 ((c-syntactic-re-search-forward ";" nil t t))
12162 (eq (char-before) ?\;))
12163 ((progn (c-forward-syntactic-ws) 12179 ((progn (c-forward-syntactic-ws)
12164 (eobp))) 12180 (eobp)))
12165 ((c-syntactic-re-search-forward c-keywords-regexp nil t t)) 12181 ((c-syntactic-re-search-forward c-stmt-block-only-keywords-regexp
12182 nil t t))
12166 ((c-syntactic-re-search-forward "{" nil t t) 12183 ((c-syntactic-re-search-forward "{" nil t t)
12167 (backward-char) 12184 (backward-char)
12168 (c-looking-at-statement-block)) 12185 (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
3098 t (c-make-keywords-re t (c-lang-const c-keywords))) 3098 t (c-make-keywords-re t (c-lang-const c-keywords)))
3099(c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp)) 3099(c-lang-defvar c-keywords-regexp (c-lang-const c-keywords-regexp))
3100 3100
3101(c-lang-defconst c-stmt-block-only-keywords
3102 "All keywords which unambiguously signify a statement block (as opposed to
3103 a brace list) when occurring inside braces."
3104 t (c--set-difference
3105 (c-lang-const c-keywords)
3106 (append (c-lang-const c-primary-expr-kwds)
3107 (c-lang-const c-constant-kwds)
3108 `(,@(when (c-major-mode-is 'c++-mode)
3109 '("typeid" "dynamic_cast" "static_cast" "const_cast"
3110 "reinterpret_cast" "alignof")))
3111 (c-lang-const c-type-modifier-prefix-kwds)
3112 (c-lang-const c-overloadable-operators)
3113 (c-lang-const c-template-typename-kwds)
3114 `(,@(when (c-major-mode-is 'c++-mode)
3115 '("reflexpr")))
3116 `(,@(when (c-major-mode-is '(c-mode c++-mode))
3117 '("sizeof")))
3118 (c-lang-const c-pre-lambda-tokens)
3119 (c-lang-const c-block-decls-with-vars)
3120 (c-lang-const c-primitive-type-kwds))
3121 :test 'string-equal))
3122
3123(c-lang-defconst c-stmt-block-only-keywords-regexp
3124 ;; A regexp matching a keyword in `c-stmt-block-only-keywords'. Such a
3125 ;; match can start and end only at token boundaries.
3126 t (concat "\\(^\\|\\=\\|[^" (c-lang-const c-symbol-chars) "]\\)"
3127 (c-make-keywords-re t (c-lang-const c-stmt-block-only-keywords))))
3128(c-lang-defvar c-stmt-block-only-keywords-regexp
3129 (c-lang-const c-stmt-block-only-keywords-regexp))
3130
3101(c-lang-defconst c-keyword-member-alist 3131(c-lang-defconst c-keyword-member-alist
3102 ;; An alist with all the keywords in the cars. The cdr for each 3132 ;; An alist with all the keywords in the cars. The cdr for each
3103 ;; keyword is a list of the symbols for the `*-kwds' lists that 3133 ;; keyword is a list of the symbols for the `*-kwds' lists that
@@ -3650,13 +3680,25 @@ list."
3650 c t) 3680 c t)
3651(c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p)) 3681(c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p))
3652 3682
3683(c-lang-defconst c-pre-id-bracelist-kwds
3684 "Keywords which, preceding an identifier and brace, signify a bracelist.
3685This is only used in c++-mode."
3686 t nil
3687 c++ '("new" "throw"))
3688
3653(c-lang-defconst c-pre-id-bracelist-key 3689(c-lang-defconst c-pre-id-bracelist-key
3654 "A regexp matching tokens which, preceding an identifier, signify a bracelist. 3690 ;; A regexp matching keywords which, preceding an identifier and brace,
3655" 3691 ;; signify a bracelist. Only used in c++-mode.
3656 t regexp-unmatchable 3692 t (c-make-keywords-re t (c-lang-const c-pre-id-bracelist-kwds)))
3657 c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)")
3658(c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key)) 3693(c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key))
3659 3694
3695(c-lang-defconst c-pre-brace-non-bracelist-key
3696 "A regexp matching tokens which, preceding a brace, make it a non-bracelist."
3697 t regexp-unmatchable
3698 c++ "&&?\\(\\S.\\|$\\)")
3699(c-lang-defvar c-pre-brace-non-bracelist-key
3700 (c-lang-const c-pre-brace-non-bracelist-key))
3701
3660(c-lang-defconst c-recognize-typeless-decls 3702(c-lang-defconst c-recognize-typeless-decls
3661 "Non-nil means function declarations without return type should be 3703 "Non-nil means function declarations without return type should be
3662recognized. That can introduce an ambiguity with parenthesized macro 3704recognized. That can introduce an ambiguity with parenthesized macro