summaryrefslogtreecommitdiff
path: root/lisp/progmodes
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2019-03-12 18:33:31 +0000
committerAlan Mackenzie <acm@muc.de>2019-03-12 18:33:31 +0000
commitaa1a4cceca2d93d83c721ce83950230739073727 (patch)
tree5ee9e4a1722b1ffd6b5b545c62e96dafd0ebafe8 /lisp/progmodes
parentd58c29b345b40b836eeb0d9452a5940beda01fff (diff)
downloademacs-aa1a4cceca2d93d83c721ce83950230739073727.tar.gz
Correct the indentation of CC Mode brace lists
while preserving the indentation of nested C++ uniform initialization. * lisp/progmodes/cc-align.el (c-lineup-2nd-brace-entry-in-arglist) (c-lineup-class-decl-init-+, c-lineup-class-decl-init-after-brace): New indentation functions. * lisp/progmodes/cc-engine.el (c-forward-class-decl): New function. (c-do-declarators): New function, partially extracted from c-font-lock-declarators, which now calls the new function. (c-inside-bracelist-p): Amend the introductory comment. (c-add-stmt-syntax): Add code to prevent the spurious recognition of a 'defun-block-intro when a brace pair is used as an initializer. (c-evaluate-offset): No longer ignore vectors of length >= 2. (c-calc-offset): Refactor clumsily nested `if'/`or' into a cond form. * lisp/progmodes/cc-fonts.el (c-font-lock-declarators): Replace the bulk of this function by a call to the new c-forward-class-decl. * lisp/progmodes/cc-langs.el (c-type-decl-prefix-key): Recognize "~" as a type decl operator. * lisp/progmodes/cc-mode.el (c-fl-decl-start): While searching backward for a "}" at an EOD, deal with actually finding the end of a brace list. * doc/misc/cc-mode.texi (List Line-Up): document c-lineup-2nd-brace-entry-in-arglist, c-lineup-class-decl-init-+, and c-lineup-class-decl-init-after-brace. * lisp/progmodes/cc-styles.el (c-style-alist): In styles "gnu", "bsd", "stroustrup", "python", and "java", change the offset for brace-list-intro from the default value or c-lineup-arglist-intro-after-paren to a list beginning with the symbol first, followed by two of the new alignment functions, followed by +. * lisp/progmodes/cc-vars.el (c-offset-alist): Change the default value of brace-list-entry from c-lineup-under-anchor back to 0.
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/cc-align.el124
-rw-r--r--lisp/progmodes/cc-engine.el271
-rw-r--r--lisp/progmodes/cc-fonts.el143
-rw-r--r--lisp/progmodes/cc-langs.el2
-rw-r--r--lisp/progmodes/cc-mode.el11
-rw-r--r--lisp/progmodes/cc-styles.el16
-rw-r--r--lisp/progmodes/cc-vars.el2
7 files changed, 402 insertions, 167 deletions
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 1f94bfd4fea..009f58ea586 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -1083,6 +1083,130 @@ arglist-cont."
(vector (+ (current-column) c-basic-offset))))
(vector 0)))))
+(defun c-lineup-2nd-brace-entry-in-arglist (langelem)
+ "Lineup the second entry of a brace block under the first, when the first
+line is also contained in an arglist or an enclosing brace ON THAT LINE.
+
+I.e. handle something like the following:
+
+ set_line (line_t {point_t{0.4, 0.2},
+ point_t{0.2, 0.5}, <---- brace-list-intro
+ .....});
+ ^ enclosing parenthesis.
+
+The middle line of that example will have a syntactic context
+with three syntactic symbols, arglist-cont-nonempty, brace-list-intro, and
+brace-list-entry.
+
+This function is intended for use in a list. If the construct
+being analyzed isn't like the preceding, the function returns nil.
+Otherwise it returns the function `c-lineup-arglist-intro-after-paren', which
+the caller then uses to perform indentation.
+
+Works with brace-list-intro."
+ ;; brace-list-intro and brace-list-entry are both present for the second
+ ;; entry of the list when the first entry is on the same line as the opening
+ ;; brace.
+ (and (assq 'brace-list-intro c-syntactic-context)
+ (assq 'brace-list-entry c-syntactic-context)
+ (or (assq 'arglist-cont-nonempty c-syntactic-context) ; "(" earlier on
+ ; the line.
+ (save-excursion ; "{" earlier on the line
+ (goto-char (c-langelem-pos
+ (assq 'brace-list-intro c-syntactic-context)))
+ (and
+ (eq (c-backward-token-2
+ 1 nil
+ (c-point 'bol (c-langelem-pos
+ (assq 'brace-list-entry
+ c-syntactic-context))))
+ 0)
+ (eq (char-after) ?{))))
+ 'c-lineup-arglist-intro-after-paren))
+
+(defun c-lineup-class-decl-init-+ (langelem)
+ "Line up the second entry of a class (etc.) initializer c-basic-offset
+characters in from the identifier when:
+\(i) The type is a class, struct, union, etc. (but not an enum);
+\(ii) There is a brace block in the type declaration, specifying it; and
+\(iii) The first element of the initializer is on the same line as its opening
+brace.
+
+I.e. we have a construct like this:
+
+ struct STR {
+ int i; float f;
+ } str_1 = {1, 1.7},
+ str_2 = {2,
+ 3.1 <---- brace-list-intro
+ };
+ <--> <---- c-basic-offset
+
+Note that the syntactic context of the brace-list-intro line also has a
+syntactic element with the symbol brace-list-entry.
+
+This function is intended for use in a list. If the above structure isn't
+present, this function returns nil, allowing a different offset specification
+to indent the line.
+
+Works with: brace-list-intro."
+ (and (assq 'brace-list-intro c-syntactic-context)
+ (assq 'brace-list-entry c-syntactic-context)
+ (let ((init-pos (c-point 'boi (c-langelem-pos
+ (assq 'brace-list-entry
+ c-syntactic-context))))
+ )
+ (save-excursion
+ (goto-char (c-langelem-pos (assq 'brace-list-intro
+ c-syntactic-context)))
+ (and
+ (c-forward-class-decl)
+ (not (c-do-declarators init-pos t nil nil nil))
+ (eq (point) init-pos)
+ (vector (+ (current-column) c-basic-offset)))))))
+
+(defun c-lineup-class-decl-init-after-brace (langelem)
+ "Line up the second entry of a class (etc.) initializer after its opening
+brace when:
+\(i) The type is a class, struct, union, etc. (but not an enum);
+\(ii) There is a brace block in the type declaration, specifying it; and
+\(iii) The first element of the initializer is on the same line as its opening
+brace.
+
+I.e. we have a construct like this:
+
+ struct STR {
+ int i; float f;
+ } str_1 = {1, 1.7},
+ str_2 = {2,
+ 3.1 <---- brace-list-intro
+ };
+
+Note that the syntactic context of the brace-list-intro line also has a
+syntactic element with the symbol brace-list-entry. Also note that this
+function works by returning the symbol `c-lineup-arglist-intro-after-paren',
+which the caller then uses to perform the indentation.
+
+This function is intended for use in a list. If the above structure isn't
+present, this function returns nil, allowing a different offset specification
+to indent the line.
+
+Works with: brace-list-intro."
+ (and (assq 'brace-list-intro c-syntactic-context)
+ (assq 'brace-list-entry c-syntactic-context)
+ (let ((init-pos (c-point 'boi (c-langelem-pos
+ (assq 'brace-list-entry
+ c-syntactic-context))))
+ )
+ (save-excursion
+ (goto-char (c-langelem-pos (assq 'brace-list-intro
+ c-syntactic-context)))
+ (and
+ (c-forward-class-decl)
+ (not (c-do-declarators init-pos t nil nil nil))
+ (eq (point) init-pos)
+ 'c-lineup-arglist-intro-after-paren)))))
+
(defun c-lineup-cpp-define (_langelem)
"Line up macro continuation lines according to the indentation of
the construct preceding the macro. E.g.:
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 301d07c9c9c..fd669280994 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -8040,49 +8040,28 @@ comment at the start of cc-engine.el for more info."
(or res (goto-char here))
res))
+(defun c-forward-class-decl ()
+ "From the beginning of a struct/union, etc. move forward to
+after the brace block which defines it, leaving point at the
+start of the next token and returning point. On failure leave
+point unchanged and return nil."
+ (let ((here (point)))
+ (if
+ (and
+ (looking-at c-class-key)
+ (eq (c-forward-token-2) 0)
+ (c-on-identifier)
+ (eq (c-forward-token-2) 0)
+ (eq (char-after) ?{)
+ (c-go-list-forward))
+ (progn
+ (c-forward-syntactic-ws)
+ (point))
+ (goto-char here)
+ nil)))
;; Handling of large scale constructs like statements and declarations.
-;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a
-;; defsubst or perhaps even a defun, but it contains lots of free
-;; variables that refer to things inside `c-forward-decl-or-cast-1'.
-(defmacro c-fdoc-shift-type-backward (&optional short)
- ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list
- ;; of types when parsing a declaration, which means that it
- ;; sometimes consumes the identifier in the declaration as a type.
- ;; This is used to "backtrack" and make the last type be treated as
- ;; an identifier instead.
- `(progn
- ,(unless short
- ;; These identifiers are bound only in the inner let.
- '(setq identifier-type at-type
- identifier-start type-start
- got-parens nil
- got-identifier t
- got-suffix t
- got-suffix-after-parens id-start
- paren-depth 0))
-
- (if (setq at-type (if (eq backup-at-type 'prefix)
- t
- backup-at-type))
- (setq type-start backup-type-start
- id-start backup-id-start)
- (setq type-start start-pos
- id-start start-pos))
-
- ;; When these flags already are set we've found specifiers that
- ;; unconditionally signal these attributes - backtracking doesn't
- ;; change that. So keep them set in that case.
- (or at-type-decl
- (setq at-type-decl backup-at-type-decl))
- (or maybe-typeless
- (setq maybe-typeless backup-maybe-typeless))
-
- ,(unless short
- ;; This identifier is bound only in the inner let.
- '(setq start id-start))))
-
(defun c-forward-declarator (&optional limit accept-anon)
;; Assuming point is at the start of a declarator, move forward over it,
;; leaving point at the next token after it (e.g. a ) or a ; or a ,).
@@ -8235,6 +8214,176 @@ comment at the start of cc-engine.el for more info."
(goto-char here)
nil)))
+(defun c-do-declarators
+ (cdd-limit cdd-list cdd-not-top cdd-comma-prop cdd-function)
+ "Assuming point is at the start of a comma separated list of declarators,
+apply CDD-FUNCTION to each declarator (when CDD-LIST is non-nil) or just the
+first declarator (when CDD-LIST is nil). When CDD-FUNCTION is nil, no
+function is applied.
+
+CDD-FUNCTION is supplied with 6 arguments:
+0. The start position of the declarator's identifier;
+1. The end position of this identifier;
+\[Note: if there is no identifier, as in int (*);, both of these are nil.]
+2. The position of the next token after the declarator (CLARIFY!!!).
+3. CDD-NOT-TOP;
+4. Non-nil if the identifier is of a function.
+5. When there is an initialization following the declarator (such as \"=
+....\" or \"( ....\".), the character which introduces this initialization,
+otherwise nil.
+
+Additionally, if CDD-COMMA-PROP is non-nil, mark the separating commas with
+this value of the c-type property, when CDD-LIST is non-nil.
+
+Stop at or before CDD-LIMIT (which may NOT be nil).
+
+If CDD-NOT-TOP is non-nil, we are not at the top-level (\"top-level\" includes
+being directly inside a class or namespace, etc.).
+
+Return non-nil if we've reached the token after the last declarator (often a
+semicolon, or a comma when CDD-LIST is nil); otherwise (when we hit CDD-LIMIT,
+or fail otherwise) return nil, leaving point at the beginning of the putative
+declarator that could not be processed.
+
+This function might do hidden buffer changes."
+ ;; N.B.: We use the "cdd-" prefix in this routine to try to prevent
+ ;; confusion with possible reference to common variable names from within
+ ;; CDD-FUNCTION.
+ (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)
+
+ ;; The following `while' applies `cdd-function' to a single declarator id
+ ;; each time round. It loops only when CDD-LIST is non-nil.
+ (while
+ (and (not cdd-exhausted)
+ (setq cdd-decl-res (c-forward-declarator cdd-limit)))
+ (setq cdd-next-pos (point)
+ cdd-id-start (car cdd-decl-res)
+ cdd-id-end (cadr cdd-decl-res)
+ cdd-got-func (and (eq (char-after) ?\()
+ (or (not (c-major-mode-is 'c++-mode))
+ (not cdd-not-top)
+ (car (cddr (cddr cdd-decl-res))) ; Id is in
+ ; parens, etc.
+ (save-excursion
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (looking-at "[*&]")))
+ (not (car (cddr cdd-decl-res)))
+ (or (not (c-major-mode-is 'c++-mode))
+ (save-excursion
+ (let (c-last-identifier-range)
+ (forward-char)
+ (c-forward-syntactic-ws)
+ (catch 'is-function
+ (while
+ (progn
+ (if (eq (char-after) ?\))
+ (throw 'is-function t))
+ (setq cdd-got-type (c-forward-type))
+ (cond
+ ((null cdd-got-type)
+ (throw 'is-function nil))
+ ((not (eq cdd-got-type 'maybe))
+ (throw 'is-function t)))
+ (c-forward-declarator nil t)
+ (eq (char-after) ?,))
+ (forward-char)
+ (c-forward-syntactic-ws))
+ t)))))
+ cdd-got-init (and (cadr (cddr cdd-decl-res))
+ (char-after)))
+
+ ;; Jump past any initializer or function prototype to see if
+ ;; there's a ',' to continue at.
+ (cond (cdd-got-func
+ ;; Skip a parenthesized initializer (C++) or a function
+ ;; prototype.
+ (if (c-go-list-forward (point) cdd-limit) ; over the parameter list.
+ (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))
+ (backward-char)
+ (setq cdd-exhausted t)
+ ))
+
+ (t (c-forward-syntactic-ws cdd-limit)))
+
+ (if cdd-function
+ (funcall cdd-function cdd-id-start cdd-id-end cdd-next-pos
+ cdd-not-top cdd-got-func cdd-got-init))
+
+ ;; If a ',' is found we set cdd-pos to the next declarator and iterate.
+ (if (and cdd-list (< (point) cdd-limit) (looking-at ","))
+ (progn
+ (when cdd-comma-prop
+ (c-put-char-property (point) 'c-type cdd-comma-prop))
+ (forward-char)
+ (c-forward-syntactic-ws cdd-limit)
+ (setq cdd-pos (point)))
+ (setq cdd-exhausted t)))
+
+ (if (> (point) cdd-pos)
+ t
+ (goto-char cdd-pos)
+ nil)))
+
+;; Macro used inside `c-forward-decl-or-cast-1'. It ought to be a
+;; defsubst or perhaps even a defun, but it contains lots of free
+;; variables that refer to things inside `c-forward-decl-or-cast-1'.
+(defmacro c-fdoc-shift-type-backward (&optional short)
+ ;; `c-forward-decl-or-cast-1' can consume an arbitrary length list
+ ;; of types when parsing a declaration, which means that it
+ ;; sometimes consumes the identifier in the declaration as a type.
+ ;; This is used to "backtrack" and make the last type be treated as
+ ;; an identifier instead.
+ `(progn
+ ,(unless short
+ ;; These identifiers are bound only in the inner let.
+ '(setq identifier-type at-type
+ identifier-start type-start
+ got-parens nil
+ got-identifier t
+ got-suffix t
+ got-suffix-after-parens id-start
+ paren-depth 0))
+
+ (if (setq at-type (if (eq backup-at-type 'prefix)
+ t
+ backup-at-type))
+ (setq type-start backup-type-start
+ id-start backup-id-start)
+ (setq type-start start-pos
+ id-start start-pos))
+
+ ;; When these flags already are set we've found specifiers that
+ ;; unconditionally signal these attributes - backtracking doesn't
+ ;; change that. So keep them set in that case.
+ (or at-type-decl
+ (setq at-type-decl backup-at-type-decl))
+ (or maybe-typeless
+ (setq maybe-typeless backup-maybe-typeless))
+
+ ,(unless short
+ ;; This identifier is bound only in the inner let.
+ '(setq start id-start))))
+
(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
;; Move forward over a declaration or a cast if at the start of one.
;; The point is assumed to be at the start of some token. Nil is
@@ -10727,12 +10876,17 @@ comment at the start of cc-engine.el for more info."
)))
(defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren)
- ;; return the buffer position of the beginning of the brace list
- ;; statement if we're inside a brace list, otherwise return nil.
- ;; CONTAINING-SEXP is the buffer pos of the innermost containing
- ;; paren. PAREN-STATE is the remainder of the state of enclosing
- ;; braces. ACCEPT-IN-PAREN is non-nil iff we will accept as a brace
- ;; list a brace directly enclosed in a parenthesis.
+ ;; return the buffer position of the beginning of the brace list statement
+ ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil.
+ ;;
+ ;; CONTAINING-SEXP is the buffer pos of the innermost containing paren. NO
+ ;; IT ISN'T!!! [This function is badly designed, and probably needs
+ ;; reformulating without its first argument, and the critical position being
+ ;; at point.]
+ ;;
+ ;; PAREN-STATE is the remainder of the state of enclosing braces.
+ ;; ACCEPT-IN-PAREN is non-nil iff we will accept as a brace list a brace
+ ;; directly enclosed in a parenthesis.
;;
;; The "brace list" here is recognized solely by its context, not by
;; its contents.
@@ -10852,7 +11006,8 @@ 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 t. Otherwise, return nil.
+ ;; empty, or the block contains a keyword) return non-nil. Otherwise,
+ ;; return nil.
(let ((here (point)))
(prog1
(if (c-go-list-forward)
@@ -11356,7 +11511,7 @@ comment at the start of cc-engine.el for more info."
(if (and (eq step-type 'same)
(/= paren-pos (point)))
- (let (inexpr)
+ (let (inexpr bspec)
(cond
((save-excursion
(goto-char paren-pos)
@@ -11378,6 +11533,13 @@ comment at the start of cc-engine.el for more info."
(c-looking-at-statement-block))
(c-add-syntax 'defun-block-intro nil)
(c-add-syntax 'brace-list-intro nil)))
+ ((save-excursion
+ (goto-char paren-pos)
+ (setq bspec (c-looking-at-or-maybe-in-bracelist
+ containing-sexp containing-sexp))
+ (and (consp bspec)
+ (eq (cdr bspec) 'in-paren)))
+ (c-add-syntax 'brace-list-intro (car bspec)))
(t (c-add-syntax 'defun-block-intro nil))))
(c-add-syntax 'statement-block-intro nil)))
@@ -13242,7 +13404,7 @@ Cannot combine absolute offsets %S and %S in `add' method"
nil))))
(if (or (null res) (integerp res)
- (and (vectorp res) (= (length res) 1) (integerp (aref res 0))))
+ (and (vectorp res) (>= (length res) 1) (integerp (aref res 0))))
res
(c-benign-error "Error evaluating offset %S for %s: Got invalid value %S"
offset symbol res)
@@ -13265,12 +13427,11 @@ Cannot combine absolute offsets %S and %S in `add' method"
(if c-strict-syntax-p
(c-benign-error "No offset found for syntactic symbol %s" symbol))
(setq offset 0))
- (if (vectorp offset)
- offset
- (or (and (numberp offset) offset)
- (and (symbolp offset) (symbol-value offset))
- 0))
- ))
+ (cond
+ ((or (vectorp offset) (numberp offset))
+ offset)
+ ((and (symbolp offset) (symbol-value offset)))
+ (t 0))))
(defun c-get-offset (langelem)
;; This is a compatibility wrapper for `c-calc-offset' in case
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 0588032fdbe..0b41eff1577 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1032,114 +1032,41 @@ casts and declarations are fontified. Used on level 2 and higher."
;;(message "c-font-lock-declarators from %s to %s" (point) limit)
(c-fontify-types-and-refs
- ((pos (point)) next-pos id-start
- decl-res
- id-face got-type got-init
- c-last-identifier-range
- (separator-prop (if types 'c-decl-type-start 'c-decl-id-start)))
-
- ;; The following `while' fontifies a single declarator id each time round.
- ;; It loops only when LIST is non-nil.
- (while
- (and pos (setq decl-res (c-forward-declarator)))
- (setq next-pos (point)
- id-start (car decl-res)
- id-face (if (and (eq (char-after) ?\()
- (or (not (c-major-mode-is 'c++-mode))
- (not not-top)
- (car (cddr (cddr decl-res))) ; Id is in
- ; parens, etc.
- (save-excursion
- (forward-char)
- (c-forward-syntactic-ws)
- (looking-at "[*&]")))
- (not (car (cddr decl-res)))
- (or (not (c-major-mode-is 'c++-mode))
- (save-excursion
- (let (c-last-identifier-range)
- (forward-char)
- (c-forward-syntactic-ws)
- (catch 'is-function
- (while
- (progn
- (if (eq (char-after) ?\))
- (throw 'is-function t))
- (setq got-type (c-forward-type))
- (cond
- ((null got-type)
- (throw 'is-function nil))
- ((not (eq got-type 'maybe))
- (throw 'is-function t)))
- (c-forward-declarator nil t)
- (eq (char-after) ?,))
- (forward-char)
- (c-forward-syntactic-ws))
- t)))))
- 'font-lock-function-name-face
- 'font-lock-variable-name-face)
- got-init (and (cadr (cddr decl-res)) ; got-init
- (char-after)))
-
- (if types
- ;; Register and fontify the identifier as a type.
- (let ((c-promote-possible-types t))
- (goto-char id-start)
- (c-forward-type))
- ;; Fontify the last symbol in the identifier if it isn't fontified
- ;; already. The check is necessary only in certain cases where this
- ;; function is used "sloppily", e.g. in `c-simple-decl-matchers'.
- (when (and c-last-identifier-range
- (not (get-text-property (car c-last-identifier-range)
- 'face)))
- (c-put-font-lock-face (car c-last-identifier-range)
- (cdr c-last-identifier-range)
- id-face)))
-
- (goto-char next-pos)
- (setq pos nil) ; So as to terminate the enclosing `while' form.
- (if (and template-class
- (eq got-init ?=) ; C++ "<class X = Y>"?
- (c-forward-token-2 1 nil limit) ; Over "="
- (let ((c-promote-possible-types t))
- (c-forward-type t))) ; Over "Y"
- (setq list nil)) ; Shouldn't be needed. We can't have a list, here.
-
- (when list
- ;; Jump past any initializer or function prototype to see if
- ;; there's a ',' to continue at.
- (cond ((eq id-face 'font-lock-function-name-face)
- ;; Skip a parenthesized initializer (C++) or a function
- ;; prototype.
- (if (c-safe (c-forward-sexp 1) t) ; over the parameter list.
- (c-forward-syntactic-ws limit)
- (goto-char limit))) ; unbalanced parens
-
- (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.
- (and (if (and (eq got-init ?=)
- (= (c-forward-token-2 1 nil limit) 0)
- (looking-at "{"))
- (c-safe (c-forward-sexp) t) ; over { .... }
- t)
- (< (point) limit)
- ;; 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 "[;,{]" limit 'move t)
- (backward-char)))
-
- (t (c-forward-syntactic-ws limit)))
-
- ;; If a ',' is found we set pos to the next declarator and iterate.
- (when (and (< (point) limit) (looking-at ","))
- (c-put-char-property (point) 'c-type separator-prop)
- (forward-char)
- (c-forward-syntactic-ws limit)
- (setq pos (point)))))) ; acts to make the `while' form continue.
- nil)
+ ()
+ (c-do-declarators
+ limit list not-top
+ (if types 'c-decl-type-start 'c-decl-id-start)
+ (lambda (id-start id-end end-pos not-top is-function init-char)
+ (if types
+ ;; Register and fontify the identifier as a type.
+ (let ((c-promote-possible-types t))
+ (goto-char id-start)
+ (c-forward-type))
+ ;; The following doesn't work properly (yet, 2018-09-22).
+ ;; (c-put-font-lock-face id-start id-end
+ ;; (if is-function
+ ;; 'font-lock-function-name-face
+ ;; 'font-lock-variable-name-face))
+ (when (and c-last-identifier-range
+ (not (get-text-property (car c-last-identifier-range)
+ 'face)))
+ ;; We use `c-last-identifier-range' rather than `id-start' and
+ ;; `id-end', since the latter two can be erroneous. E.g. in
+ ;; "~Foo", `id-start' is at the tilde. This is a bug in
+ ;; `c-forward-declarator'.
+ (c-put-font-lock-face (car c-last-identifier-range)
+ (cdr c-last-identifier-range)
+ (if is-function
+ 'font-lock-function-name-face
+ 'font-lock-variable-name-face))))
+ (and template-class
+ (eq init-char ?=) ; C++ "<class X = Y>"?
+ (progn
+ (goto-char end-pos)
+ (c-forward-token-2 1 nil limit) ; Over "="
+ (let ((c-promote-possible-types t))
+ (c-forward-type t))))))
+ nil))
(defun c-get-fontification-context (match-pos not-front-decl &optional toplev)
;; Return a cons (CONTEXT . RESTRICTED-<>-ARGLISTS) for MATCH-POS.
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 53342713b4a..7cc8029e0a3 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3258,7 +3258,7 @@ Identifier syntax is in effect when this is matched \(see
"\\|"
"\\.\\.\\."
"\\|"
- "[*(&]"
+ "[*(&~]"
"\\|"
(c-lang-const c-type-decl-prefix-key)
"\\|"
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 4e63bd9144b..8343978fc38 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1803,7 +1803,16 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; Go to a less nested declaration each time round this loop.
(and
(setq old-pos (point))
- (c-syntactic-skip-backward "^;{}" bod-lim t)
+ (let (pseudo)
+ (while
+ (progn
+ (c-syntactic-skip-backward "^;{}" bod-lim t)
+ (and (eq (char-before) ?})
+ (save-excursion
+ (backward-char)
+ (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state))))))
+ (goto-char pseudo))
+ t)
(> (point) bod-lim)
(progn (c-forward-syntactic-ws)
;; Have we got stuck in a comment at EOB?
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index d2c41008711..92ea67128f4 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -68,7 +68,9 @@
(arglist-close . c-lineup-arglist)
(inline-open . 0)
(brace-list-open . +)
- (brace-list-intro . c-lineup-arglist-intro-after-paren)
+ (brace-list-intro . (first
+ c-lineup-2nd-brace-entry-in-arglist
+ c-lineup-class-decl-init-+ +))
(topmost-intro-cont
. (first c-lineup-topmost-intro-cont
c-lineup-gnu-DEFUN-intro-cont))))
@@ -95,6 +97,9 @@
(label . 0)
(statement-cont . +)
(inline-open . 0)
+ (brace-list-intro . (first
+ c-lineup-2nd-brace-entry-in-arglist
+ c-lineup-class-decl-init-+ +))
(inexpr-class . 0))))
("stroustrup"
@@ -104,6 +109,9 @@
(substatement-open . 0)
(substatement-label . 0)
(label . 0)
+ (brace-list-intro . (first
+ c-lineup-2nd-brace-entry-in-arglist
+ c-lineup-class-decl-init-+ +))
(statement-cont . +))))
("whitesmith"
@@ -194,6 +202,9 @@
(c-offsets-alist . ((substatement-open . 0)
(inextern-lang . 0)
(arglist-intro . +)
+ (brace-list-intro . (first
+ c-lineup-2nd-brace-entry-in-arglist
+ c-lineup-class-decl-init-+ +))
(knr-argdecl-intro . +)))
(c-hanging-braces-alist . ((brace-list-open)
(brace-list-intro)
@@ -219,6 +230,9 @@
(statement-cont . +)
(arglist-intro . c-lineup-arglist-intro-after-paren)
(arglist-close . c-lineup-arglist)
+ (brace-list-intro . (first
+ c-lineup-2nd-brace-entry-in-arglist
+ c-lineup-class-decl-init-+ +))
(access-label . 0)
(inher-cont . c-lineup-java-inher)
(func-decl-cont . c-lineup-java-throws))))
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 89534882672..6e8acd4c0dd 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -1115,7 +1115,7 @@ can always override the use of `c-default-style' by making calls to
;; Anchor pos: At the brace list decl start(*).
(brace-list-intro . +)
;; Anchor pos: At the brace list decl start(*).
- (brace-list-entry . c-lineup-under-anchor)
+ (brace-list-entry . 0)
;; Anchor pos: At the first non-ws char after the open paren if
;; the first token is on the same line, otherwise boi at that
;; token.