aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2016-09-11 21:09:08 +0000
committerAlan Mackenzie2016-09-11 21:09:08 +0000
commitc417f08b16cd9e16451a6d3231097eeb4a804f2d (patch)
tree9590af6fa9497372061c4a41106e05066180cd84
parentf95ca1268da211f5c60985d411df43bb5477430b (diff)
downloademacs-c417f08b16cd9e16451a6d3231097eeb4a804f2d.tar.gz
emacs-c417f08b16cd9e16451a6d3231097eeb4a804f2d.zip
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.el257
-rw-r--r--lisp/progmodes/cc-fonts.el47
-rw-r--r--lisp/progmodes/cc-langs.el63
-rw-r--r--lisp/progmodes/cc-mode.el2
4 files changed, 337 insertions, 32 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 259f8a03b37..a1574b23c5a 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."
5128 (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face) 5128 (c-debug-remove-face ,beg ,end 'c-debug-decl-spot-face)
5129 (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face)))) 5129 (c-debug-remove-face ,beg ,end 'c-debug-decl-sws-face))))
5130 5130
5131;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5132;; Machinery for determining when we're at top level (this including being
5133;; directly inside a class or namespace, etc.)
5134;;
5135;; We maintain a stack of brace depths in structures like classes and
5136;; namespaces. The car of this structure, when non-nil, indicates that the
5137;; associated position is within a template (etc.) structure, and the value is
5138;; the position where the (outermost) template ends. The other elements in
5139;; the structure are stacked elements, one each for each enclosing "top level"
5140;; structure.
5141;;
5142;; At the very outermost level, the value of the stack would be (nil 1), the
5143;; "1" indicating an enclosure in a notional all-enclosing block. After
5144;; passing a keyword such as "namespace", the value would become (nil 0 1).
5145;; At this point, passing a semicolon would cause the 0 to be dropped from the
5146;; stack (at any other time, a semicolon is ignored). Alternatively, on
5147;; passing an opening brace, the stack would become (nil 1 1). Each opening
5148;; brace passed causes the cadr to be incremented, and passing closing braces
5149;; causes it to be decremented until it reaches 1. On passing a closing brace
5150;; when the cadr of the stack is at 1, this causes it to be removed from the
5151;; stack, the corresponding namespace (etc.) structure having been closed.
5152;;
5153;; There is a special stack value -1 which means the C++ colon operator
5154;; introducing a list of inherited classes has just been parsed. The value
5155;; persists on the stack until the next open brace or semicolon.
5156;;
5157;; When the car of the stack is non-nil, i.e. when we're in a template (etc.)
5158;; structure, braces are not counted. The counting resumes only after passing
5159;; the template's closing position, which is recorded in the car of the stack.
5160;;
5161;; The test for being at top level consists of the cadr being 0 or 1.
5162;;
5163;; The values of this stack throughout a buffer are cached in a simple linear
5164;; cache, every 5000 characters.
5165;;
5166;; Note to maintainers: This cache mechanism is MUCH faster than recalculating
5167;; the stack at every entry to `c-find-decl-spots' using `c-at-toplevel-p' or
5168;; the like.
5169;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
5170;; The approximate interval at which we cache the value of the brace stack.
5171(defconst c-bs-interval 5000)
5172;; The list of cached values of the brace stack. Each value in the list is a
5173;; cons of the position it is valid for and the value of the stack as
5174;; described above.
5175(defvar c-bs-cache nil)
5176(make-variable-buffer-local 'c-bs-cache)
5177;; The position of the buffer at and below which entries in `c-bs-cache' are
5178;; valid.
5179(defvar c-bs-cache-limit 1)
5180(make-variable-buffer-local 'c-bs-cache-limit)
5181;; The previous buffer position for which the brace stack value was
5182;; determined.
5183(defvar c-bs-prev-pos most-positive-fixnum)
5184(make-variable-buffer-local 'c-bs-prev-pos)
5185;; The value of the brace stack at `c-bs-prev-pos'.
5186(defvar c-bs-prev-stack nil)
5187(make-variable-buffer-local 'c-bs-prev-stack)
5188
5189(defun c-init-bs-cache ()
5190 ;; Initialize the cache in `c-bs-cache' and related variables.
5191 (setq c-bs-cache nil
5192 c-bs-cache-limit 1
5193 c-bs-prev-pos most-positive-fixnum
5194 c-bs-prev-stack nil))
5195
5196(defun c-truncate-bs-cache (pos &rest _ignore)
5197 ;; Truncate the upper bound of the cache `c-bs-cache' to POS, if it is
5198 ;; higher than that position. This is called as either a before- or
5199 ;; after-change-function.
5200 (setq c-bs-cache-limit
5201 (min c-bs-cache-limit pos)))
5202
5203(defun c-update-brace-stack (stack from to)
5204 ;; Give a brace-stack which has the value STACK at position FROM, update it
5205 ;; to it's value at position TO, where TO is after (or equal to) FROM.
5206 ;; Return a cons of either TO (if it is outside a literal) and this new
5207 ;; value, or of the next position after TO outside a literal and the new
5208 ;; value.
5209 (let (match kwd-sym (prev-match-pos 1)
5210 (s (cdr stack))
5211 (bound-<> (car stack))
5212 )
5213 (save-excursion
5214 (cond
5215 ((and bound-<> (<= to bound-<>))
5216 (goto-char to)) ; Nothing to do.
5217 (bound-<>
5218 (goto-char bound-<>)
5219 (setq bound-<> nil))
5220 (t (goto-char from)))
5221 (while (and (< (point) to)
5222 (c-syntactic-re-search-forward
5223 (if (<= (car s) 0)
5224 c-brace-stack-thing-key
5225 c-brace-stack-no-semi-key)
5226 to 'after-literal)
5227 (> (point) prev-match-pos)) ; prevent infinite loop.
5228 (setq prev-match-pos (point))
5229 (setq match (match-string-no-properties 1)
5230 kwd-sym (c-keyword-sym match))
5231 (cond
5232 ((and (equal match "{")
5233 (progn (backward-char)
5234 (prog1 (looking-at "\\s(")
5235 (forward-char))))
5236 (setq s (if s
5237 (cons (if (<= (car s) 0)
5238 1
5239 (1+ (car s)))
5240 (cdr s))
5241 (list 1))))
5242 ((and (equal match "}")
5243 (progn (backward-char)
5244 (prog1 (looking-at "\\s)")
5245 (forward-char))))
5246 (setq s
5247 (cond
5248 ((and s (> (car s) 1))
5249 (cons (1- (car s)) (cdr s)))
5250 ((and (cdr s) (eq (car s) 1))
5251 (cdr s))
5252 (t s))))
5253 ((and (equal match "<")
5254 (progn (backward-char)
5255 (prog1 (looking-at "\\s(")
5256 (forward-char))))
5257 (backward-char)
5258 (if (c-forward-<>-arglist nil) ; Should always work.
5259 (when (> (point) to)
5260 (setq bound-<> (point)))
5261 (forward-char)))
5262 ((and (equal match ":")
5263 s
5264 (eq (car s) 0))
5265 (setq s (cons -1 (cdr s))))
5266 ((and (equal match ",")
5267 (eq (car s) -1))) ; at "," in "class foo : bar, ..."
5268 ((member match '(";" "," ")"))
5269 (when (and s (cdr s) (<= (car s) 0))
5270 (setq s (cdr s))))
5271 ((c-keyword-member kwd-sym 'c-flat-decl-block-kwds)
5272 (push 0 s))))
5273 (cons (point)
5274 (cons bound-<> s)))))
5275
5276(defun c-brace-stack-at (here)
5277 ;; Given a buffer position HERE, Return the value of the brace stack there.
5278 (save-excursion
5279 (save-restriction
5280 (widen)
5281 (let ((c c-bs-cache)
5282 (can-use-prev (<= c-bs-prev-pos c-bs-cache-limit))
5283 elt stack pos npos high-elt)
5284 ;; Trim the cache to take account of buffer changes.
5285 (while (and c
5286 (> (caar c) c-bs-cache-limit))
5287 (setq c (cdr c)))
5288 (setq c-bs-cache c)
5289
5290 (while (and c
5291 (> (caar c) here))
5292 (setq high-elt (car c))
5293 (setq c (cdr c)))
5294 (setq pos (or (and c (caar c))
5295 (point-min)))
5296
5297 (setq elt (if c
5298 (car c)
5299 (cons (point-min)
5300 (cons nil (list 1)))))
5301 (when (not high-elt)
5302 (setq stack (cdr elt))
5303 (while
5304 ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
5305 (<= (setq npos (+ pos c-bs-interval)) here)
5306 (setq elt (c-update-brace-stack stack pos npos))
5307 (setq npos (car elt))
5308 (setq stack (cdr elt))
5309 (unless (eq npos (point-max)) ; NPOS could be in a literal at EOB.
5310 (setq c-bs-cache (cons elt c-bs-cache)))
5311 (setq pos npos)))
5312
5313 (if (> pos c-bs-cache-limit)
5314 (setq c-bs-cache-limit pos))
5315
5316 ;; Can we just use the previous value?
5317 (if (and can-use-prev
5318 (<= c-bs-prev-pos here)
5319 (> c-bs-prev-pos (car elt)))
5320 (setq pos c-bs-prev-pos
5321 stack c-bs-prev-stack)
5322 (setq pos (car elt)
5323 stack (cdr elt)))
5324 (if (> here c-bs-cache-limit)
5325 (setq c-bs-cache-limit here))
5326 (setq elt (c-update-brace-stack stack pos here)
5327 c-bs-prev-pos (car elt)
5328 c-bs-prev-stack (cdr elt))))))
5329
5330(defun c-bs-at-toplevel-p (here)
5331 ;; Is position HERE at the top level, as indicated by the brace stack?
5332 (let ((stack (c-brace-stack-at here)))
5333 (or (null stack) ; Probably unnecessary.
5334 (<= (cadr stack) 1))))
5335
5131(defmacro c-find-decl-prefix-search () 5336(defmacro c-find-decl-prefix-search ()
5132 ;; Macro used inside `c-find-decl-spots'. It ought to be a defun, 5337 ;; Macro used inside `c-find-decl-spots'. It ought to be a defun,
5133 ;; but it contains lots of free variables that refer to things 5338 ;; 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."
5221 cfd-re-match nil) 5426 cfd-re-match nil)
5222 (setq cfd-match-pos cfd-prop-match 5427 (setq cfd-match-pos cfd-prop-match
5223 cfd-prop-match nil)) 5428 cfd-prop-match nil))
5429 (setq cfd-top-level (c-bs-at-toplevel-p cfd-match-pos))
5224 5430
5225 (goto-char cfd-match-pos) 5431 (goto-char cfd-match-pos)
5226 5432
@@ -5319,7 +5525,11 @@ comment at the start of cc-engine.el for more info."
5319 ;; comments. 5525 ;; comments.
5320 (cfd-token-pos 0) 5526 (cfd-token-pos 0)
5321 ;; The end position of the last entered macro. 5527 ;; The end position of the last entered macro.
5322 (cfd-macro-end 0)) 5528 (cfd-macro-end 0)
5529 ;; Whether the last position returned from `c-find-decl-prefix-search'
5530 ;; is at the top-level (including directly in a class or namespace,
5531 ;; etc.).
5532 cfd-top-level)
5323 5533
5324 ;; Initialize by finding a syntactically relevant start position 5534 ;; Initialize by finding a syntactically relevant start position
5325 ;; before the point, and do the first `c-decl-prefix-or-start-re' 5535 ;; 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."
5627 nil)))) ; end of when condition 5837 nil)))) ; end of when condition
5628 5838
5629 (c-debug-put-decl-spot-faces cfd-match-pos (point)) 5839 (c-debug-put-decl-spot-faces cfd-match-pos (point))
5630 (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0)) 5840 (if (funcall cfd-fun cfd-match-pos (/= cfd-macro-end 0) cfd-top-level)
5631 (setq cfd-prop-match nil)) 5841 (setq cfd-prop-match nil))
5632 5842
5633 (when (/= cfd-macro-end 0) 5843 (when (/= cfd-macro-end 0)
@@ -7552,10 +7762,12 @@ comment at the start of cc-engine.el for more info."
7552 ;; Assuming point is at the start of a declarator, move forward over it, 7762 ;; Assuming point is at the start of a declarator, move forward over it,
7553 ;; leaving point at the next token after it (e.g. a ) or a ; or a ,). 7763 ;; leaving point at the next token after it (e.g. a ) or a ; or a ,).
7554 ;; 7764 ;;
7555 ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT), where ID-START and 7765 ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT DECORATED),
7556 ;; ID-END are the bounds of the declarator's identifier, and 7766 ;; where ID-START and ID-END are the bounds of the declarator's identifier,
7557 ;; BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id. 7767 ;; and BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id.
7558 ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(". 7768 ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(",
7769 ;; DECORATED is non-nil when the identifier is embellished by an operator,
7770 ;; like "*x", or "(*x)".
7559 ;; 7771 ;;
7560 ;; If ACCEPT-ANON is non-nil, move forward over any "anonymous declarator", 7772 ;; If ACCEPT-ANON is non-nil, move forward over any "anonymous declarator",
7561 ;; i.e. something like the (*) in int (*), such as might be found in a 7773 ;; 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."
7574 ;; array/struct initialization) or "=" or terminating delimiter 7786 ;; array/struct initialization) or "=" or terminating delimiter
7575 ;; (e.g. "," or ";" or "}"). 7787 ;; (e.g. "," or ";" or "}").
7576 (let ((here (point)) 7788 (let ((here (point))
7577 id-start id-end brackets-after-id paren-depth) 7789 id-start id-end brackets-after-id paren-depth decorated)
7578 (or limit (setq limit (point-max))) 7790 (or limit (setq limit (point-max)))
7579 (if (and 7791 (if (and
7580 (< (point) limit) 7792 (< (point) limit)
@@ -7614,6 +7826,8 @@ comment at the start of cc-engine.el for more info."
7614 (setq got-identifier t) 7826 (setq got-identifier t)
7615 nil)) 7827 nil))
7616 t)) 7828 t))
7829 (if (looking-at c-type-decl-operator-prefix-key)
7830 (setq decorated t))
7617 (if (eq (char-after) ?\() 7831 (if (eq (char-after) ?\()
7618 (progn 7832 (progn
7619 (setq paren-depth (1+ paren-depth)) 7833 (setq paren-depth (1+ paren-depth))
@@ -7668,7 +7882,7 @@ comment at the start of cc-engine.el for more info."
7668 (setq brackets-after-id t)) 7882 (setq brackets-after-id t))
7669 (backward-char) 7883 (backward-char)
7670 found)) 7884 found))
7671 (list id-start id-end brackets-after-id (match-beginning 1)) 7885 (list id-start id-end brackets-after-id (match-beginning 1) decorated)
7672 7886
7673 (goto-char here) 7887 (goto-char here)
7674 nil))) 7888 nil)))
@@ -7744,6 +7958,9 @@ comment at the start of cc-engine.el for more info."
7744 ;; inside a function declaration arglist). 7958 ;; inside a function declaration arglist).
7745 ;; '<> In an angle bracket arglist. 7959 ;; '<> In an angle bracket arglist.
7746 ;; 'arglist Some other type of arglist. 7960 ;; 'arglist Some other type of arglist.
7961 ;; 'top Some other context and point is at the top-level (either
7962 ;; outside any braces or directly inside a class or namespace,
7963 ;; etc.)
7747 ;; nil Some other context or unknown context. Includes 7964 ;; nil Some other context or unknown context. Includes
7748 ;; within the parens of an if, for, ... construct. 7965 ;; within the parens of an if, for, ... construct.
7749 ;; 'not-decl This value is never supplied to this function. It 7966 ;; '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."
8152 maybe-typeless 8369 maybe-typeless
8153 backup-maybe-typeless 8370 backup-maybe-typeless
8154 (when c-recognize-typeless-decls 8371 (when c-recognize-typeless-decls
8155 (and (not context) 8372 (and (memq context '(nil top))
8156 ;; Deal with C++11's "copy-initialization" 8373 ;; Deal with C++11's "copy-initialization"
8157 ;; where we have <type>(<constant>), by 8374 ;; where we have <type>(<constant>), by
8158 ;; contrasting with a typeless 8375 ;; contrasting with a typeless
@@ -8215,7 +8432,7 @@ comment at the start of cc-engine.el for more info."
8215 8432
8216 (setq at-decl-end 8433 (setq at-decl-end
8217 (looking-at (cond ((eq context '<>) "[,>]") 8434 (looking-at (cond ((eq context '<>) "[,>]")
8218 (context "[,)]") 8435 ((not (memq context '(nil top))) "[,\)]")
8219 (t "[,;]")))) 8436 (t "[,;]"))))
8220 8437
8221 ;; Now we've collected info about various characteristics of 8438 ;; Now we've collected info about various characteristics of
@@ -8344,7 +8561,7 @@ comment at the start of cc-engine.el for more info."
8344 8561
8345 (if (and got-parens 8562 (if (and got-parens
8346 (not got-prefix) 8563 (not got-prefix)
8347 (not context) 8564 (memq context '(nil top))
8348 (not (eq at-type t)) 8565 (not (eq at-type t))
8349 (or backup-at-type 8566 (or backup-at-type
8350 maybe-typeless 8567 maybe-typeless
@@ -8394,6 +8611,18 @@ comment at the start of cc-engine.el for more info."
8394 ;; instantiation expression). 8611 ;; instantiation expression).
8395 (throw 'at-decl-or-cast nil)))) 8612 (throw 'at-decl-or-cast nil))))
8396 8613
8614 ;; CASE 9.5
8615 (when (and (not context) ; i.e. not at top level.
8616 (c-major-mode-is 'c++-mode)
8617 (eq at-decl-or-cast 'ids)
8618 after-paren-pos)
8619 ;; We've got something like "foo bar (...)" in C++ which isn't at
8620 ;; the top level. This is probably a uniform initialization of bar
8621 ;; to the contents of the parens. In this case the declarator ends
8622 ;; at the open paren.
8623 (goto-char (1- after-paren-pos))
8624 (throw 'at-decl-or-cast t))
8625
8397 ;; CASE 10 8626 ;; CASE 10
8398 (when at-decl-or-cast 8627 (when at-decl-or-cast
8399 ;; By now we've located the type in the declaration that we know 8628 ;; 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."
8402 8631
8403 ;; CASE 11 8632 ;; CASE 11
8404 (when (and got-identifier 8633 (when (and got-identifier
8405 (not context) 8634 (memq context '(nil top))
8406 (looking-at c-after-suffixed-type-decl-key) 8635 (looking-at c-after-suffixed-type-decl-key)
8407 (if (and got-parens 8636 (if (and got-parens
8408 (not got-prefix) 8637 (not got-prefix)
@@ -8498,7 +8727,7 @@ comment at the start of cc-engine.el for more info."
8498 (when (and got-prefix-before-parens 8727 (when (and got-prefix-before-parens
8499 at-type 8728 at-type
8500 (or at-decl-end (looking-at "=[^=]")) 8729 (or at-decl-end (looking-at "=[^=]"))
8501 (not context) 8730 (memq context '(nil top))
8502 (or (not got-suffix) 8731 (or (not got-suffix)
8503 at-decl-start)) 8732 at-decl-start))
8504 ;; Got something like "foo * bar;". Since we're not inside 8733 ;; 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."
8524 (throw 'at-decl-or-cast t))) 8753 (throw 'at-decl-or-cast t)))
8525 8754
8526 ;; CASE 18 8755 ;; CASE 18
8527 (when (and context 8756 (when (and (not (memq context '(nil top)))
8528 (or got-prefix 8757 (or got-prefix
8529 (and (eq context 'decl) 8758 (and (eq context 'decl)
8530 (not c-recognize-paren-inits) 8759 (not c-recognize-paren-inits)
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 735108ff7dc..26a002ac8a1 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."
899 (c-get-char-property (1- (point)) 'c-type))))) 899 (c-get-char-property (1- (point)) 'c-type)))))
900 (when (memq prop '(c-decl-id-start c-decl-type-start)) 900 (when (memq prop '(c-decl-id-start c-decl-type-start))
901 (c-forward-syntactic-ws limit) 901 (c-forward-syntactic-ws limit)
902 (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)))) 902 (c-font-lock-declarators limit t (eq prop 'c-decl-type-start)
903 (c-bs-at-toplevel-p (point)))))
903 904
904 (setq c-font-lock-context ;; (c-guess-font-lock-context) 905 (setq c-font-lock-context ;; (c-guess-font-lock-context)
905 (save-excursion 906 (save-excursion
@@ -991,7 +992,7 @@ casts and declarations are fontified. Used on level 2 and higher."
991 (goto-char pos))))) 992 (goto-char pos)))))
992 nil) 993 nil)
993 994
994(defun c-font-lock-declarators (limit list types) 995(defun c-font-lock-declarators (limit list types not-top)
995 ;; Assuming the point is at the start of a declarator in a declaration, 996 ;; Assuming the point is at the start of a declarator in a declaration,
996 ;; fontify the identifier it declares. (If TYPES is set, it does this via 997 ;; fontify the identifier it declares. (If TYPES is set, it does this via
997 ;; the macro `c-fontify-types-and-refs'.) 998 ;; the macro `c-fontify-types-and-refs'.)
@@ -1001,7 +1002,9 @@ casts and declarations are fontified. Used on level 2 and higher."
1001 ;; additionally, mark the commas with c-type property 'c-decl-id-start or 1002 ;; additionally, mark the commas with c-type property 'c-decl-id-start or
1002 ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT. 1003 ;; 'c-decl-type-start (according to TYPES). Stop at LIMIT.
1003 ;; 1004 ;;
1004 ;; If TYPES is non-nil, fontify all identifiers as types. 1005 ;; If TYPES is non-nil, fontify all identifiers as types. If NOT-TOP is
1006 ;; non-nil, we are not at the top-level ("top-level" includes being directly
1007 ;; inside a class or namespace, etc.).
1005 ;; 1008 ;;
1006 ;; Nil is always returned. The function leaves point at the delimiter after 1009 ;; Nil is always returned. The function leaves point at the delimiter after
1007 ;; the last declarator it processes. 1010 ;; the last declarator it processes.
@@ -1025,6 +1028,14 @@ casts and declarations are fontified. Used on level 2 and higher."
1025 (setq next-pos (point) 1028 (setq next-pos (point)
1026 id-start (car decl-res) 1029 id-start (car decl-res)
1027 id-face (if (and (eq (char-after) ?\() 1030 id-face (if (and (eq (char-after) ?\()
1031 (or (not (c-major-mode-is 'c++-mode))
1032 (not not-top)
1033 (car (cddr (cddr decl-res))) ; Id is in
1034 ; parens, etc.
1035 (save-excursion
1036 (forward-char)
1037 (c-forward-syntactic-ws)
1038 (looking-at "[*&]")))
1028 (not (car (cddr decl-res))) ; brackets-after-id 1039 (not (car (cddr decl-res))) ; brackets-after-id
1029 (or (not (c-major-mode-is 'c++-mode)) 1040 (or (not (c-major-mode-is 'c++-mode))
1030 (save-excursion 1041 (save-excursion
@@ -1199,7 +1210,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1199 c-decl-start-re 1210 c-decl-start-re
1200 (eval c-maybe-decl-faces) 1211 (eval c-maybe-decl-faces)
1201 1212
1202 (lambda (match-pos inside-macro) 1213 (lambda (match-pos inside-macro &optional toplev)
1203 ;; Note to maintainers: don't use `limit' inside this lambda form; 1214 ;; Note to maintainers: don't use `limit' inside this lambda form;
1204 ;; c-find-decl-spots sometimes narrows to less than `limit'. 1215 ;; c-find-decl-spots sometimes narrows to less than `limit'.
1205 (setq start-pos (point)) 1216 (setq start-pos (point))
@@ -1223,7 +1234,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1223 (let ((type (and (> match-pos (point-min)) 1234 (let ((type (and (> match-pos (point-min))
1224 (c-get-char-property (1- match-pos) 'c-type)))) 1235 (c-get-char-property (1- match-pos) 'c-type))))
1225 (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{))) 1236 (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{)))
1226 (setq context nil 1237 (setq context (and toplev 'top)
1227 c-restricted-<>-arglists nil)) 1238 c-restricted-<>-arglists nil))
1228 ;; A control flow expression or a decltype 1239 ;; A control flow expression or a decltype
1229 ((and (eq (char-before match-pos) ?\() 1240 ((and (eq (char-before match-pos) ?\()
@@ -1273,7 +1284,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1273 'c-not-decl)) 1284 'c-not-decl))
1274 ;; We're inside an "ordinary" open brace. 1285 ;; We're inside an "ordinary" open brace.
1275 ((eq (char-before match-pos) ?{) 1286 ((eq (char-before match-pos) ?{)
1276 (setq context nil 1287 (setq context (and toplev 'top)
1277 c-restricted-<>-arglists nil)) 1288 c-restricted-<>-arglists nil))
1278 ;; Inside an angle bracket arglist. 1289 ;; Inside an angle bracket arglist.
1279 ((or (eq type 'c-<>-arg-sep) 1290 ((or (eq type 'c-<>-arg-sep)
@@ -1411,7 +1422,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1411 (goto-char (car decl-or-cast)) 1422 (goto-char (car decl-or-cast))
1412 1423
1413 (let ((decl-list 1424 (let ((decl-list
1414 (if context 1425 (if (not (memq context '(nil top)))
1415 ;; Should normally not fontify a list of 1426 ;; Should normally not fontify a list of
1416 ;; declarators inside an arglist, but the first 1427 ;; declarators inside an arglist, but the first
1417 ;; argument in the ';' separated list of a "for" 1428 ;; argument in the ';' separated list of a "for"
@@ -1437,7 +1448,8 @@ casts and declarations are fontified. Used on level 2 and higher."
1437 'c-decl-id-start))))) 1448 'c-decl-id-start)))))
1438 1449
1439 (c-font-lock-declarators 1450 (c-font-lock-declarators
1440 (min limit (point-max)) decl-list (cadr decl-or-cast))) 1451 (min limit (point-max)) decl-list
1452 (cadr decl-or-cast) (not toplev)))
1441 1453
1442 ;; A declaration has been successfully identified, so do all the 1454 ;; A declaration has been successfully identified, so do all the
1443 ;; fontification of types and refs that've been recorded. 1455 ;; fontification of types and refs that've been recorded.
@@ -1498,7 +1510,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1498 (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) 1510 (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start)
1499 1511
1500 (c-forward-syntactic-ws) 1512 (c-forward-syntactic-ws)
1501 (c-font-lock-declarators limit t nil))) 1513 (c-font-lock-declarators limit t nil t)))
1502 nil) 1514 nil)
1503 1515
1504(defun c-font-lock-cut-off-declarators (limit) 1516(defun c-font-lock-cut-off-declarators (limit)
@@ -1512,6 +1524,7 @@ casts and declarations are fontified. Used on level 2 and higher."
1512 ;; fontification". 1524 ;; fontification".
1513 (let ((decl-search-lim (c-determine-limit 1000)) 1525 (let ((decl-search-lim (c-determine-limit 1000))
1514 paren-state bod-res is-typedef encl-pos 1526 paren-state bod-res is-typedef encl-pos
1527 (here (point))
1515 c-recognize-knr-p) ; Strictly speaking, bogus, but it 1528 c-recognize-knr-p) ; Strictly speaking, bogus, but it
1516 ; speeds up lisp.h tremendously. 1529 ; speeds up lisp.h tremendously.
1517 (save-excursion 1530 (save-excursion
@@ -1539,7 +1552,8 @@ casts and declarations are fontified. Used on level 2 and higher."
1539 (c-forward-syntactic-ws)) 1552 (c-forward-syntactic-ws))
1540 ;; At a real declaration? 1553 ;; At a real declaration?
1541 (if (memq (c-forward-type t) '(t known found decltype)) 1554 (if (memq (c-forward-type t) '(t known found decltype))
1542 (c-font-lock-declarators limit t is-typedef))))))) 1555 (c-font-lock-declarators
1556 limit t is-typedef (not (c-bs-at-toplevel-p here)))))))))
1543 nil)) 1557 nil))
1544 1558
1545(defun c-font-lock-enclosing-decls (limit) 1559(defun c-font-lock-enclosing-decls (limit)
@@ -1573,7 +1587,8 @@ casts and declarations are fontified. Used on level 2 and higher."
1573 (goto-char ps-elt) 1587 (goto-char ps-elt)
1574 (when (c-safe (c-forward-sexp)) 1588 (when (c-safe (c-forward-sexp))
1575 (c-forward-syntactic-ws) 1589 (c-forward-syntactic-ws)
1576 (c-font-lock-declarators limit t in-typedef)))))))) 1590 (c-font-lock-declarators limit t in-typedef
1591 (not (c-bs-at-toplevel-p (point)))))))))))
1577 1592
1578(defun c-font-lock-raw-strings (limit) 1593(defun c-font-lock-raw-strings (limit)
1579 ;; Fontify C++ raw strings. 1594 ;; Fontify C++ raw strings.
@@ -1741,7 +1756,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
1741 (eval . (list ,(c-make-font-lock-search-function 1756 (eval . (list ,(c-make-font-lock-search-function
1742 'c-known-type-key 1757 'c-known-type-key
1743 '(1 'font-lock-type-face t) 1758 '(1 'font-lock-type-face t)
1744 '((c-font-lock-declarators limit t nil) 1759 '((c-font-lock-declarators limit t nil nil)
1745 (save-match-data 1760 (save-match-data
1746 (goto-char (match-end 1)) 1761 (goto-char (match-end 1))
1747 (c-forward-syntactic-ws)) 1762 (c-forward-syntactic-ws))
@@ -1763,7 +1778,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
1763 "\\)")) 1778 "\\)"))
1764 `(,type-match 1779 `(,type-match
1765 'font-lock-type-face t) 1780 'font-lock-type-face t)
1766 `((c-font-lock-declarators limit t nil) 1781 `((c-font-lock-declarators limit t nil nil)
1767 (save-match-data 1782 (save-match-data
1768 (goto-char (match-end ,type-match)) 1783 (goto-char (match-end ,type-match))
1769 (c-forward-syntactic-ws)) 1784 (c-forward-syntactic-ws))
@@ -1775,7 +1790,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
1775 (concat "\\<\\(" 1790 (concat "\\<\\("
1776 (regexp-opt (c-lang-const c-typeless-decl-kwds)) 1791 (regexp-opt (c-lang-const c-typeless-decl-kwds))
1777 "\\)\\>") 1792 "\\)\\>")
1778 '((c-font-lock-declarators limit t nil) 1793 '((c-font-lock-declarators limit t nil nil)
1779 (save-match-data 1794 (save-match-data
1780 (goto-char (match-end 1)) 1795 (goto-char (match-end 1))
1781 (c-forward-syntactic-ws)) 1796 (c-forward-syntactic-ws))
@@ -2014,7 +2029,7 @@ higher."
2014 ;; before the '{' of the enum list, to avoid searching too far. 2029 ;; before the '{' of the enum list, to avoid searching too far.
2015 "[^][{};/#=]*" 2030 "[^][{};/#=]*"
2016 "{") 2031 "{")
2017 '((c-font-lock-declarators limit t nil) 2032 '((c-font-lock-declarators limit t nil t)
2018 (save-match-data 2033 (save-match-data
2019 (goto-char (match-end 0)) 2034 (goto-char (match-end 0))
2020 (c-put-char-property (1- (point)) 'c-type 2035 (c-put-char-property (1- (point)) 'c-type
@@ -2413,7 +2428,7 @@ need for `c++-font-lock-extra-types'.")
2413 limit 2428 limit
2414 "[-+]" 2429 "[-+]"
2415 nil 2430 nil
2416 (lambda (match-pos inside-macro) 2431 (lambda (match-pos inside-macro &optional top-level)
2417 (forward-char) 2432 (forward-char)
2418 (c-font-lock-objc-method)))) 2433 (c-font-lock-objc-method))))
2419 nil) 2434 nil)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index ae6e6a3071f..3c328489ec1 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.")
479 c-before-change-check-<>-operators 479 c-before-change-check-<>-operators
480 c-depropertize-CPP 480 c-depropertize-CPP
481 c-before-after-change-digit-quote 481 c-before-after-change-digit-quote
482 c-invalidate-macro-cache) 482 c-invalidate-macro-cache
483 c-truncate-bs-cache)
483 (c objc) '(c-extend-region-for-CPP 484 (c objc) '(c-extend-region-for-CPP
484 c-depropertize-CPP 485 c-depropertize-CPP
485 c-invalidate-macro-cache) 486 c-invalidate-macro-cache
487 c-truncate-bs-cache)
486 ;; java 'c-before-change-check-<>-operators 488 ;; java 'c-before-change-check-<>-operators
487 awk 'c-awk-record-region-clear-NL) 489 awk 'c-awk-record-region-clear-NL)
488(c-lang-defvar c-get-state-before-change-functions 490(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
2588(c-lang-defvar c-opt-inexpr-brace-list-key 2590(c-lang-defvar c-opt-inexpr-brace-list-key
2589 (c-lang-const c-opt-inexpr-brace-list-key)) 2591 (c-lang-const c-opt-inexpr-brace-list-key))
2590 2592
2593(c-lang-defconst c-flat-decl-block-kwds
2594 ;; Keywords that can introduce another declaration level, i.e. where a
2595 ;; following "{" isn't a function block or brace list. Note that, for
2596 ;; historical reasons, `c-decl-block-key' is NOT constructed from this lang
2597 ;; const.
2598 t (c--delete-duplicates
2599 (append (c-lang-const c-class-decl-kwds)
2600 (c-lang-const c-other-block-decl-kwds)
2601 (c-lang-const c-inexpr-class-kwds))
2602 :test 'string-equal))
2603
2604(c-lang-defconst c-brace-stack-thing-key
2605 ;; Regexp matching any keyword or operator relevant to the brace stack (see
2606 ;; `c-update-brace-stack' in cc-engine.el).
2607 t (c-make-keywords-re 'appendable
2608 (append
2609 (c-lang-const c-flat-decl-block-kwds)
2610 (if (c-lang-const c-recognize-<>-arglists)
2611 '("{" "}" ";" "," ")" ":" "<")
2612 '("{" "}" ";" "," ")" ":")))))
2613(c-lang-defvar c-brace-stack-thing-key (c-lang-const c-brace-stack-thing-key))
2614
2615(c-lang-defconst c-brace-stack-no-semi-key
2616 ;; Regexp matching any keyword or operator relevant to the brace stack when
2617 ;; a semicolon is not relevant (see `c-update-brace-stack' in
2618 ;; cc-engine.el).
2619 t (c-make-keywords-re 'appendable
2620 (append
2621 (c-lang-const c-flat-decl-block-kwds)
2622 (if (c-lang-const c-recognize-<>-arglists)
2623 '("{" "}" "<")
2624 '("{" "}")))))
2625(c-lang-defvar c-brace-stack-no-semi-key
2626 (c-lang-const c-brace-stack-no-semi-key))
2627
2591(c-lang-defconst c-decl-block-key 2628(c-lang-defconst c-decl-block-key
2592 ;; Regexp matching keywords in any construct that contain another 2629 ;; Regexp matching keywords in any construct that contain another
2593 ;; declaration level, i.e. that isn't followed by a function block 2630 ;; 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
3031(c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key) 3068(c-lang-defvar c-type-decl-prefix-key (c-lang-const c-type-decl-prefix-key)
3032 'dont-doc) 3069 'dont-doc)
3033 3070
3071(c-lang-defconst c-type-decl-operator-prefix-key
3072 "Regexp matching any declarator operator which isn't a keyword
3073that might precede the identifier in a declaration, e.g. the
3074\"*\" in \"char *argv\". The end of the first submatch is taken
3075as the end of the operator. Identifier syntax is in effect when
3076this is matched \(see `c-identifier-syntax-table')."
3077 t ;; Default to a regexp that never matches.
3078 "\\<\\>"
3079 ;; Check that there's no "=" afterwards to avoid matching tokens
3080 ;; like "*=".
3081 (c objc) (concat "\\(\\*\\)"
3082 "\\([^=]\\|$\\)")
3083 c++ (concat "\\("
3084 "\\.\\.\\."
3085 "\\|"
3086 "\\*"
3087 "\\)"
3088 "\\([^=]\\|$\\)")
3089 pike "\\(\\*\\)\\([^=]\\|$\\)")
3090(c-lang-defvar c-type-decl-operator-prefix-key
3091 (c-lang-const c-type-decl-operator-prefix-key))
3092
3034(c-lang-defconst c-type-decl-suffix-key 3093(c-lang-defconst c-type-decl-suffix-key
3035 "Regexp matching the declarator operators that might follow after the 3094 "Regexp matching the declarator operators that might follow after the
3036identifier in a declaration, e.g. the \"[\" in \"char argv[]\". This 3095identifier 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 f2c62563c5f..5b0679ac5b2 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."
557 557
558 ;; Initialize the cache of brace pairs, and opening braces/brackets/parens. 558 ;; Initialize the cache of brace pairs, and opening braces/brackets/parens.
559 (c-state-cache-init) 559 (c-state-cache-init)
560 ;; Initialize the "brace stack" cache.
561 (c-init-bs-cache)
560 562
561 (when (or c-recognize-<>-arglists 563 (when (or c-recognize-<>-arglists
562 (c-major-mode-is 'awk-mode) 564 (c-major-mode-is 'awk-mode)