diff options
| author | Alan Mackenzie | 2021-03-02 20:31:36 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2021-03-02 20:31:36 +0000 |
| commit | 8dd588b1fb51bb9178bf34a6be9f35de84e95045 (patch) | |
| tree | e42564b6f27d055c16d70bd3b33595ba7b8585ed | |
| parent | aa14398aa14362095f1a42845015b9bab141c7d6 (diff) | |
| download | emacs-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.el | 7 | ||||
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 125 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 50 |
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. | ||
| 3685 | This 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 |
| 3662 | recognized. That can introduce an ambiguity with parenthesized macro | 3704 | recognized. That can introduce an ambiguity with parenthesized macro |