diff options
author | Alan Mackenzie <acm@muc.de> | 2016-09-11 21:09:08 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2016-09-11 21:09:08 +0000 |
commit | c417f08b16cd9e16451a6d3231097eeb4a804f2d (patch) | |
tree | 9590af6fa9497372061c4a41106e05066180cd84 | |
parent | f95ca1268da211f5c60985d411df43bb5477430b (diff) |
Correctly fontify C++ direct initializations with parens inside functions
Or, more clearly, when something looks like a function declaration and it's
inside a function, fontify it as a direct initialization.
For this purpose, introduce a "brace stack" for each buffer, where an entry on
the brace stack states how deeply nested a particular position is inside
braces inside a "top level", which includes classes and namespaces.
Also introduce a new "context", "top", with which c-font-lock-declarations
signals to c-forward-decl-or-cast-1 that point is at the top level.
* lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): add
c-truncate-bs-cache.
(c-flat-decl-block-kwds, c-brace-stack-thing-key, c-brace-stack-no-semi-key)
(c-type-decl-operator-prefix-key): new language constants/variables.
* lisp/progmodes/cc-engine.el (c-bs-interval, c-bs-cache, c-bs-cache-limit)
(c-bs-prev-pos, c-bs-prev-stack): New mostly local variables for the brace
stack cache.
(c-init-bs-cache, c-truncate-bs-cache, c-truncate-bs-cache, c-brace-stack-at)
(c-bs-at-toplevel-p): New functions which manipulate the brace stack (cache).
(c-find-decl-prefix-search): Keep track of whether we're at top level.
(c-find-decl-spots): New local variable cfd-top-level which records what it
says. On calling cfd-fun, pass cfd-top-level as an additional argument.
(c-forward-declarator): Add new element DECORATED to the result list. Set it
to non-nil when a match for c-type-decl-operator-prefix-key is found.
(c-forward-decl-or-cast-1): Handle the newly introduced context "top".
Introduce "CASE 9.5", which recognizes direct initializations.
* lisp/progmodes/cc-fonts.el (c-font-lock-complex-decl-prepare)
(c-font-lock-enum-tail, c-font-lock-cut-off-declarators)
(c-font-lock-enclosing-decls, c-simple-decl-matchers, c-basic-matchers-after):
Add appropriate `not-top' argument to calls to c-font-lock-declarators.
(c-font-lock-declarators): Additional parameter `not-top'. Use not-top to
participate in the decision whether to fontify an identifier as a function or
a variable.
(c-font-lock-declarations): The internal lambda function takes an additional
argument `toplev' from c-find-decl-spots, which it uses in determining the
"context" of a declaration. Add appropriate `not-top' argument to calls to
c-font-lock-declarators.
(c-font-lock-objc-methods): Add extra parameter to internal lambda function,
like for c-font-lock-declarators.
* lisp/progmodes/cc-mode.el (c-basic-common-init): Initialize the brace stack
cache.
-rw-r--r-- | lisp/progmodes/cc-engine.el | 257 | ||||
-rw-r--r-- | lisp/progmodes/cc-fonts.el | 47 | ||||
-rw-r--r-- | lisp/progmodes/cc-langs.el | 63 | ||||
-rw-r--r-- | lisp/progmodes/cc-mode.el | 2 |
4 files changed, 337 insertions, 32 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 259f8a03b3..a1574b23c5 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -5128,6 +5128,211 @@ comment at the start of cc-engine.el for more info." (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face) (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face)))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Machinery for determining when we're at top level (this including being +;; directly inside a class or namespace, etc.) +;; +;; We maintain a stack of brace depths in structures like classes and +;; namespaces. The car of this structure, when non-nil, indicates that the +;; associated position is within a template (etc.) structure, and the value is +;; the position where the (outermost) template ends. The other elements in +;; the structure are stacked elements, one each for each enclosing "top level" +;; structure. +;; +;; At the very outermost level, the value of the stack would be (nil 1), the +;; "1" indicating an enclosure in a notional all-enclosing block. After +;; passing a keyword such as "namespace", the value would become (nil 0 1). +;; At this point, passing a semicolon would cause the 0 to be dropped from the +;; stack (at any other time, a semicolon is ignored). Alternatively, on +;; passing an opening brace, the stack would become (nil 1 1). Each opening +;; brace passed causes the cadr to be incremented, and passing closing braces +;; causes it to be decremented until it reaches 1. On passing a closing brace +;; when the cadr of the stack is at 1, this causes it to be removed from the +;; stack, the corresponding namespace (etc.) structure having been closed. +;; +;; There is a special stack value -1 which means the C++ colon operator +;; introducing a list of inherited classes has just been parsed. The value +;; persists on the stack until the next open brace or semicolon. +;; +;; When the car of the stack is non-nil, i.e. when we're in a template (etc.) +;; structure, braces are not counted. The counting resumes only after passing +;; the template's closing position, which is recorded in the car of the stack. +;; +;; The test for being at top level consists of the cadr being 0 or 1. +;; +;; The values of this stack throughout a buffer are cached in a simple linear +;; cache, every 5000 characters. +;; +;; Note to maintainers: This cache mechanism is MUCH faster than recalculating +;; the stack at every entry to `c-find-decl-spots' using `c-at-toplevel-p' or +;; the like. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The approximate interval at which we cache the value of the brace stack. +(defconst c-bs-interval 5000) +;; The list of cached values of the brace stack. Each value in the list is a +;; cons of the position it is valid for and the value of the stack as +;; described above. +(defvar c-bs-cache nil) +(make-variable-buffer-local 'c-bs-cache) +;; The position of the buffer at and below which entries in `c-bs-cache' are +;; valid. +(defvar c-bs-cache-limit 1) +(make-variable-buffer-local 'c-bs-cache-limit) +;; The previous buffer position for which the brace stack value was +;; determined. +(defvar c-bs-prev-pos most-positive-fixnum) +(make-variable-buffer-local 'c-bs-prev-pos) +;; The value of the brace stack at `c-bs-prev-pos'. +(defvar c-bs-prev-stack nil) +(make-variable-buffer-local 'c-bs-prev-stack) + +(defun c-init-bs-cache () + ;; Initialize the cache in `c-bs-cache' and related variables. + (setq c-bs-cache nil + c-bs-cache-limit 1 + c-bs-prev-pos most-positive-fixnum + c-bs-prev-stack nil)) + +(defun c-truncate-bs-cache (pos &rest _ignore) + ;; Truncate the upper bound of the cache `c-bs-cache' to POS, if it is + ;; higher than that position. This is called as either a before- or + ;; after-change-function. + (setq c-bs-cache-limit + (min c-bs-cache-limit pos))) + +(defun c-update-brace-stack (stack from to) + ;; Give a brace-stack which has the value STACK at position FROM, update it + ;; to it's value at position TO, where TO is after (or equal to) FROM. + ;; Return a cons of either TO (if it is outside a literal) and this new + ;; value, or of the next position after TO outside a literal and the new + ;; value. + (let (match kwd-sym (prev-match-pos 1) + (s (cdr stack)) + (bound-<> (car stack)) + ) + (save-excursion + (cond + ((and bound-<> (<= to bound-<>)) + (goto-char to)) ; Nothing to do. + (bound-<> + (goto-char bound-<>) + (setq bound-<> nil)) + (t (goto-char from))) + (while (and (< (point) to) + (c-syntactic-re-search-forward + (if (<= (car s) 0) + c-brace-stack-thing-key + c-brace-stack-no-semi-key) + to 'after-literal) + (> (point) prev-match-pos)) ; prevent infinite loop. + (setq prev-match-pos (point)) + (setq match (match-string-no-properties 1) + kwd-sym (c-keyword-sym match)) + (cond + ((and (equal match "{") + (progn (backward-char) + (prog1 (looking-at "\\s(") + (forward-char)))) + (setq s (if s + (cons (if (<= (car s) 0) + 1 + (1+ (car s))) + (cdr s)) + (list 1)))) + ((and (equal match "}") + (progn (backward-char) + (prog1 (looking-at "\\s)") + (forward-char)))) + (setq s + (cond + ((and s (> (car s) 1)) + (cons (1- (car s)) (cdr s))) + ((and (cdr s) (eq (car s) 1)) + (cdr s)) + (t s)))) + ((and (equal match "<") + (progn (backward-char) + (prog1 (looking-at "\\s(") + (forward-char)))) + (backward-char) + (if (c-forward-<>-arglist nil) ; Should always work. + (when (> (point) to) + (setq bound-<> (point))) + (forward-char))) + ((and (equal match ":") + s + (eq (car s) 0)) + (setq s (cons -1 (cdr s)))) + ((and (equal match ",") + (eq (car s) -1))) ; at "," in "class foo : bar, ..." + ((member match '(";" "," ")")) + (when (and s (cdr s) (<= (car s) 0)) + (setq s (cdr s)))) + ((c-keyword-member kwd-sym 'c-flat-decl-block-kwds) + (push 0 s)))) + (cons (point) + (cons bound-<> s))))) + +(defun c-brace-stack-at (here) + ;; Given a buffer position HERE, Return the value of the brace stack there. + (save-excursion + (save-restriction + (widen) + (let ((c c-bs-cache) + (can-use-prev (<= c-bs-prev-pos c-bs-cache-limit)) + elt stack pos npos high-elt) + ;; Trim the cache to take account of buffer changes. + (while (and c + (> (caar c) c-bs-cache-limit)) + (setq c (cdr c))) + (setq c-bs-cache c) + + (while (and c + (> (caar c) here)) + (setq high-elt (car c)) + (setq c (cdr c))) + (setq pos (or (and c (caar c)) + (point-min))) + + (setq elt (if c + (car c) + (cons (point-min) + (cons nil (list 1))))) + (when (not high-elt) + (setq stack (cdr elt)) + (while + ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration. + (<= (setq npos (+ pos c-bs-interval)) here) + (setq elt (c-update-brace-stack stack pos npos)) + (setq npos (car elt)) + (setq stack (cdr elt)) + (unless (eq npos (point-max)) ; NPOS could be in a literal at EOB. + (setq c-bs-cache (cons elt c-bs-cache))) + (setq pos npos))) + + (if (> pos c-bs-cache-limit) + (setq c-bs-cache-limit pos)) + + ;; Can we just use the previous value? + (if (and can-use-prev + (<= c-bs-prev-pos here) + (> c-bs-prev-pos (car elt))) + (setq pos c-bs-prev-pos + stack c-bs-prev-stack) + (setq pos (car elt) + stack (cdr elt))) + (if (> here c-bs-cache-limit) + (setq c-bs-cache-limit here)) + (setq elt (c-update-brace-stack stack pos here) + c-bs-prev-pos (car elt) + c-bs-prev-stack (cdr elt)))))) + +(defun c-bs-at-toplevel-p (here) + ;; Is position HERE at the top level, as indicated by the brace stack? + (let ((stack (c-brace-stack-at here))) + (or (null stack) ; Probably unnecessary. + (<= (cadr stack) 1)))) + (defmacro c-find-decl-prefix-search () ;; Macro used inside `c-find-decl-spots'. It ought to be a defun, ;; but it contains lots of free variables that refer to things @@ -5221,6 +5426,7 @@ comment at the start of cc-engine.el for more info." cfd-re-match nil) (setq cfd-match-pos cfd-prop-match cfd-prop-match nil)) + (setq cfd-top-level (c-bs-at-toplevel-p cfd-match-pos)) (goto-char cfd-match-pos) @@ -5319,7 +5525,11 @@ comment at the start of cc-engine.el for more info." ;; comments. (cfd-token-pos 0) ;; The end position of the last entered macro. - (cfd-macro-end 0)) + (cfd-macro-end 0) + ;; Whether the last position returned from `c-find-decl-prefix-search' + ;; is at the top-level (including directly in a class or namespace, + ;; etc.). + cfd-top-level) ;; Initialize by finding a syntactically relevant start position ;; before the point, and do the first `c-decl-prefix-or-start-re' @@ -5627,7 +5837,7 @@ comment at the start of cc-engine.el for more info." nil)))) ; end of when condition (c-debug-put-decl-spot-faces cfd-match-pos (point)) - (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) + (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0) cfd-top-level) (setq cfd-prop-match nil)) (when (/= cfd-macro-end 0) @@ -7552,10 +7762,12 @@ comment at the start of cc-engine.el for more info." ;; 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 ,). ;; - ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT), where ID-START and - ;; ID-END are the bounds of the declarator's identifier, and - ;; BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id. - ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(". + ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT DECORATED), + ;; where ID-START and ID-END are the bounds of the declarator's identifier, + ;; and BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id. + ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(", + ;; DECORATED is non-nil when the identifier is embellished by an operator, + ;; like "*x", or "(*x)". ;; ;; If ACCEPT-ANON is non-nil, move forward over any "anonymous declarator", ;; i.e. something like the (*) in int (*), such as might be found in a @@ -7574,7 +7786,7 @@ comment at the start of cc-engine.el for more info." ;; array/struct initialization) or "=" or terminating delimiter ;; (e.g. "," or ";" or "}"). (let ((here (point)) - id-start id-end brackets-after-id paren-depth) + id-start id-end brackets-after-id paren-depth decorated) (or limit (setq limit (point-max))) (if (and (< (point) limit) @@ -7614,6 +7826,8 @@ comment at the start of cc-engine.el for more info." (setq got-identifier t) nil)) t)) + (if (looking-at c-type-decl-operator-prefix-key) + (setq decorated t)) (if (eq (char-after) ?\() (progn (setq paren-depth (1+ paren-depth)) @@ -7668,7 +7882,7 @@ comment at the start of cc-engine.el for more info." (setq brackets-after-id t)) (backward-char) found)) - (list id-start id-end brackets-after-id (match-beginning 1)) + (list id-start id-end brackets-after-id (match-beginning 1) decorated) (goto-char here) nil))) @@ -7744,6 +7958,9 @@ comment at the start of cc-engine.el for more info." ;; inside a function declaration arglist). ;; '<> In an angle bracket arglist. ;; 'arglist Some other type of arglist. + ;; 'top Some other context and point is at the top-level (either + ;; outside any braces or directly inside a class or namespace, + ;; etc.) ;; nil Some other context or unknown context. Includes ;; within the parens of an if, for, ... construct. ;; 'not-decl This value is never supplied to this function. It @@ -8152,7 +8369,7 @@ comment at the start of cc-engine.el for more info." maybe-typeless backup-maybe-typeless (when c-recognize-typeless-decls - (and (not context) + (and (memq context '(nil top)) ;; Deal with C++11's "copy-initialization" ;; where we have <type>(<constant>), by ;; contrasting with a typeless @@ -8215,7 +8432,7 @@ comment at the start of cc-engine.el for more info." (setq at-decl-end (looking-at (cond ((eq context '<>) "[,>]") - (context "[,)]") + ((not (memq context '(nil top))) "[,\)]") (t "[,;]")))) ;; Now we've collected info about various characteristics of @@ -8344,7 +8561,7 @@ comment at the start of cc-engine.el for more info." (if (and got-parens (not got-prefix) - (not context) + (memq context '(nil top)) (not (eq at-type t)) (or backup-at-type maybe-typeless @@ -8394,6 +8611,18 @@ comment at the start of cc-engine.el for more info." ;; instantiation expression). (throw 'at-decl-or-cast nil)))) + ;; CASE 9.5 + (when (and (not context) ; i.e. not at top level. + (c-major-mode-is 'c++-mode) + (eq at-decl-or-cast 'ids) + after-paren-pos) + ;; We've got something like "foo bar (...)" in C++ which isn't at + ;; the top level. This is probably a uniform initialization of bar + ;; to the contents of the parens. In this case the declarator ends + ;; at the open paren. + (goto-char (1- after-paren-pos)) + (throw 'at-decl-or-cast t)) + ;; CASE 10 (when at-decl-or-cast ;; By now we've located the type in the declaration that we know @@ -8402,7 +8631,7 @@ comment at the start of cc-engine.el for more info." ;; CASE 11 (when (and got-identifier - (not context) + (memq context '(nil top)) (looking-at c-after-suffixed-type-decl-key) (if (and got-parens (not got-prefix) @@ -8498,7 +8727,7 @@ comment at the start of cc-engine.el for more info." (when (and got-prefix-before-parens at-type (or at-decl-end (looking-at "=[^=]")) - (not context) + (memq context '(nil top)) (or (not got-suffix) at-decl-start)) ;; Got something like "foo * bar;". Since we're not inside @@ -8524,7 +8753,7 @@ comment at the start of cc-engine.el for more info." (throw 'at-decl-or-cast t))) ;; CASE 18 - (when (and context + (when (and (not (memq context '(nil top))) (or got-prefix (and (eq context 'decl) (not c-recognize-paren-inits) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 735108ff7d..26a002ac8a 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -899,7 +899,8 @@ casts and declarations are fontified. Used on level 2 and higher." (c-get-char-property (1- (point)) 'c-type))))) (when (memq prop '(c-decl-id-start c-decl-type-start)) (c-forward-syntactic-ws limit) - (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)))) + (c-font-lock-declarators limit t (eq prop 'c-decl-type-start) + (c-bs-at-toplevel-p (point))))) (setq c-font-lock-context ;; (c-guess-font-lock-context) (save-excursion @@ -991,7 +992,7 @@ casts and declarations are fontified. Used on level 2 and higher." (goto-char pos))))) nil) -(defun c-font-lock-declarators (limit list types) +(defun c-font-lock-declarators (limit list types not-top) ;; Assuming the point is at the start of a declarator in a declaration, ;; fontify the identifier it declares. (If TYPES is set, it does this via ;; the macro `c-fontify-types-and-refs'.) @@ -1001,7 +1002,9 @@ casts and declarations are fontified. Used on level 2 and higher." ;; additionally, mark the commas with c-type property 'c-decl-id-start or ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT. ;; - ;; If TYPES is non-nil, fontify all identifiers as types. + ;; If TYPES is non-nil, fontify all identifiers as types. If NOT-TOP is + ;; non-nil, we are not at the top-level ("top-level" includes being directly + ;; inside a class or namespace, etc.). ;; ;; Nil is always returned. The function leaves point at the delimiter after ;; the last declarator it processes. @@ -1025,6 +1028,14 @@ casts and declarations are fontified. Used on level 2 and higher." (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))) ; brackets-after-id (or (not (c-major-mode-is 'c++-mode)) (save-excursion @@ -1199,7 +1210,7 @@ casts and declarations are fontified. Used on level 2 and higher." c-decl-start-re (eval c-maybe-decl-faces) - (lambda (match-pos inside-macro) + (lambda (match-pos inside-macro &optional toplev) ;; Note to maintainers: don't use `limit' inside this lambda form; ;; c-find-decl-spots sometimes narrows to less than `limit'. (setq start-pos (point)) @@ -1223,7 +1234,7 @@ casts and declarations are fontified. Used on level 2 and higher." (let ((type (and (> match-pos (point-min)) (c-get-char-property (1- match-pos) 'c-type)))) (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{))) - (setq context nil + (setq context (and toplev 'top) c-restricted-<>-arglists nil)) ;; A control flow expression or a decltype ((and (eq (char-before match-pos) ?\() @@ -1273,7 +1284,7 @@ casts and declarations are fontified. Used on level 2 and higher." 'c-not-decl)) ;; We're inside an "ordinary" open brace. ((eq (char-before match-pos) ?{) - (setq context nil + (setq context (and toplev 'top) c-restricted-<>-arglists nil)) ;; Inside an angle bracket arglist. ((or (eq type 'c-<>-arg-sep) @@ -1411,7 +1422,7 @@ casts and declarations are fontified. Used on level 2 and higher." (goto-char (car decl-or-cast)) (let ((decl-list - (if context + (if (not (memq context '(nil top))) ;; Should normally not fontify a list of ;; declarators inside an arglist, but the first ;; argument in the ';' separated list of a "for" @@ -1437,7 +1448,8 @@ casts and declarations are fontified. Used on level 2 and higher." 'c-decl-id-start))))) (c-font-lock-declarators - (min limit (point-max)) decl-list (cadr decl-or-cast))) + (min limit (point-max)) decl-list + (cadr decl-or-cast) (not toplev))) ;; A declaration has been successfully identified, so do all the ;; fontification of types and refs that've been recorded. @@ -1498,7 +1510,7 @@ casts and declarations are fontified. Used on level 2 and higher." (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) (c-forward-syntactic-ws) - (c-font-lock-declarators limit t nil))) + (c-font-lock-declarators limit t nil t))) nil) (defun c-font-lock-cut-off-declarators (limit) @@ -1512,6 +1524,7 @@ casts and declarations are fontified. Used on level 2 and higher." ;; fontification". (let ((decl-search-lim (c-determine-limit 1000)) paren-state bod-res is-typedef encl-pos + (here (point)) c-recognize-knr-p) ; Strictly speaking, bogus, but it ; speeds up lisp.h tremendously. (save-excursion @@ -1539,7 +1552,8 @@ casts and declarations are fontified. Used on level 2 and higher." (c-forward-syntactic-ws)) ;; At a real declaration? (if (memq (c-forward-type t) '(t known found decltype)) - (c-font-lock-declarators limit t is-typedef))))))) + (c-font-lock-declarators + limit t is-typedef (not (c-bs-at-toplevel-p here))))))))) nil)) (defun c-font-lock-enclosing-decls (limit) @@ -1573,7 +1587,8 @@ casts and declarations are fontified. Used on level 2 and higher." (goto-char ps-elt) (when (c-safe (c-forward-sexp)) (c-forward-syntactic-ws) - (c-font-lock-declarators limit t in-typedef)))))))) + (c-font-lock-declarators limit t in-typedef + (not (c-bs-at-toplevel-p (point))))))))))) (defun c-font-lock-raw-strings (limit) ;; Fontify C++ raw strings. @@ -1741,7 +1756,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." (eval . (list ,(c-make-font-lock-search-function 'c-known-type-key '(1 'font-lock-type-face t) - '((c-font-lock-declarators limit t nil) + '((c-font-lock-declarators limit t nil nil) (save-match-data (goto-char (match-end 1)) (c-forward-syntactic-ws)) @@ -1763,7 +1778,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." "\\)")) `(,type-match 'font-lock-type-face t) - `((c-font-lock-declarators limit t nil) + `((c-font-lock-declarators limit t nil nil) (save-match-data (goto-char (match-end ,type-match)) (c-forward-syntactic-ws)) @@ -1775,7 +1790,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." (concat "\\<\\(" (regexp-opt (c-lang-const c-typeless-decl-kwds)) "\\)\\>") - '((c-font-lock-declarators limit t nil) + '((c-font-lock-declarators limit t nil nil) (save-match-data (goto-char (match-end 1)) (c-forward-syntactic-ws)) @@ -2014,7 +2029,7 @@ higher." ;; before the '{' of the enum list, to avoid searching too far. "[^][{};/#=]*" "{") - '((c-font-lock-declarators limit t nil) + '((c-font-lock-declarators limit t nil t) (save-match-data (goto-char (match-end 0)) (c-put-char-property (1- (point)) 'c-type @@ -2413,7 +2428,7 @@ need for `c++-font-lock-extra-types'.") limit "[-+]" nil - (lambda (match-pos inside-macro) + (lambda (match-pos inside-macro &optional top-level) (forward-char) (c-font-lock-objc-method)))) nil) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index ae6e6a3071..3c328489ec 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -479,10 +479,12 @@ so that all identifiers are recognized as words.") c-before-change-check-<>-operators c-depropertize-CPP c-before-after-change-digit-quote - c-invalidate-macro-cache) + c-invalidate-macro-cache + c-truncate-bs-cache) (c objc) '(c-extend-region-for-CPP c-depropertize-CPP - c-invalidate-macro-cache) + c-invalidate-macro-cache + c-truncate-bs-cache) ;; java 'c-before-change-check-<>-operators awk 'c-awk-record-region-clear-NL) (c-lang-defvar c-get-state-before-change-functions @@ -2588,6 +2590,41 @@ Note that Java specific rules are currently applied to tell this from (c-lang-defvar c-opt-inexpr-brace-list-key (c-lang-const c-opt-inexpr-brace-list-key)) +(c-lang-defconst c-flat-decl-block-kwds + ;; Keywords that can introduce another declaration level, i.e. where a + ;; following "{" isn't a function block or brace list. Note that, for + ;; historical reasons, `c-decl-block-key' is NOT constructed from this lang + ;; const. + t (c--delete-duplicates + (append (c-lang-const c-class-decl-kwds) + (c-lang-const c-other-block-decl-kwds) + (c-lang-const c-inexpr-class-kwds)) + :test 'string-equal)) + +(c-lang-defconst c-brace-stack-thing-key + ;; Regexp matching any keyword or operator relevant to the brace stack (see + ;; `c-update-brace-stack' in cc-engine.el). + t (c-make-keywords-re 'appendable + (append + (c-lang-const c-flat-decl-block-kwds) + (if (c-lang-const c-recognize-<>-arglists) + '("{" "}" ";" "," ")" ":" "<") + '("{" "}" ";" "," ")" ":"))))) +(c-lang-defvar c-brace-stack-thing-key (c-lang-const c-brace-stack-thing-key)) + +(c-lang-defconst c-brace-stack-no-semi-key + ;; Regexp matching any keyword or operator relevant to the brace stack when + ;; a semicolon is not relevant (see `c-update-brace-stack' in + ;; cc-engine.el). + t (c-make-keywords-re 'appendable + (append + (c-lang-const c-flat-decl-block-kwds) + (if (c-lang-const c-recognize-<>-arglists) + '("{" "}" "<") + '("{" "}"))))) +(c-lang-defvar c-brace-stack-no-semi-key + (c-lang-const c-brace-stack-no-semi-key)) + (c-lang-defconst c-decl-block-key ;; Regexp matching keywords in any construct that contain another ;; declaration level, i.e. that isn't followed by a function block @@ -3031,6 +3068,28 @@ Identifier syntax is in effect when this is matched \(see (c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key) 'dont-doc) +(c-lang-defconst c-type-decl-operator-prefix-key + "Regexp matching any declarator operator which isn't a keyword +that might precede the identifier in a declaration, e.g. the +\"*\" in \"char *argv\". The end of the first submatch is taken +as the end of the operator. Identifier syntax is in effect when +this is matched \(see `c-identifier-syntax-table')." + t ;; Default to a regexp that never matches. + "\\<\\>" + ;; Check that there's no "=" afterwards to avoid matching tokens + ;; like "*=". + (c objc) (concat "\\(\\*\\)" + "\\([^=]\\|$\\)") + c++ (concat "\\(" + "\\.\\.\\." + "\\|" + "\\*" + "\\)" + "\\([^=]\\|$\\)") + pike "\\(\\*\\)\\([^=]\\|$\\)") +(c-lang-defvar c-type-decl-operator-prefix-key + (c-lang-const c-type-decl-operator-prefix-key)) + (c-lang-defconst c-type-decl-suffix-key "Regexp matching the declarator operators that might follow after the identifier in a declaration, e.g. the \"[\" in \"char argv[]\". This diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index f2c62563c5..5b0679ac5b 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -557,6 +557,8 @@ that requires a literal mode spec at compile time." ;; Initialize the cache of brace pairs, and opening braces/brackets/parens. (c-state-cache-init) + ;; Initialize the "brace stack" cache. + (c-init-bs-cache) (when (or c-recognize-<>-arglists (c-major-mode-is 'awk-mode) |