diff options
Diffstat (limited to 'lisp/progmodes/cc-engine.el')
-rw-r--r-- | lisp/progmodes/cc-engine.el | 1507 |
1 files changed, 836 insertions, 671 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 3e14dd18397..9a6e975dd93 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -147,18 +147,19 @@ (cc-require-when-compile 'cc-langs) (cc-require 'cc-vars) +(eval-when-compile (require 'cl)) + ;; Make declarations for all the `c-lang-defvar' variables in cc-langs. (defmacro c-declare-lang-variables () `(progn - ,@(apply 'nconc - (mapcar (lambda (init) - `(,(if (elt init 2) - `(defvar ,(car init) nil ,(elt init 2)) - `(defvar ,(car init) nil)) - (make-variable-buffer-local ',(car init)))) - (cdr c-lang-variable-inits))))) + ,@(mapcan (lambda (init) + `(,(if (elt init 2) + `(defvar ,(car init) nil ,(elt init 2)) + `(defvar ,(car init) nil)) + (make-variable-buffer-local ',(car init)))) + (cdr c-lang-variable-inits)))) (c-declare-lang-variables) @@ -533,7 +534,7 @@ comment at the start of cc-engine.el for more info." (while (progn (when (eq (get-text-property (point) 'c-type) value) (c-clear-char-property (point) 'c-type)) - (goto-char (next-single-property-change (point) 'c-type nil to)) + (goto-char (c-next-single-property-change (point) 'c-type nil to)) (< (point) to))))) @@ -845,7 +846,6 @@ comment at the start of cc-engine.el for more info." ;; Record this as the first token if not starting inside it. (setq tok start)) - ;; The following while loop goes back one sexp (balanced parens, ;; etc. with contents, or symbol or suchlike) each iteration. This ;; movement is accomplished with a call to c-backward-sexp approx 170 @@ -1052,7 +1052,10 @@ comment at the start of cc-engine.el for more info." ;; Just gone back over a brace block? ((and (eq (char-after) ?{) - (not (c-looking-at-inexpr-block lim nil t))) + (not (c-looking-at-inexpr-block lim nil t)) + (save-excursion + (c-backward-token-2 1 t nil) + (not (looking-at "=\\([^=]\\|$\\)")))) (save-excursion (c-forward-sexp) (point))) ;; Just gone back over some paren block? @@ -1720,7 +1723,7 @@ comment at the start of cc-engine.el for more info." ;; the cases when the marked rung is complete. ;; (`next-single-property-change' is certain to move at least one ;; step forward.) - (setq rung-pos (1- (next-single-property-change + (setq rung-pos (1- (c-next-single-property-change rung-is-marked 'c-is-sws nil rung-end-pos))) ;; Got no marked rung here. Since the simple ws might have started ;; inside a line comment or cpp directive we must set `rung-pos' as @@ -1736,7 +1739,7 @@ comment at the start of cc-engine.el for more info." ;; The following search is the main reason that `c-in-sws' ;; and `c-is-sws' aren't combined to one property. - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-in-sws nil (point-max))) (unless (get-text-property (point) 'c-is-sws) ;; If the `c-in-sws' region extended past the last @@ -1858,7 +1861,7 @@ comment at the start of cc-engine.el for more info." ;; possible since we can't be in the ending ws of a line comment or ;; cpp directive now. (if (setq rung-is-marked next-rung-is-marked) - (setq rung-pos (1- (next-single-property-change + (setq rung-pos (1- (c-next-single-property-change rung-is-marked 'c-is-sws nil rung-end-pos))) (setq rung-pos next-rung-pos)) (setq safe-start t))) @@ -1936,7 +1939,7 @@ comment at the start of cc-engine.el for more info." (unless (get-text-property (point) 'c-is-sws) ;; If the `c-in-sws' region extended past the first ;; `c-is-sws' char we have to go forward a bit. - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-is-sws))) (c-debug-sws-msg @@ -2175,7 +2178,6 @@ comment at the start of cc-engine.el for more info." ;; the middle of the desert, as long as it is not within a brace pair ;; recorded in `c-state-cache' or a paren/bracket pair. - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; We maintain a simple cache of positions which aren't in a literal, so as to ;; speed up testing for non-literality. @@ -2545,7 +2547,7 @@ comment at the start of cc-engine.el for more info." (setq pos here+) (c-safe (while - (setq ren+1 (scan-lists pos 1 1)) ; might signal + (setq ren+1 (c-sc-scan-lists pos 1 1)) ; might signal (setq lonely-rens (cons ren+1 lonely-rens) pos ren+1))))) @@ -2557,7 +2559,7 @@ comment at the start of cc-engine.el for more info." (c-safe (while (and lonely-rens ; actual values aren't used. - (setq pa (scan-lists pos -1 1))) + (setq pa (c-sc-scan-lists pos -1 1))) (setq pos pa) (setq lonely-rens (cdr lonely-rens))))) pos)) @@ -2713,8 +2715,8 @@ comment at the start of cc-engine.el for more info." (progn (c-safe (while - (and (setq ce (scan-lists bra -1 -1)) ; back past )/]/}; might signal - (setq bra (scan-lists ce -1 1)) ; back past (/[/{; might signal + (and (setq ce (c-sc-scan-lists bra -1 -1)) ; back past )/]/}; might signal + (setq bra (c-sc-scan-lists ce -1 1)) ; back past (/[/{; might signal (or (> bra here) ;(> ce here) (and (< ce here) @@ -2766,7 +2768,7 @@ comment at the start of cc-engine.el for more info." (not (c-beginning-of-macro)))) (setq c-state-cache (cons (cons (1- bra+1) - (scan-lists bra+1 1 1)) + (c-sc-scan-lists bra+1 1 1)) (if (consp (car c-state-cache)) (cdr c-state-cache) c-state-cache))) @@ -2795,7 +2797,7 @@ comment at the start of cc-engine.el for more info." paren+1 ; Pos after some opening or closing paren. paren+1s ; A list of `paren+1's; used to determine a ; good-pos. - bra+1 ce+1 ; just after L/R bra-ces. + bra+1 ; just after L bra-ce. bra+1s ; list of OLD values of bra+1. mstart) ; start of a macro. @@ -2816,9 +2818,9 @@ comment at the start of cc-engine.el for more info." ;; are no more b/b/p's to scan. (c-safe (while t - (setq pa+1 (scan-lists ren+1 1 -1) ; Into (/{/[; might signal + (setq pa+1 (c-sc-scan-lists ren+1 1 -1) ; Into (/{/[; might signal paren+1s (cons pa+1 paren+1s)) - (setq ren+1 (scan-lists pa+1 1 1)) ; Out of )/}/]; might signal + (setq ren+1 (c-sc-scan-lists pa+1 1 1)) ; Out of )/}/]; might signal (if (and (eq (char-before pa+1) ?{)) ; Check for a macro later. (setq bra+1 pa+1)) (setcar paren+1s ren+1))) @@ -2842,7 +2844,7 @@ comment at the start of cc-engine.el for more info." ;; finished - we just need to check for having found an ;; unmatched )/}/], which we ignore. Such a )/}/] can't be in a ;; macro, due the action of `c-neutralize-syntax-in-CPP'. - (c-safe (setq ren+1 (scan-lists ren+1 1 1)))))) ; acts as loop control. + (c-safe (setq ren+1 (c-sc-scan-lists ren+1 1 1)))))) ; acts as loop control. ;; Record the final, innermost, brace-pair if there is one. (c-state-push-any-brace-pair bra+1 macro-start-or-here) @@ -2945,7 +2947,7 @@ comment at the start of cc-engine.el for more info." ;; The next loop jumps forward out of a nested level of parens each ;; time round; the corresponding elements in `c-state-cache' are ;; removed. `pos' is just after the brace-pair or the open paren at - ;; (car c-state-cache). There can be no open parens/braces/brackets + ;; (car c-state-cache). There can be no open parens/braces/brackets ;; between `start-point'/`start-point-actual-macro-start' and HERE, ;; due to the interface spec to this function. (setq pos (if (and start-point-actual-macro-end @@ -2969,7 +2971,7 @@ comment at the start of cc-engine.el for more info." ;; Scan! (setq pps-state - (parse-partial-sexp + (c-sc-parse-partial-sexp (point) (if (< (point) pps-point) pps-point here) target-depth nil pps-state)) @@ -3000,9 +3002,10 @@ comment at the start of cc-engine.el for more info." ))) (if (< (point) pps-point) - (setq pps-state (parse-partial-sexp (point) pps-point - nil nil ; TARGETDEPTH, STOPBEFORE - pps-state))) + (setq pps-state (c-sc-parse-partial-sexp + (point) pps-point + nil nil ; TARGETDEPTH, STOPBEFORE + pps-state))) ;; If the last paren pair we moved out of was actually a brace pair, ;; insert it into `c-state-cache'. @@ -3123,12 +3126,15 @@ comment at the start of cc-engine.el for more info." (save-restriction (narrow-to-region here-bol (point-max)) (setq pos here-lit-start) - (c-safe (while (setq pa (scan-lists pos -1 1)) + (c-safe (while (setq pa (c-sc-scan-lists pos -1 1)) (setq pos pa)))) ; might signal nil)) ; for the cond - ((setq ren (c-safe-scan-lists pos -1 -1 too-far-back)) - ;; CASE 3: After a }/)/] before `here''s BOL. + ((save-restriction + (narrow-to-region too-far-back (point-max)) + (setq ren (c-safe (c-sc-scan-lists pos -1 -1)))) + + ;; CASE 3: After a }/)/] before `here''s BOL. (list (1+ ren) (and dropped-cons pos) nil)) ; Return value (t @@ -3311,7 +3317,7 @@ comment at the start of cc-engine.el for more info." (setq res (c-remove-stale-state-cache start-point here here-bopl)) (setq cache-pos (car res) scan-backward-pos (cadr res) - cons-separated (car (cddr res)) + cons-separated (car (cddr res)) bopl-state (cadr (cddr res))) ; will be nil if (< here-bopl ; start-point) (if (and scan-backward-pos @@ -3350,15 +3356,19 @@ comment at the start of cc-engine.el for more info." ;; of all parens in preprocessor constructs, except for any such construct ;; containing point. We can then call `c-invalidate-state-cache-1' without ;; worrying further about macros and template delimiters. - (c-with-<->-as-parens-suppressed - (if (and c-state-old-cpp-beg - (< c-state-old-cpp-beg here)) - (c-with-all-but-one-cpps-commented-out - c-state-old-cpp-beg - (min c-state-old-cpp-end here) - (c-invalidate-state-cache-1 here)) - (c-with-cpps-commented-out - (c-invalidate-state-cache-1 here))))) + (if (eval-when-compile (memq 'category-properties c-emacs-features)) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and c-state-old-cpp-beg + (< c-state-old-cpp-beg here)) + (c-with-all-but-one-cpps-commented-out + c-state-old-cpp-beg + (min c-state-old-cpp-end here) + (c-invalidate-state-cache-1 here)) + (c-with-cpps-commented-out + (c-invalidate-state-cache-1 here)))) + ;; XEmacs + (c-invalidate-state-cache-1 here))) (defmacro c-state-maybe-marker (place marker) ;; If PLACE is non-nil, return a marker marking it, otherwise nil. @@ -3386,13 +3396,17 @@ comment at the start of cc-engine.el for more info." ;; FIXME!!! Put in a `condition-case' here to protect the integrity of the ;; subsystem. (prog1 - (c-with-<->-as-parens-suppressed - (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) - (c-with-all-but-one-cpps-commented-out - here-cpp-beg here-cpp-end - (c-parse-state-1)) - (c-with-cpps-commented-out - (c-parse-state-1)))) + (if (eval-when-compile (memq 'category-properties c-emacs-features)) + ;; Emacs + (c-with-<->-as-parens-suppressed + (if (and here-cpp-beg (> here-cpp-end here-cpp-beg)) + (c-with-all-but-one-cpps-commented-out + here-cpp-beg here-cpp-end + (c-parse-state-1)) + (c-with-cpps-commented-out + (c-parse-state-1)))) + ;; XEmacs + (c-parse-state-1)) (setq c-state-old-cpp-beg (c-state-maybe-marker here-cpp-beg c-state-old-cpp-beg-marker) c-state-old-cpp-end @@ -3407,6 +3421,7 @@ comment at the start of cc-engine.el for more info." (defvar c-parse-state-point nil) (defvar c-parse-state-state nil) +(make-variable-buffer-local 'c-parse-state-state) (defun c-record-parse-state-state () (setq c-parse-state-point (point)) (setq c-parse-state-state @@ -3414,9 +3429,9 @@ comment at the start of cc-engine.el for more info." (lambda (arg) (let ((val (symbol-value arg))) (cons arg - (if (consp val) - (copy-tree val) - val)))) + (cond ((consp val) (copy-tree val)) + ((markerp val) (copy-marker val)) + (t val))))) '(c-state-cache c-state-cache-good-pos c-state-nonlit-pos-cache @@ -3436,7 +3451,11 @@ comment at the start of cc-engine.el for more info." (concat "(setq " (mapconcat (lambda (arg) - (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg))) + (format "%s %s%s" (car arg) + (if (atom (cdr arg)) "" "'") + (if (markerp (cdr arg)) + (format "(copy-marker %s)" (marker-position (cdr arg))) + (cdr arg)))) c-parse-state-state " ") ")"))) @@ -4181,7 +4200,7 @@ comment at the start of cc-engine.el for more info." ;; Use `parse-partial-sexp' from a safe position down to the point to check ;; if it's outside comments and strings. (save-excursion - (let ((pos (point)) safe-pos state pps-end-pos) + (let ((pos (point)) safe-pos state) ;; Pick a safe position as close to the point as possible. ;; ;; FIXME: Consult `syntax-ppss' here if our cache doesn't give a good @@ -4263,16 +4282,18 @@ comment at the start of cc-engine.el for more info." ;; loops when it hasn't succeeded. (while (and - (< (skip-chars-backward skip-chars limit) 0) + (let ((pos (point))) + (while (and + (< (skip-chars-backward skip-chars limit) 0) + ;; Don't stop inside a literal. + (when (setq lit-beg (c-ssb-lit-begin)) + (goto-char lit-beg) + t))) + (< (point) pos)) (let ((pos (point)) state-2 pps-end-pos) (cond - ;; Don't stop inside a literal - ((setq lit-beg (c-ssb-lit-begin)) - (goto-char lit-beg) - t) - ((and paren-level (save-excursion (setq state-2 (parse-partial-sexp @@ -4778,7 +4799,7 @@ comment at the start of cc-engine.el for more info." (unless cfd-prop-match (save-excursion (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'c-type nil cfd-limit)) (and (< (point) cfd-limit) (not (eq (c-get-char-property (1- (point)) 'c-type) @@ -4818,7 +4839,7 @@ comment at the start of cc-engine.el for more info." ;; Pseudo match inside a comment or string literal. Skip out ;; of comments and string literals. (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'face nil cfd-limit)) (and (< (point) cfd-limit) (c-got-face-at (point) c-literal-faces)))) @@ -4873,14 +4894,17 @@ comment at the start of cc-engine.el for more info." ;; it should return non-nil to ensure that the next search will find them. ;; ;; Such a spot is: - ;; o The first token after bob. - ;; o The first token after the end of submatch 1 in - ;; `c-decl-prefix-or-start-re' when that submatch matches. - ;; o The start of each `c-decl-prefix-or-start-re' match when - ;; submatch 1 doesn't match. - ;; o The first token after the end of each occurrence of the - ;; `c-type' text property with the value `c-decl-end', provided - ;; `c-type-decl-end-used' is set. + ;; o The first token after bob. + ;; o The first token after the end of submatch 1 in + ;; `c-decl-prefix-or-start-re' when that submatch matches. This + ;; submatch is typically a (L or R) brace or paren, a ;, or a ,. + ;; o The start of each `c-decl-prefix-or-start-re' match when + ;; submatch 1 doesn't match. This is, for example, the keyword + ;; "class" in Pike. + ;; o The start of a previously recognized declaration; "recognized" + ;; means that the last char of the previous token has a `c-type' + ;; text property with the value `c-decl-end'; this only holds + ;; when `c-type-decl-end-used' is set. ;; ;; Only a spot that match CFD-DECL-RE and whose face is in the ;; CFD-FACE-CHECKLIST list causes CFD-FUN to be called. The face @@ -4912,7 +4936,7 @@ comment at the start of cc-engine.el for more info." ;; ;; This function might do hidden buffer changes. - (let ((cfd-start-pos (point)) + (let ((cfd-start-pos (point)) ; never changed (cfd-buffer-end (point-max)) ;; The end of the token preceding the decl spot last found ;; with `c-decl-prefix-or-start-re'. `cfd-limit' if there's @@ -4951,10 +4975,20 @@ comment at the start of cc-engine.el for more info." ;; statement or declaration, which is earlier than the first ;; returned match. + ;; This `cond' moves back over any literals or macros. It has special + ;; handling for when the region being searched is entirely within a + ;; macro. It sets `cfd-continue-pos' (unless we've reached + ;; `cfd-limit'). (cond ;; First we need to move to a syntactically relevant position. ;; Begin by backing out of comment or string literals. + ;; + ;; This arm of the cond actually triggers if we're in a literal, + ;; and cfd-limit is at most at BONL. ((and + ;; This arm of the `and' moves backwards out of a literal when + ;; the face at point is a literal face. In this case, its value + ;; is always non-nil. (when (c-got-face-at (point) c-literal-faces) ;; Try to use the faces to back up to the start of the ;; literal. FIXME: What if the point is on a declaration @@ -4983,7 +5017,7 @@ comment at the start of cc-engine.el for more info." (let ((range (c-literal-limits))) (if range (goto-char (car range))))) - (setq start-in-literal (point))) + (setq start-in-literal (point))) ; end of `and' arm. ;; The start is in a literal. If the limit is in the same ;; one we don't have to find a syntactic position etc. We @@ -4994,22 +5028,22 @@ comment at the start of cc-engine.el for more info." (save-excursion (goto-char cfd-start-pos) (while (progn - (goto-char (next-single-property-change + (goto-char (c-next-single-property-change (point) 'face nil cfd-limit)) (and (< (point) cfd-limit) (c-got-face-at (point) c-literal-faces)))) - (= (point) cfd-limit))) + (= (point) cfd-limit))) ; end of `cond' arm condition ;; Completely inside a literal. Set up variables to trig the ;; (< cfd-continue-pos cfd-start-pos) case below and it'll ;; find a suitable start position. - (setq cfd-continue-pos start-in-literal)) + (setq cfd-continue-pos start-in-literal)) ; end of `cond' arm ;; Check if the region might be completely inside a macro, to ;; optimize that like the completely-inside-literal above. ((save-excursion (and (= (forward-line 1) 0) - (bolp) ; forward-line has funny behavior at eob. + (bolp) ; forward-line has funny behavior at eob. (>= (point) cfd-limit) (progn (backward-char) (eq (char-before) ?\\)))) @@ -5019,6 +5053,8 @@ comment at the start of cc-engine.el for more info." (setq cfd-continue-pos (1- cfd-start-pos) start-in-macro t)) + ;; The default arm of the `cond' moves back over any macro we're in + ;; and over any syntactic WS. It sets `c-find-decl-syntactic-pos'. (t ;; Back out of any macro so we don't miss any declaration ;; that could follow after it. @@ -5065,10 +5101,10 @@ comment at the start of cc-engine.el for more info." (< (point) cfd-limit)) ;; Do an initial search now. In the bob case above it's ;; only done to search for a `c-decl-end' spot. - (c-find-decl-prefix-search)) + (c-find-decl-prefix-search)) ; sets cfd-continue-pos (setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos) - cfd-match-pos))))) + cfd-match-pos))))) ; end of `cond' ;; Advance `cfd-continue-pos' if it's before the start position. ;; The closest continue position that might have effect at or @@ -5127,7 +5163,7 @@ comment at the start of cc-engine.el for more info." ;; `cfd-match-pos' so we can continue at the start position. ;; (Note that we don't get here if the first match is below ;; it.) - (goto-char cfd-start-pos))) + (goto-char cfd-start-pos))) ; end of `cond' ;; Delete found matches if they are before our new continue ;; position, so that `c-find-decl-prefix-search' won't back up @@ -5136,7 +5172,7 @@ comment at the start of cc-engine.el for more info." (when (and cfd-re-match (< cfd-re-match cfd-continue-pos)) (setq cfd-re-match nil)) (when (and cfd-prop-match (< cfd-prop-match cfd-continue-pos)) - (setq cfd-prop-match nil))) + (setq cfd-prop-match nil))) ; end of `when' (if syntactic-pos ;; This is the normal case and we got a proper syntactic @@ -5157,9 +5193,10 @@ comment at the start of cc-engine.el for more info." ;; good start position for the search, so do it. (c-find-decl-prefix-search))) - ;; Now loop. Round what? (ACM, 2006/7/5). We already got the first match. - + ;; Now loop, one decl spot per iteration. We already have the first + ;; match in `cfd-match-pos'. (while (progn + ;; Go forward over "false matches", one per iteration. (while (and (< cfd-match-pos cfd-limit) @@ -5200,10 +5237,10 @@ comment at the start of cc-engine.el for more info." (goto-char cfd-continue-pos) t))) - (< (point) cfd-limit)) - (c-find-decl-prefix-search)) + (< (point) cfd-limit)) ; end of "false matches" condition + (c-find-decl-prefix-search)) ; end of "false matches" loop - (< (point) cfd-limit)) + (< (point) cfd-limit)) ; end of condition for "decl-spot" while (when (and (>= (point) cfd-start-pos) @@ -5231,7 +5268,7 @@ comment at the start of cc-engine.el for more info." ;; The matched token was the last thing in the macro, ;; so the whole match is bogus. (setq cfd-macro-end 0) - nil)))) + 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)) @@ -5411,8 +5448,8 @@ comment at the start of cc-engine.el for more info." (c-go-list-forward)) (when (equal (c-get-char-property (1- (point)) 'syntax-table) c->-as-paren-syntax) ; should always be true. - (c-clear-char-property (1- (point)) 'category)) - (c-clear-char-property pos 'category)))) + (c-unmark-<->-as-paren (1- (point)))) + (c-unmark-<->-as-paren pos)))) (defun c-clear->-pair-props (&optional pos) ;; POS (default point) is at a > character. If it is marked with @@ -5428,8 +5465,8 @@ comment at the start of cc-engine.el for more info." (c-go-up-list-backward)) (when (equal (c-get-char-property (point) 'syntax-table) c-<-as-paren-syntax) ; should always be true. - (c-clear-char-property (point) 'category)) - (c-clear-char-property pos 'category)))) + (c-unmark-<->-as-paren (point))) + (c-unmark-<->-as-paren pos)))) (defun c-clear-<>-pair-props (&optional pos) ;; POS (default point) is at a < or > character. If it has an @@ -5518,9 +5555,10 @@ comment at the start of cc-engine.el for more info." (c-syntactic-skip-backward "^;{}" (c-determine-limit 512)) (setq new-beg (point)) - ;; Remove the syntax-table properties from each pertinent <...> pair. - ;; Firsly, the ones with the < before beg and > after beg. - (while (c-search-forward-char-property 'category 'c-<-as-paren-syntax beg) + ;; Remove the syntax-table/category properties from each pertinent <...> + ;; pair. Firsly, the ones with the < before beg and > after beg. + (while + (c-search-forward-char-property 'syntax-table c-<-as-paren-syntax beg) (if (c-clear-<-pair-props-if-match-after beg (1- (point))) (setq need-new-beg t))) @@ -5531,7 +5569,7 @@ comment at the start of cc-engine.el for more info." ;; Remove syntax-table properties from the remaining pertinent <...> ;; pairs, those with a > after end and < before end. - (while (c-search-backward-char-property 'category 'c->-as-paren-syntax end) + (while (c-search-backward-char-property 'syntax-table c->-as-paren-syntax end) (if (c-clear->-pair-props-if-match-before end) (setq need-new-end t))) @@ -5544,8 +5582,6 @@ comment at the start of cc-engine.el for more info." (when need-new-end (and (> new-end c-new-END) (setq c-new-END new-end)))))) - - (defun c-after-change-check-<>-operators (beg end) ;; This is called from `after-change-functions' when ;; c-recognize-<>-arglists' is set. It ensures that no "<" or ">" @@ -5880,7 +5916,6 @@ comment at the start of cc-engine.el for more info." ;; Recursive part of `c-forward-<>-arglist'. ;; ;; This function might do hidden buffer changes. - (let ((start (point)) res pos tmp ;; Cover this so that any recorded found type ranges are ;; automatically lost if it turns out to not be an angle @@ -5916,32 +5951,31 @@ comment at the start of cc-engine.el for more info." (while (and (progn (c-forward-syntactic-ws) - (let ((orig-record-found-types c-record-found-types)) - (when (or (and c-record-type-identifiers all-types) - (c-major-mode-is 'java-mode)) - ;; All encountered identifiers are types, so set the - ;; promote flag and parse the type. - (progn - (c-forward-syntactic-ws) - (if (looking-at "\\?") - (forward-char) - (when (looking-at c-identifier-start) - (let ((c-promote-possible-types t) - (c-record-found-types t)) - (c-forward-type)))) - - (c-forward-syntactic-ws) - - (when (or (looking-at "extends") - (looking-at "super")) - (forward-word) - (c-forward-syntactic-ws) + (when (or (and c-record-type-identifiers all-types) + (c-major-mode-is 'java-mode)) + ;; All encountered identifiers are types, so set the + ;; promote flag and parse the type. + (progn + (c-forward-syntactic-ws) + (if (looking-at "\\?") + (forward-char) + (when (looking-at c-identifier-start) (let ((c-promote-possible-types t) (c-record-found-types t)) - (c-forward-type) - (c-forward-syntactic-ws)))))) + (c-forward-type)))) + + (c-forward-syntactic-ws) + + (when (or (looking-at "extends") + (looking-at "super")) + (forward-word) + (c-forward-syntactic-ws) + (let ((c-promote-possible-types t) + (c-record-found-types t)) + (c-forward-type) + (c-forward-syntactic-ws))))) - (setq pos (point)) ; e.g. first token inside the '<' + (setq pos (point)) ; e.g. first token inside the '<' ;; Note: These regexps exploit the match order in \| so ;; that "<>" is matched by "<" rather than "[^>:-]>". @@ -5957,7 +5991,7 @@ comment at the start of cc-engine.el for more info." ;; Either an operator starting with '>' or the end of ;; the angle bracket arglist. - (if (looking-at c->-op-cont-regexp) + (if (looking-at c->-op-without->-cont-regexp) (progn (goto-char (match-end 0)) t) ; Continue the loop. @@ -6006,7 +6040,6 @@ comment at the start of cc-engine.el for more info." (c-keyword-member (c-keyword-sym (match-string 1)) 'c-<>-type-kwds))))))) - ;; It was an angle bracket arglist. (setq c-record-found-types subres) @@ -6032,7 +6065,7 @@ comment at the start of cc-engine.el for more info." (or (and (eq (char-before) ?&) (not (eq (char-after) ?&))) (eq (char-before) ?,))) - ;; Just another argument. Record the position. The + ;; Just another argument. Record the position. The ;; type check stuff that made us stop at it is at ;; the top of the loop. (setq arg-start-pos (cons (point) arg-start-pos))) @@ -6299,7 +6332,8 @@ comment at the start of cc-engine.el for more info." ;; `*-font-lock-extra-types'); ;; o - 'prefix if it's a known prefix of a type; ;; o - 'found if it's a type that matches one in `c-found-types'; - ;; o - 'maybe if it's an identifier that might be a type; or + ;; o - 'maybe if it's an identifier that might be a type; + ;; o - 'decltype if it's a decltype(variable) declaration; - or ;; o - nil if it can't be a type (the point isn't moved then). ;; ;; The point is assumed to be at the beginning of a token. @@ -6329,6 +6363,16 @@ comment at the start of cc-engine.el for more info." (setq res 'prefix))) (cond + ((looking-at c-typeof-key) ; e.g. C++'s "decltype". + (goto-char (match-end 1)) + (c-forward-syntactic-ws) + (setq res (and (eq (char-after) ?\() + (c-safe (c-forward-sexp)) + 'decltype)) + (if res + (c-forward-syntactic-ws) + (goto-char start))) + ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT ; "typedef". (goto-char (match-end 1)) @@ -6444,18 +6488,19 @@ comment at the start of cc-engine.el for more info." (setq res nil))))) (when res - ;; Skip trailing type modifiers. If any are found we know it's + ;; Skip trailing type modifiers. If any are found we know it's ;; a type. (when c-opt-type-modifier-key (while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile" (goto-char (match-end 1)) (c-forward-syntactic-ws) (setq res t))) + ;; Step over any type suffix operator. Do not let the existence ;; of these alter the classification of the found type, since ;; these operators typically are allowed in normal expressions ;; too. - (when c-opt-type-suffix-key + (when c-opt-type-suffix-key ; e.g. "..." (while (looking-at c-opt-type-suffix-key) (goto-char (match-end 1)) (c-forward-syntactic-ws))) @@ -6532,7 +6577,7 @@ comment at the start of cc-engine.el for more info." (progn (c-forward-syntactic-ws) t) (if (looking-at "(") (c-go-list-forward) - t))) + t))) (defmacro c-pull-open-brace (ps) ;; Pull the next open brace from PS (which has the form of paren-state), @@ -6543,6 +6588,36 @@ comment at the start of cc-engine.el for more info." (prog1 (car ,ps) (setq ,ps (cdr ,ps))))) +(defun c-back-over-member-initializer-braces () + ;; Point is just after a closing brace/parenthesis. Try to parse this as a + ;; C++ member initializer list, going back to just after the introducing ":" + ;; and returning t. Otherwise return nil, leaving point unchanged. + (let ((here (point)) res) + (setq res + (catch 'done + (when (not (c-go-list-backward)) + (throw 'done nil)) + (c-backward-syntactic-ws) + (when (not (c-simple-skip-symbol-backward)) + (throw 'done nil)) + (c-backward-syntactic-ws) + + (while (eq (char-before) ?,) + (backward-char) + (c-backward-syntactic-ws) + (when (not (memq (char-before) '(?\) ?}))) + (throw 'done nil)) + (when (not (c-go-list-backward)) + (throw 'done nil)) + (c-backward-syntactic-ws) + (when (not (c-simple-skip-symbol-backward)) + (throw 'done nil)) + (c-backward-syntactic-ws)) + + (eq (char-before) ?:))) + (or res (goto-char here)) + res)) + (defun c-back-over-member-initializers () ;; Test whether we are in a C++ member initializer list, and if so, go back ;; to the introducing ":", returning the position of the opening paren of @@ -6667,6 +6742,13 @@ comment at the start of cc-engine.el for more info." ;; Foo::Foo (int b) : Base (b) {} ;; car ^ ^ point ;; + ;; auto foo = 5; + ;; car ^ ^ point + ;; auto cplusplus_11 (int a, char *b) -> decltype (bar): + ;; car ^ ^ point + ;; + ;; + ;; ;; The cdr of the return value is non-nil when a ;; `c-typedef-decl-kwds' specifier is found in the declaration. ;; Specifically it is a dotted pair (A . B) where B is t when a @@ -6732,6 +6814,10 @@ comment at the start of cc-engine.el for more info." ;; If `backup-at-type' is nil then the other variables have ;; undefined values. backup-at-type backup-type-start backup-id-start + ;; This stores `kwd-sym' of the symbol before the current one. + ;; This is needed to distinguish the C++11 version of "auto" from + ;; the pre C++11 meaning. + backup-kwd-sym ;; Set if we've found a specifier (apart from "typedef") that makes ;; the defined identifier(s) types. at-type-decl @@ -6740,6 +6826,10 @@ comment at the start of cc-engine.el for more info." ;; Set if we've found a specifier that can start a declaration ;; where there's no type. maybe-typeless + ;; Save the value of kwd-sym between loops of the "Check for a + ;; type" loop. Needed to distinguish a C++11 "auto" from a pre + ;; C++11 one. + prev-kwd-sym ;; If a specifier is found that also can be a type prefix, ;; these flags are set instead of those above. If we need to ;; back up an identifier, they are copied to the real flag @@ -6757,6 +6847,8 @@ comment at the start of cc-engine.el for more info." backup-if-not-cast ;; For casts, the return position. cast-end + ;; Have we got a new-style C++11 "auto"? + new-style-auto ;; Save `c-record-type-identifiers' and ;; `c-record-ref-identifiers' since ranges are recorded ;; speculatively and should be thrown away if it turns out @@ -6775,11 +6867,12 @@ comment at the start of cc-engine.el for more info." (let* ((start (point)) kwd-sym kwd-clause-end found-type) ;; Look for a specifier keyword clause. - (when (or (looking-at c-prefix-spec-kwds-re) + (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto (and (c-major-mode-is 'java-mode) (looking-at "@[A-Za-z0-9]+"))) - (if (looking-at c-typedef-key) - (setq at-typedef t)) + (save-match-data + (if (looking-at c-typedef-key) + (setq at-typedef t))) (setq kwd-sym (c-keyword-sym (match-string 1))) (save-excursion (c-forward-keyword-clause 1) @@ -6787,6 +6880,12 @@ comment at the start of cc-engine.el for more info." (when (setq found-type (c-forward-type t)) ; brace-block-too ;; Found a known or possible type or a prefix of a known type. + (when (and (c-major-mode-is 'c++-mode) ; C++11 style "auto"? + (eq prev-kwd-sym (c-keyword-sym "auto")) + (looking-at "[=(]")) ; FIXME!!! proper regexp. + (setq new-style-auto t) + (setq found-type nil) + (goto-char start)) ; position of foo in "auto foo" (when at-type ;; Got two identifiers with nothing but whitespace @@ -6805,6 +6904,7 @@ comment at the start of cc-engine.el for more info." (setq backup-at-type at-type backup-type-start type-start backup-id-start id-start + backup-kwd-sym kwd-sym at-type found-type type-start start id-start (point) @@ -6860,6 +6960,7 @@ comment at the start of cc-engine.el for more info." ;; specifier keyword and we know we're in a ;; declaration. (setq at-decl-or-cast t) + (setq prev-kwd-sym kwd-sym) (goto-char kwd-clause-end)))) @@ -7051,50 +7152,60 @@ comment at the start of cc-engine.el for more info." (c-forward-syntactic-ws)) - (when (and (or maybe-typeless backup-maybe-typeless) - (not got-identifier) - (not got-prefix) - at-type) + (when (or (and new-style-auto + (looking-at c-auto-ops-re)) + (and (or maybe-typeless backup-maybe-typeless) + (not got-identifier) + (not got-prefix) + at-type)) ;; Have found no identifier but `c-typeless-decl-kwds' has ;; matched so we know we're inside a declaration. The ;; preceding type must be the identifier instead. (c-fdoc-shift-type-backward)) + ;; Prepare the "-> type;" for fontification later on. + (when (and new-style-auto + (looking-at c-haskell-op-re)) + (save-excursion + (goto-char (match-end 0)) + (c-forward-syntactic-ws) + (setq type-start (point)) + (setq at-type (c-forward-type)))) + (setq at-decl-or-cast (catch 'at-decl-or-cast ;; CASE 1 - (when (> paren-depth 0) - ;; Encountered something inside parens that isn't matched by - ;; the `c-type-decl-*' regexps, so it's not a type decl - ;; expression. Try to skip out to the same paren depth to - ;; not confuse the cast check below. - (c-safe (goto-char (scan-lists (point) 1 paren-depth))) - ;; If we've found a specifier keyword then it's a - ;; declaration regardless. - (throw 'at-decl-or-cast (eq at-decl-or-cast t))) - - (setq at-decl-end - (looking-at (cond ((eq context '<>) "[,>]") - (context "[,\)]") - (t "[,;]")))) - - ;; Now we've collected info about various characteristics of - ;; the construct we're looking at. Below follows a decision - ;; tree based on that. It's ordered to check more certain - ;; signs before less certain ones. - - (if got-identifier - (progn - - ;; CASE 2 - (when (and (or at-type maybe-typeless) - (not (or got-prefix got-parens))) - ;; Got another identifier directly after the type, so it's a - ;; declaration. - (throw 'at-decl-or-cast t)) + (when (> paren-depth 0) + ;; Encountered something inside parens that isn't matched by + ;; the `c-type-decl-*' regexps, so it's not a type decl + ;; expression. Try to skip out to the same paren depth to + ;; not confuse the cast check below. + (c-safe (goto-char (scan-lists (point) 1 paren-depth))) + ;; If we've found a specifier keyword then it's a + ;; declaration regardless. + (throw 'at-decl-or-cast (eq at-decl-or-cast t))) + + (setq at-decl-end + (looking-at (cond ((eq context '<>) "[,>]") + (context "[,\)]") + (t "[,;]")))) + + ;; Now we've collected info about various characteristics of + ;; the construct we're looking at. Below follows a decision + ;; tree based on that. It's ordered to check more certain + ;; signs before less certain ones. + + (if got-identifier + (progn + ;; CASE 2 + (when (and (or at-type maybe-typeless) + (not (or got-prefix got-parens))) + ;; Got another identifier directly after the type, so it's a + ;; declaration. + (throw 'at-decl-or-cast t)) (when (and got-parens (not got-prefix) @@ -7116,9 +7227,9 @@ comment at the start of cc-engine.el for more info." (c-fdoc-shift-type-backward))) ;; Found no identifier. - (if backup-at-type - (progn + (if backup-at-type + (progn ;; CASE 3 (when (= (point) start) @@ -7141,250 +7252,251 @@ comment at the start of cc-engine.el for more info." (setq backup-if-not-cast t) (throw 'at-decl-or-cast t))) - ;; CASE 4 - (when (and got-suffix - (not got-prefix) - (not got-parens)) - ;; Got a plain list of identifiers followed by some suffix. - ;; If this isn't a cast then the last identifier probably is - ;; the declared one and we should back up to the previous - ;; type. - (setq backup-if-not-cast t) - (throw 'at-decl-or-cast t))) - - ;; CASE 5 - (when (eq at-type t) - ;; If the type is known we know that there can't be any - ;; identifier somewhere else, and it's only in declarations in - ;; e.g. function prototypes and in casts that the identifier may - ;; be left out. - (throw 'at-decl-or-cast t)) - - (when (= (point) start) - ;; Only got a single identifier (parsed as a type so far). - ;; CASE 6 - (if (and - ;; Check that the identifier isn't at the start of an - ;; expression. - at-decl-end - (cond - ((eq context 'decl) - ;; Inside an arglist that contains declarations. If K&R - ;; style declarations and parenthesis style initializers - ;; aren't allowed then the single identifier must be a - ;; type, else we require that it's known or found - ;; (primitive types are handled above). - (or (and (not c-recognize-knr-p) - (not c-recognize-paren-inits)) - (memq at-type '(known found)))) - ((eq context '<>) - ;; Inside a template arglist. Accept known and found - ;; types; other identifiers could just as well be - ;; constants in C++. - (memq at-type '(known found))))) - (throw 'at-decl-or-cast t) - ;; CASE 7 - ;; Can't be a valid declaration or cast, but if we've found a - ;; specifier it can't be anything else either, so treat it as - ;; an invalid/unfinished declaration or cast. - (throw 'at-decl-or-cast at-decl-or-cast)))) - - (if (and got-parens - (not got-prefix) - (not context) - (not (eq at-type t)) - (or backup-at-type - maybe-typeless - backup-maybe-typeless - (when c-recognize-typeless-decls - (or (not got-suffix) - (not (looking-at - c-after-suffixed-type-maybe-decl-key)))))) - ;; Got an empty paren pair and a preceding type that probably - ;; really is the identifier. Shift the type backwards to make - ;; the last one the identifier. This is analogous to the - ;; "backtracking" done inside the `c-type-decl-suffix-key' loop - ;; above. - ;; - ;; Exception: In addition to the conditions in that - ;; "backtracking" code, do not shift backward if we're not - ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". - ;; Since there's no preceding type, the shift would mean that - ;; the declaration is typeless. But if the regexp doesn't match - ;; then we will simply fall through in the tests below and not - ;; recognize it at all, so it's better to try it as an abstract - ;; declarator instead. - (c-fdoc-shift-type-backward) - - ;; Still no identifier. - ;; CASE 8 - (when (and got-prefix (or got-parens got-suffix)) - ;; Require `got-prefix' together with either `got-parens' or - ;; `got-suffix' to recognize it as an abstract declarator: - ;; `got-parens' only is probably an empty function call. - ;; `got-suffix' only can build an ordinary expression together - ;; with the preceding identifier which we've taken as a type. - ;; We could actually accept on `got-prefix' only, but that can - ;; easily occur temporarily while writing an expression so we - ;; avoid that case anyway. We could do a better job if we knew - ;; the point when the fontification was invoked. - (throw 'at-decl-or-cast t)) - - ;; CASE 9 - (when (and at-type - (not got-prefix) - (not got-parens) - got-suffix-after-parens - (eq (char-after got-suffix-after-parens) ?\()) - ;; Got a type, no declarator but a paren suffix. I.e. it's a - ;; normal function call after all (or perhaps a C++ style object - ;; instantiation expression). - (throw 'at-decl-or-cast nil)))) - - ;; CASE 10 - (when at-decl-or-cast - ;; By now we've located the type in the declaration that we know - ;; we're in. - (throw 'at-decl-or-cast t)) - - ;; CASE 11 - (when (and got-identifier - (not context) - (looking-at c-after-suffixed-type-decl-key) - (if (and got-parens + ;; CASE 4 + (when (and got-suffix (not got-prefix) - (not got-suffix) - (not (eq at-type t))) - ;; Shift the type backward in the case that there's a - ;; single identifier inside parens. That can only - ;; occur in K&R style function declarations so it's - ;; more likely that it really is a function call. - ;; Therefore we only do this after - ;; `c-after-suffixed-type-decl-key' has matched. - (progn (c-fdoc-shift-type-backward) t) - got-suffix-after-parens)) - ;; A declaration according to `c-after-suffixed-type-decl-key'. - (throw 'at-decl-or-cast t)) - - ;; CASE 12 - (when (and (or got-prefix (not got-parens)) - (memq at-type '(t known))) - ;; It's a declaration if a known type precedes it and it can't be a - ;; function call. - (throw 'at-decl-or-cast t)) - - ;; If we get here we can't tell if this is a type decl or a normal - ;; expression by looking at it alone. (That's under the assumption - ;; that normal expressions always can look like type decl expressions, - ;; which isn't really true but the cases where it doesn't hold are so - ;; uncommon (e.g. some placements of "const" in C++) it's not worth - ;; the effort to look for them.) + (not got-parens)) + ;; Got a plain list of identifiers followed by some suffix. + ;; If this isn't a cast then the last identifier probably is + ;; the declared one and we should back up to the previous + ;; type. + (setq backup-if-not-cast t) + (throw 'at-decl-or-cast t))) + + ;; CASE 5 + (when (eq at-type t) + ;; If the type is known we know that there can't be any + ;; identifier somewhere else, and it's only in declarations in + ;; e.g. function prototypes and in casts that the identifier may + ;; be left out. + (throw 'at-decl-or-cast t)) + + (when (= (point) start) + ;; Only got a single identifier (parsed as a type so far). + ;; CASE 6 + (if (and + ;; Check that the identifier isn't at the start of an + ;; expression. + at-decl-end + (cond + ((eq context 'decl) + ;; Inside an arglist that contains declarations. If K&R + ;; style declarations and parenthesis style initializers + ;; aren't allowed then the single identifier must be a + ;; type, else we require that it's known or found + ;; (primitive types are handled above). + (or (and (not c-recognize-knr-p) + (not c-recognize-paren-inits)) + (memq at-type '(known found)))) + ((eq context '<>) + ;; Inside a template arglist. Accept known and found + ;; types; other identifiers could just as well be + ;; constants in C++. + (memq at-type '(known found))))) + (throw 'at-decl-or-cast t) + ;; CASE 7 + ;; Can't be a valid declaration or cast, but if we've found a + ;; specifier it can't be anything else either, so treat it as + ;; an invalid/unfinished declaration or cast. + (throw 'at-decl-or-cast at-decl-or-cast)))) + + (if (and got-parens + (not got-prefix) + (not context) + (not (eq at-type t)) + (or backup-at-type + maybe-typeless + backup-maybe-typeless + (when c-recognize-typeless-decls + (or (not got-suffix) + (not (looking-at + c-after-suffixed-type-maybe-decl-key)))))) + ;; Got an empty paren pair and a preceding type that probably + ;; really is the identifier. Shift the type backwards to make + ;; the last one the identifier. This is analogous to the + ;; "backtracking" done inside the `c-type-decl-suffix-key' loop + ;; above. + ;; + ;; Exception: In addition to the conditions in that + ;; "backtracking" code, do not shift backward if we're not + ;; looking at either `c-after-suffixed-type-decl-key' or "[;,]". + ;; Since there's no preceding type, the shift would mean that + ;; the declaration is typeless. But if the regexp doesn't match + ;; then we will simply fall through in the tests below and not + ;; recognize it at all, so it's better to try it as an abstract + ;; declarator instead. + (c-fdoc-shift-type-backward) + + ;; Still no identifier. + ;; CASE 8 + (when (and got-prefix (or got-parens got-suffix)) + ;; Require `got-prefix' together with either `got-parens' or + ;; `got-suffix' to recognize it as an abstract declarator: + ;; `got-parens' only is probably an empty function call. + ;; `got-suffix' only can build an ordinary expression together + ;; with the preceding identifier which we've taken as a type. + ;; We could actually accept on `got-prefix' only, but that can + ;; easily occur temporarily while writing an expression so we + ;; avoid that case anyway. We could do a better job if we knew + ;; the point when the fontification was invoked. + (throw 'at-decl-or-cast t)) + + ;; CASE 9 + (when (and at-type + (not got-prefix) + (not got-parens) + got-suffix-after-parens + (eq (char-after got-suffix-after-parens) ?\()) + ;; Got a type, no declarator but a paren suffix. I.e. it's a + ;; normal function call after all (or perhaps a C++ style object + ;; instantiation expression). + (throw 'at-decl-or-cast nil)))) + + ;; CASE 10 + (when at-decl-or-cast + ;; By now we've located the type in the declaration that we know + ;; we're in. + (throw 'at-decl-or-cast t)) + + ;; CASE 11 + (when (and got-identifier + (not context) + (looking-at c-after-suffixed-type-decl-key) + (if (and got-parens + (not got-prefix) + (not got-suffix) + (not (eq at-type t))) + ;; Shift the type backward in the case that there's a + ;; single identifier inside parens. That can only + ;; occur in K&R style function declarations so it's + ;; more likely that it really is a function call. + ;; Therefore we only do this after + ;; `c-after-suffixed-type-decl-key' has matched. + (progn (c-fdoc-shift-type-backward) t) + got-suffix-after-parens)) + ;; A declaration according to `c-after-suffixed-type-decl-key'. + (throw 'at-decl-or-cast t)) + + ;; CASE 12 + (when (and (or got-prefix (not got-parens)) + (memq at-type '(t known))) + ;; It's a declaration if a known type precedes it and it can't be a + ;; function call. + (throw 'at-decl-or-cast t)) + + ;; If we get here we can't tell if this is a type decl or a normal + ;; expression by looking at it alone. (That's under the assumption + ;; that normal expressions always can look like type decl expressions, + ;; which isn't really true but the cases where it doesn't hold are so + ;; uncommon (e.g. some placements of "const" in C++) it's not worth + ;; the effort to look for them.) ;;; 2008-04-16: commented out the next form, to allow the function to recognize ;;; "foo (int bar)" in CC (an implicit type (in class foo) without a semicolon) ;;; as a(n almost complete) declaration, enabling it to be fontified. - ;; CASE 13 - ;; (unless (or at-decl-end (looking-at "=[^=]")) - ;; If this is a declaration it should end here or its initializer(*) - ;; should start here, so check for allowed separation tokens. Note - ;; that this rule doesn't work e.g. with a K&R arglist after a - ;; function header. - ;; - ;; *) Don't check for C++ style initializers using parens - ;; since those already have been matched as suffixes. - ;; - ;; If `at-decl-or-cast' is then we've found some other sign that - ;; it's a declaration or cast, so then it's probably an - ;; invalid/unfinished one. - ;; (throw 'at-decl-or-cast at-decl-or-cast)) - - ;; Below are tests that only should be applied when we're certain to - ;; not have parsed halfway through an expression. - - ;; CASE 14 - (when (memq at-type '(t known)) - ;; The expression starts with a known type so treat it as a - ;; declaration. - (throw 'at-decl-or-cast t)) - - ;; CASE 15 - (when (and (c-major-mode-is 'c++-mode) - ;; In C++ we check if the identifier is a known type, since - ;; (con|de)structors use the class name as identifier. - ;; We've always shifted over the identifier as a type and - ;; then backed up again in this case. - identifier-type - (or (memq identifier-type '(found known)) - (and (eq (char-after identifier-start) ?~) - ;; `at-type' probably won't be 'found for - ;; destructors since the "~" is then part of the - ;; type name being checked against the list of - ;; known types, so do a check without that - ;; operator. - (or (save-excursion - (goto-char (1+ identifier-start)) - (c-forward-syntactic-ws) - (c-with-syntax-table - c-identifier-syntax-table - (looking-at c-known-type-key))) - (save-excursion - (goto-char (1+ identifier-start)) - ;; We have already parsed the type earlier, - ;; so it'd be possible to cache the end - ;; position instead of redoing it here, but - ;; then we'd need to keep track of another - ;; position everywhere. - (c-check-type (point) - (progn (c-forward-type) - (point)))))))) - (throw 'at-decl-or-cast t)) - - (if got-identifier - (progn - ;; CASE 16 - (when (and got-prefix-before-parens - at-type - (or at-decl-end (looking-at "=[^=]")) - (not context) - (not got-suffix)) - ;; Got something like "foo * bar;". Since we're not inside an - ;; arglist it would be a meaningless expression because the - ;; result isn't used. We therefore choose to recognize it as - ;; a declaration. Do not allow a suffix since it could then - ;; be a function call. - (throw 'at-decl-or-cast t)) - - ;; CASE 17 - (when (and (or got-suffix-after-parens - (looking-at "=[^=]")) - (eq at-type 'found) - (not (eq context 'arglist))) - ;; Got something like "a (*b) (c);" or "a (b) = c;". It could - ;; be an odd expression or it could be a declaration. Treat - ;; it as a declaration if "a" has been used as a type - ;; somewhere else (if it's a known type we won't get here). - (throw 'at-decl-or-cast t))) - - ;; CASE 18 - (when (and context - (or got-prefix - (and (eq context 'decl) - (not c-recognize-paren-inits) - (or got-parens got-suffix)))) - ;; Got a type followed by an abstract declarator. If `got-prefix' - ;; is set it's something like "a *" without anything after it. If - ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", - ;; or similar, which we accept only if the context rules out - ;; expressions. - (throw 'at-decl-or-cast t))) - - ;; If we had a complete symbol table here (which rules out - ;; `c-found-types') we should return t due to the disambiguation rule - ;; (in at least C++) that anything that can be parsed as a declaration - ;; is a declaration. Now we're being more defensive and prefer to - ;; highlight things like "foo (bar);" as a declaration only if we're - ;; inside an arglist that contains declarations. - (eq context 'decl)))) + ;; CASE 13 + ;; (unless (or at-decl-end (looking-at "=[^=]")) + ;; If this is a declaration it should end here or its initializer(*) + ;; should start here, so check for allowed separation tokens. Note + ;; that this rule doesn't work e.g. with a K&R arglist after a + ;; function header. + ;; + ;; *) Don't check for C++ style initializers using parens + ;; since those already have been matched as suffixes. + ;; + ;; If `at-decl-or-cast' is then we've found some other sign that + ;; it's a declaration or cast, so then it's probably an + ;; invalid/unfinished one. + ;; (throw 'at-decl-or-cast at-decl-or-cast)) + + ;; Below are tests that only should be applied when we're certain to + ;; not have parsed halfway through an expression. + + ;; CASE 14 + (when (memq at-type '(t known)) + ;; The expression starts with a known type so treat it as a + ;; declaration. + (throw 'at-decl-or-cast t)) + + ;; CASE 15 + (when (and (c-major-mode-is 'c++-mode) + ;; In C++ we check if the identifier is a known type, since + ;; (con|de)structors use the class name as identifier. + ;; We've always shifted over the identifier as a type and + ;; then backed up again in this case. + identifier-type + (or (memq identifier-type '(found known)) + (and (eq (char-after identifier-start) ?~) + ;; `at-type' probably won't be 'found for + ;; destructors since the "~" is then part of the + ;; type name being checked against the list of + ;; known types, so do a check without that + ;; operator. + (or (save-excursion + (goto-char (1+ identifier-start)) + (c-forward-syntactic-ws) + (c-with-syntax-table + c-identifier-syntax-table + (looking-at c-known-type-key))) + (save-excursion + (goto-char (1+ identifier-start)) + ;; We have already parsed the type earlier, + ;; so it'd be possible to cache the end + ;; position instead of redoing it here, but + ;; then we'd need to keep track of another + ;; position everywhere. + (c-check-type (point) + (progn (c-forward-type) + (point)))))))) + (throw 'at-decl-or-cast t)) + + (if got-identifier + (progn + ;; CASE 16 + (when (and got-prefix-before-parens + at-type + (or at-decl-end (looking-at "=[^=]")) + (not context) + (not got-suffix)) + ;; Got something like "foo * bar;". Since we're not inside an + ;; arglist it would be a meaningless expression because the + ;; result isn't used. We therefore choose to recognize it as + ;; a declaration. Do not allow a suffix since it could then + ;; be a function call. + (throw 'at-decl-or-cast t)) + + ;; CASE 17 + (when (and (or got-suffix-after-parens + (looking-at "=[^=]")) + (eq at-type 'found) + (not (eq context 'arglist))) + ;; Got something like "a (*b) (c);" or "a (b) = c;". It could + ;; be an odd expression or it could be a declaration. Treat + ;; it as a declaration if "a" has been used as a type + ;; somewhere else (if it's a known type we won't get here). + (throw 'at-decl-or-cast t))) + + ;; CASE 18 + (when (and context + (or got-prefix + (and (eq context 'decl) + (not c-recognize-paren-inits) + (or got-parens got-suffix)))) + ;; Got a type followed by an abstract declarator. If `got-prefix' + ;; is set it's something like "a *" without anything after it. If + ;; `got-parens' or `got-suffix' is set it's "a()", "a[]", "a()[]", + ;; or similar, which we accept only if the context rules out + ;; expressions. + (throw 'at-decl-or-cast t))) + + ;; If we had a complete symbol table here (which rules out + ;; `c-found-types') we should return t due to the disambiguation rule + ;; (in at least C++) that anything that can be parsed as a declaration + ;; is a declaration. Now we're being more defensive and prefer to + ;; highlight things like "foo (bar);" as a declaration only if we're + ;; inside an arglist that contains declarations. + ;; CASE 19 + (eq context 'decl)))) ;; The point is now after the type decl expression. @@ -7473,6 +7585,8 @@ comment at the start of cc-engine.el for more info." ;; interactive refontification. (c-put-c-type-property (point) 'c-decl-arg-start)) + ;; Record the type's coordinates in `c-record-type-identifiers' for + ;; later fontification. (when (and c-record-type-identifiers at-type ;; (not (eq at-type t)) ;; There seems no reason to exclude a token from ;; fontification just because it's "a known type that can't @@ -7571,10 +7685,10 @@ comment at the start of cc-engine.el for more info." (c-put-c-type-property (1- (point)) 'c-decl-end) t) - ;; It's an unfinished label. We consider the keyword enough - ;; to recognize it as a label, so that it gets fontified. - ;; Leave the point at the end of it, but don't put any - ;; `c-decl-end' marker. + ;; It's an unfinished label. We consider the keyword enough + ;; to recognize it as a label, so that it gets fontified. + ;; Leave the point at the end of it, but don't put any + ;; `c-decl-end' marker. (goto-char kwd-end) t)))) @@ -7759,69 +7873,69 @@ comment at the start of cc-engine.el for more info." ;; ;; This function might do hidden buffer changes. - (let ((start (point)) - start-char - (c-promote-possible-types t) - lim - ;; Turn off recognition of angle bracket arglists while parsing - ;; types here since the protocol reference list might then be - ;; considered part of the preceding name or superclass-name. - c-recognize-<>-arglists) - - (if (or - (when (looking-at - (eval-when-compile - (c-make-keywords-re t - (append (c-lang-const c-protection-kwds objc) - '("@end")) - 'objc-mode))) - (goto-char (match-end 1)) - t) + (let ((start (point)) + start-char + (c-promote-possible-types t) + lim + ;; Turn off recognition of angle bracket arglists while parsing + ;; types here since the protocol reference list might then be + ;; considered part of the preceding name or superclass-name. + c-recognize-<>-arglists) + + (if (or + (when (looking-at + (eval-when-compile + (c-make-keywords-re t + (append (c-lang-const c-protection-kwds objc) + '("@end")) + 'objc-mode))) + (goto-char (match-end 1)) + t) - (and - (looking-at - (eval-when-compile - (c-make-keywords-re t - '("@interface" "@implementation" "@protocol") - 'objc-mode))) + (and + (looking-at + (eval-when-compile + (c-make-keywords-re t + '("@interface" "@implementation" "@protocol") + 'objc-mode))) - ;; Handle the name of the class itself. - (progn -; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's -; at EOB. - (goto-char (match-end 0)) - (setq lim (point)) - (c-skip-ws-forward) - (c-forward-type)) - - (catch 'break - ;; Look for ": superclass-name" or "( category-name )". - (when (looking-at "[:\(]") - (setq start-char (char-after)) + ;; Handle the name of the class itself. + (progn + ;; (c-forward-token-2) ; 2006/1/13 This doesn't move if the token's + ;; at EOB. + (goto-char (match-end 0)) + (setq lim (point)) + (c-skip-ws-forward) + (c-forward-type)) + + (catch 'break + ;; Look for ": superclass-name" or "( category-name )". + (when (looking-at "[:\(]") + (setq start-char (char-after)) + (forward-char) + (c-forward-syntactic-ws) + (unless (c-forward-type) (throw 'break nil)) + (when (eq start-char ?\() + (unless (eq (char-after) ?\)) (throw 'break nil)) (forward-char) - (c-forward-syntactic-ws) - (unless (c-forward-type) (throw 'break nil)) - (when (eq start-char ?\() - (unless (eq (char-after) ?\)) (throw 'break nil)) - (forward-char) - (c-forward-syntactic-ws))) - - ;; Look for a protocol reference list. - (if (eq (char-after) ?<) - (let ((c-recognize-<>-arglists t) - (c-parse-and-markup-<>-arglists t) - c-restricted-<>-arglists) - (c-forward-<>-arglist t)) - t)))) + (c-forward-syntactic-ws))) - (progn - (c-backward-syntactic-ws lim) - (c-clear-c-type-property start (1- (point)) 'c-decl-end) - (c-put-c-type-property (1- (point)) 'c-decl-end) - t) + ;; Look for a protocol reference list. + (if (eq (char-after) ?<) + (let ((c-recognize-<>-arglists t) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists) + (c-forward-<>-arglist t)) + t)))) - (c-clear-c-type-property start (point) 'c-decl-end) - nil))) + (progn + (c-backward-syntactic-ws lim) + (c-clear-c-type-property start (1- (point)) 'c-decl-end) + (c-put-c-type-property (1- (point)) 'c-decl-end) + t) + + (c-clear-c-type-property start (point) 'c-decl-end) + nil))) (defun c-beginning-of-inheritance-list (&optional lim) ;; Go to the first non-whitespace after the colon that starts a @@ -7908,7 +8022,7 @@ comment at the start of cc-engine.el for more info." ;; ;; This function might do hidden buffer changes. - (let ((beg (point)) end id-start) + (let ((beg (point)) id-start) (and (eq (c-beginning-of-statement-1 lim) 'same) @@ -7998,54 +8112,54 @@ comment at the start of cc-engine.el for more info." (throw 'knr nil))) (if after-rparen - ;; We're inside a paren. Could it be our argument list....? - (if - (and - (progn - (goto-char after-rparen) - (unless (c-go-list-backward) (throw 'knr nil)) ; - ;; FIXME!!! What about macros between the parens? 2007/01/20 - (setq before-lparen (point))) + ;; We're inside a paren. Could it be our argument list....? + (if + (and + (progn + (goto-char after-rparen) + (unless (c-go-list-backward) (throw 'knr nil)) ; + ;; FIXME!!! What about macros between the parens? 2007/01/20 + (setq before-lparen (point))) - ;; It can't be the arg list if next token is ; or { - (progn (goto-char after-rparen) - (c-forward-syntactic-ws) - (not (memq (char-after) '(?\; ?\{ ?\=)))) + ;; It can't be the arg list if next token is ; or { + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (not (memq (char-after) '(?\; ?\{ ?\=)))) - ;; Is the thing preceding the list an identifier (the - ;; function name), or a macro expansion? - (progn - (goto-char before-lparen) - (eq (c-backward-token-2) 0) - (or (eq (c-on-identifier) (point)) - (and (eq (char-after) ?\)) - (c-go-up-list-backward) - (eq (c-backward-token-2) 0) - (eq (c-on-identifier) (point))))) - - ;; Have we got a non-empty list of comma-separated - ;; identifiers? - (progn - (goto-char before-lparen) - (c-forward-token-2) ; to first token inside parens - (and - (c-on-identifier) - (c-forward-token-2) - (catch 'id-list - (while (eq (char-after) ?\,) - (c-forward-token-2) - (unless (c-on-identifier) (throw 'id-list nil)) - (c-forward-token-2)) - (eq (char-after) ?\)))))) - - ;; ...Yes. We've identified the function's argument list. - (throw 'knr - (progn (goto-char after-rparen) - (c-forward-syntactic-ws) - (point))) - - ;; ...No. The current parens aren't the function's arg list. - (goto-char before-lparen)) + ;; Is the thing preceding the list an identifier (the + ;; function name), or a macro expansion? + (progn + (goto-char before-lparen) + (eq (c-backward-token-2) 0) + (or (eq (c-on-identifier) (point)) + (and (eq (char-after) ?\)) + (c-go-up-list-backward) + (eq (c-backward-token-2) 0) + (eq (c-on-identifier) (point))))) + + ;; Have we got a non-empty list of comma-separated + ;; identifiers? + (progn + (goto-char before-lparen) + (c-forward-token-2) ; to first token inside parens + (and + (c-on-identifier) + (c-forward-token-2) + (catch 'id-list + (while (eq (char-after) ?\,) + (c-forward-token-2) + (unless (c-on-identifier) (throw 'id-list nil)) + (c-forward-token-2)) + (eq (char-after) ?\)))))) + + ;; ...Yes. We've identified the function's argument list. + (throw 'knr + (progn (goto-char after-rparen) + (c-forward-syntactic-ws) + (point))) + + ;; ...No. The current parens aren't the function's arg list. + (goto-char before-lparen)) (or (c-go-list-backward) ; backwards over [ .... ] (throw 'knr nil))))))))) @@ -8251,7 +8365,7 @@ comment at the start of cc-engine.el for more info." (and (progn (while ; keep going back to "[;={"s until we either find - ; no more, or get to one which isn't an "operator =" + ; no more, or get to one which isn't an "operator =" (and (c-syntactic-re-search-forward "[;={]" start t t t) (eq (char-before) ?=) c-overloadable-operators-regexp @@ -8365,10 +8479,7 @@ comment at the start of cc-engine.el for more info." (when (and c-recognize-<>-arglists (eq (char-before) ?>)) ;; Could be at the end of a template arglist. - (let ((c-parse-and-markup-<>-arglists t) - (c-disallow-comma-in-<>-arglists - (and containing-sexp - (not (eq (char-after containing-sexp) ?{))))) + (let ((c-parse-and-markup-<>-arglists t)) (while (and (c-backward-<>-arglist nil limit) (progn @@ -8392,31 +8503,44 @@ comment at the start of cc-engine.el for more info." (cond ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t) (goto-char (setq kwd-start (match-beginning 0))) - (or - - ;; Found a keyword that can't be a type? - (match-beginning 1) - - ;; Can be a type too, in which case it's the return type of a - ;; function (under the assumption that no declaration level - ;; block construct starts with a type). - (not (c-forward-type)) - - ;; Jumped over a type, but it could be a declaration keyword - ;; followed by the declared identifier that we've jumped over - ;; instead (e.g. in "class Foo {"). If it indeed is a type - ;; then we should be at the declarator now, so check for a - ;; valid declarator start. - ;; - ;; Note: This doesn't cope with the case when a declared - ;; identifier is followed by e.g. '(' in a language where '(' - ;; also might be part of a declarator expression. Currently - ;; there's no such language. - (not (or (looking-at c-symbol-start) - (looking-at c-type-decl-prefix-key))))) + (and + ;; Exclude cases where we matched what would ordinarily + ;; be a block declaration keyword, except where it's not + ;; legal because it's part of a "compound keyword" like + ;; "enum class". Of course, if c-after-brace-list-key + ;; is nil, we can skip the test. + (or (equal c-after-brace-list-key "\\<\\>") + (save-match-data + (save-excursion + (not + (and + (looking-at c-after-brace-list-key) + (= (c-backward-token-2 1 t) 0) + (looking-at c-brace-list-key)))))) + (or + ;; Found a keyword that can't be a type? + (match-beginning 1) + + ;; Can be a type too, in which case it's the return type of a + ;; function (under the assumption that no declaration level + ;; block construct starts with a type). + (not (c-forward-type)) + + ;; Jumped over a type, but it could be a declaration keyword + ;; followed by the declared identifier that we've jumped over + ;; instead (e.g. in "class Foo {"). If it indeed is a type + ;; then we should be at the declarator now, so check for a + ;; valid declarator start. + ;; + ;; Note: This doesn't cope with the case when a declared + ;; identifier is followed by e.g. '(' in a language where '(' + ;; also might be part of a declarator expression. Currently + ;; there's no such language. + (not (or (looking-at c-symbol-start) + (looking-at c-type-decl-prefix-key)))))) ;; In Pike a list of modifiers may be followed by a brace - ;; to make them apply to many identifiers. Note that the + ;; to make them apply to many identifiers. Note that the ;; match data will be empty on return in this case. ((and (c-major-mode-is 'pike-mode) (progn @@ -8518,11 +8642,44 @@ comment at the start of cc-engine.el for more info." (not (looking-at "="))))) b-pos))) +(defun c-backward-colon-prefixed-type () + ;; We're at the token after what might be a type prefixed with a colon. Try + ;; moving backward over this type and the colon. On success, return t and + ;; leave point before colon; on failure, leave point unchanged. Will clobber + ;; match data. + (let ((here (point)) + (colon-pos nil)) + (save-excursion + (while + (and (eql (c-backward-token-2) 0) + (or (not (looking-at "\\s)")) + (c-go-up-list-backward)) + (cond + ((eql (char-after) ?:) + (setq colon-pos (point)) + (forward-char) + (c-forward-syntactic-ws) + (or (and (c-forward-type) + (progn (c-forward-syntactic-ws) + (eq (point) here))) + (setq colon-pos nil)) + nil) + ((eql (char-after) ?\() + t) + ((looking-at c-symbol-key) + t) + (t nil))))) + (when colon-pos + (goto-char colon-pos) + t))) + (defun c-backward-over-enum-header () ;; We're at a "{". Move back to the enum-like keyword that starts this ;; declaration and return t, otherwise don't move and return nil. (let ((here (point)) up-sexp-pos before-identifier) + (when c-recognize-post-brace-list-type-p + (c-backward-colon-prefixed-type)) (while (and (eq (c-backward-token-2) 0) @@ -8533,10 +8690,11 @@ comment at the start of cc-engine.el for more info." (not before-identifier)) (setq before-identifier t)) ((and before-identifier - (or (eq (char-after) ?,) + (or (eql (char-after) ?,) (looking-at c-postfix-decl-spec-key))) (setq before-identifier nil) t) + ((looking-at c-after-brace-list-key) t) ((looking-at c-brace-list-key) nil) ((and c-recognize-<>-arglists (eq (char-after) ?<) @@ -8574,86 +8732,86 @@ comment at the start of cc-engine.el for more info." (while (and (not bufpos) containing-sexp) (when paren-state - (if (consp (car paren-state)) - (setq lim (cdr (car paren-state)) - paren-state (cdr paren-state)) - (setq lim (car paren-state))) - (when paren-state - (setq next-containing (car paren-state) - paren-state (cdr paren-state)))) - (goto-char containing-sexp) - (if (c-looking-at-inexpr-block next-containing next-containing) - ;; We're in an in-expression block of some kind. Do not - ;; check nesting. We deliberately set the limit to the - ;; containing sexp, so that c-looking-at-inexpr-block - ;; doesn't check for an identifier before it. - (setq containing-sexp nil) - ;; see if the open brace is preceded by = or [...] in - ;; this statement, but watch out for operator= - (setq braceassignp 'dontknow) - (c-backward-token-2 1 t lim) - ;; Checks to do only on the first sexp before the brace. - (when (and c-opt-inexpr-brace-list-key - (eq (char-after) ?\[)) - ;; In Java, an initialization brace list may follow - ;; directly after "new Foo[]", so check for a "new" - ;; earlier. - (while (eq braceassignp 'dontknow) - (setq braceassignp - (cond ((/= (c-backward-token-2 1 t lim) 0) nil) - ((looking-at c-opt-inexpr-brace-list-key) t) - ((looking-at "\\sw\\|\\s_\\|[.[]") - ;; Carry on looking if this is an - ;; identifier (may contain "." in Java) - ;; or another "[]" sexp. - 'dontknow) - (t nil))))) - ;; Checks to do on all sexps before the brace, up to the - ;; beginning of the statement. + (if (consp (car paren-state)) + (setq lim (cdr (car paren-state)) + paren-state (cdr paren-state)) + (setq lim (car paren-state))) + (when paren-state + (setq next-containing (car paren-state) + paren-state (cdr paren-state)))) + (goto-char containing-sexp) + (if (c-looking-at-inexpr-block next-containing next-containing) + ;; We're in an in-expression block of some kind. Do not + ;; check nesting. We deliberately set the limit to the + ;; containing sexp, so that c-looking-at-inexpr-block + ;; doesn't check for an identifier before it. + (setq containing-sexp nil) + ;; see if the open brace is preceded by = or [...] in + ;; this statement, but watch out for operator= + (setq braceassignp 'dontknow) + (c-backward-token-2 1 t lim) + ;; Checks to do only on the first sexp before the brace. + (when (and c-opt-inexpr-brace-list-key + (eq (char-after) ?\[)) + ;; In Java, an initialization brace list may follow + ;; directly after "new Foo[]", so check for a "new" + ;; earlier. (while (eq braceassignp 'dontknow) - (cond ((eq (char-after) ?\;) - (setq braceassignp nil)) - ((and class-key - (looking-at class-key)) - (setq braceassignp nil)) - ((eq (char-after) ?=) - ;; We've seen a =, but must check earlier tokens so - ;; that it isn't something that should be ignored. - (setq braceassignp 'maybe) - (while (and (eq braceassignp 'maybe) - (zerop (c-backward-token-2 1 t lim))) - (setq braceassignp - (cond - ;; Check for operator = - ((and c-opt-op-identifier-prefix - (looking-at c-opt-op-identifier-prefix)) - nil) - ;; Check for `<opchar>= in Pike. - ((and (c-major-mode-is 'pike-mode) - (or (eq (char-after) ?`) - ;; Special case for Pikes - ;; `[]=, since '[' is not in - ;; the punctuation class. - (and (eq (char-after) ?\[) - (eq (char-before) ?`)))) - nil) - ((looking-at "\\s.") 'maybe) - ;; make sure we're not in a C++ template - ;; argument assignment - ((and - (c-major-mode-is 'c++-mode) - (save-excursion - (let ((here (point)) - (pos< (progn - (skip-chars-backward "^<>") - (point)))) - (and (eq (char-before) ?<) - (not (c-crosses-statement-barrier-p - pos< here)) - (not (c-in-literal)) - )))) - nil) - (t t)))))) + (setq braceassignp + (cond ((/= (c-backward-token-2 1 t lim) 0) nil) + ((looking-at c-opt-inexpr-brace-list-key) t) + ((looking-at "\\sw\\|\\s_\\|[.[]") + ;; Carry on looking if this is an + ;; identifier (may contain "." in Java) + ;; or another "[]" sexp. + 'dontknow) + (t nil))))) + ;; Checks to do on all sexps before the brace, up to the + ;; beginning of the statement. + (while (eq braceassignp 'dontknow) + (cond ((eq (char-after) ?\;) + (setq braceassignp nil)) + ((and class-key + (looking-at class-key)) + (setq braceassignp nil)) + ((eq (char-after) ?=) + ;; We've seen a =, but must check earlier tokens so + ;; that it isn't something that should be ignored. + (setq braceassignp 'maybe) + (while (and (eq braceassignp 'maybe) + (zerop (c-backward-token-2 1 t lim))) + (setq braceassignp + (cond + ;; Check for operator = + ((and c-opt-op-identifier-prefix + (looking-at c-opt-op-identifier-prefix)) + nil) + ;; Check for `<opchar>= in Pike. + ((and (c-major-mode-is 'pike-mode) + (or (eq (char-after) ?`) + ;; Special case for Pikes + ;; `[]=, since '[' is not in + ;; the punctuation class. + (and (eq (char-after) ?\[) + (eq (char-before) ?`)))) + nil) + ((looking-at "\\s.") 'maybe) + ;; make sure we're not in a C++ template + ;; argument assignment + ((and + (c-major-mode-is 'c++-mode) + (save-excursion + (let ((here (point)) + (pos< (progn + (skip-chars-backward "^<>") + (point)))) + (and (eq (char-before) ?<) + (not (c-crosses-statement-barrier-p + pos< here)) + (not (c-in-literal)) + )))) + nil) + (t t)))))) (if (and (eq braceassignp 'dontknow) (/= (c-backward-token-2 1 t lim) 0)) (setq braceassignp nil))) @@ -9176,7 +9334,7 @@ comment at the start of cc-engine.el for more info." (max (c-point 'boi paren-pos) (point)))) (t (c-add-syntax 'defun-block-intro nil)))) - (c-add-syntax 'statement-block-intro nil))) + (c-add-syntax 'statement-block-intro nil))) (if (= paren-pos boi) ;; Always done if the open brace was at boi. The @@ -9346,15 +9504,15 @@ comment at the start of cc-engine.el for more info." ;;annotations. ((and (c-major-mode-is 'java-mode) (setq placeholder (point)) - (c-beginning-of-statement-1) - (progn - (while (and (c-forward-annotation) - (< (point) placeholder)) - (c-forward-syntactic-ws)) - t) - (prog1 - (>= (point) placeholder) - (goto-char placeholder))) + (c-beginning-of-statement-1) + (progn + (while (and (c-forward-annotation) + (< (point) placeholder)) + (c-forward-syntactic-ws)) + t) + (prog1 + (>= (point) placeholder) + (goto-char placeholder))) (c-beginning-of-statement-1 containing-sexp) (c-add-syntax 'annotation-var-cont (point))) @@ -9373,16 +9531,16 @@ comment at the start of cc-engine.el for more info." (not (looking-at c-<-op-cont-regexp)))))) (c-with-syntax-table c++-template-syntax-table (goto-char placeholder) - (c-beginning-of-statement-1 containing-sexp t) - (if (save-excursion - (c-backward-syntactic-ws containing-sexp) - (eq (char-before) ?<)) - ;; In a nested template arglist. - (progn - (goto-char placeholder) - (c-syntactic-skip-backward "^,;" containing-sexp t) - (c-forward-syntactic-ws)) - (back-to-indentation))) + (c-beginning-of-statement-1 containing-sexp t)) + (if (save-excursion + (c-backward-syntactic-ws containing-sexp) + (eq (char-before) ?<)) + ;; In a nested template arglist. + (progn + (goto-char placeholder) + (c-syntactic-skip-backward "^,;" containing-sexp t) + (c-forward-syntactic-ws)) + (back-to-indentation)) ;; FIXME: Should use c-add-stmt-syntax, but it's not yet ;; template aware. (c-add-syntax 'template-args-cont (point) placeholder)) @@ -9405,7 +9563,7 @@ comment at the start of cc-engine.el for more info." ((indent-point (point)) (case-fold-search nil) open-paren-in-column-0-is-defun-start - ;; A whole ugly bunch of various temporary variables. Have + ;; A whole ugly bunch of various temporary variables. Have ;; to declare them here since it's not possible to declare ;; a variable with only the scope of a cond test and the ;; following result clauses, and most of this function is a @@ -9460,22 +9618,26 @@ comment at the start of cc-engine.el for more info." (c-keyword-sym (match-string 1))))) ;; Init some position variables. - (if c-state-cache + (if paren-state (progn (setq containing-sexp (car paren-state) paren-state (cdr paren-state)) (if (consp containing-sexp) - (progn - (setq lim (cdr containing-sexp)) - (if (cdr c-state-cache) - ;; Ignore balanced paren. The next entry - ;; can't be another one. - (setq containing-sexp (car (cdr c-state-cache)) - paren-state (cdr paren-state)) - ;; If there is no surrounding open paren then - ;; put the last balanced pair back on paren-state. - (setq paren-state (cons containing-sexp paren-state) - containing-sexp nil))) + (save-excursion + (goto-char (cdr containing-sexp)) + (if (and (c-major-mode-is 'c++-mode) + (c-back-over-member-initializer-braces)) + (c-syntactic-skip-backward "^}" nil t)) + (setq lim (point)) + (if paren-state + ;; Ignore balanced paren. The next entry + ;; can't be another one. + (setq containing-sexp (car paren-state) + paren-state (cdr paren-state)) + ;; If there is no surrounding open paren then + ;; put the last balanced pair back on paren-state. + (setq paren-state (cons containing-sexp paren-state) + containing-sexp nil))) (setq lim (1+ containing-sexp)))) (setq lim (point-min))) @@ -10040,16 +10202,16 @@ comment at the start of cc-engine.el for more info." (eq (char-after placeholder) ?<)))))) (c-with-syntax-table c++-template-syntax-table (goto-char placeholder) - (c-beginning-of-statement-1 lim t) - (if (save-excursion - (c-backward-syntactic-ws lim) - (eq (char-before) ?<)) - ;; In a nested template arglist. - (progn - (goto-char placeholder) - (c-syntactic-skip-backward "^,;" lim t) - (c-forward-syntactic-ws)) - (back-to-indentation))) + (c-beginning-of-statement-1 lim t)) + (if (save-excursion + (c-backward-syntactic-ws lim) + (eq (char-before) ?<)) + ;; In a nested template arglist. + (progn + (goto-char placeholder) + (c-syntactic-skip-backward "^,;" lim t) + (c-forward-syntactic-ws)) + (back-to-indentation)) ;; FIXME: Should use c-add-stmt-syntax, but it's not yet ;; template aware. (c-add-syntax 'template-args-cont (point) placeholder)) @@ -10289,7 +10451,6 @@ comment at the start of cc-engine.el for more info." (c-add-syntax 'topmost-intro-cont (c-point 'boi))) )) - ;; (CASE 6 has been removed.) ;; CASE 7: line is an expression, not a statement. Most @@ -10318,7 +10479,7 @@ comment at the start of cc-engine.el for more info." paren-state)) ;; CASE 7B: Looking at the opening brace of an - ;; in-expression block or brace list. C.f. cases 4, 16A + ;; in-expression block or brace list. C.f. cases 4, 16A ;; and 17E. ((and (eq char-after-ip ?{) (progn @@ -10440,7 +10601,7 @@ comment at the start of cc-engine.el for more info." ))) ;; CASE 9: we are inside a brace-list - ((and (not (c-major-mode-is 'awk-mode)) ; Maybe this isn't needed (ACM, 2002/3/29) + ((and (not (c-major-mode-is 'awk-mode)) ; Maybe this isn't needed (ACM, 2002/3/29) (setq special-brace-list (or (and c-special-brace-lists ;;;; ALWAYS NIL FOR AWK!! (save-excursion @@ -10492,7 +10653,7 @@ comment at the start of cc-engine.el for more info." (if (eq (point) (c-point 'boi)) (c-add-syntax 'brace-list-close (point)) (setq lim (c-most-enclosing-brace c-state-cache (point))) - (c-beginning-of-statement-1 lim) + (c-beginning-of-statement-1 lim nil nil t) (c-add-stmt-syntax 'brace-list-close nil t lim paren-state))) (t @@ -10654,9 +10815,9 @@ comment at the start of cc-engine.el for more info." )) ;; CASE 19: line is an expression, not a statement, and is directly - ;; contained by a template delimiter. Most likely, we are in a + ;; contained by a template delimiter. Most likely, we are in a ;; template arglist within a statement. This case is based on CASE - ;; 7. At some point in the future, we may wish to create more + ;; 7. At some point in the future, we may wish to create more ;; syntactic symbols such as `template-intro', ;; `template-cont-nonempty', etc., and distinguish between them as we ;; do for `arglist-intro' etc. (2009-12-07). @@ -10992,7 +11153,7 @@ Cannot combine absolute offsets %S and %S in `add' method" ;; ;; This function might do hidden buffer changes. (let* ((symbol (c-langelem-sym langelem)) - (match (assq symbol c-offsets-alist)) + (match (assq symbol c-offsets-alist)) (offset (cdr-safe match))) (if match (setq offset (c-evaluate-offset offset langelem symbol)) @@ -11063,4 +11224,8 @@ Cannot combine absolute offsets %S and %S in `add' method" (cc-provide 'cc-engine) +;;; Local Variables: +;;; indent-tabs-mode: t +;;; tab-width: 8 +;;; End: ;;; cc-engine.el ends here |