X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/821ff7208c4a8fb4b12a0ea8039006d2b2e57463..020716e178cdae443a3630c4307023cb3fc4c350:/lisp/progmodes/cc-engine.el diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index a1cbdc1656..bc42e1032a 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -705,7 +705,7 @@ comment at the start of cc-engine.el for more info." ;; The last position where a label is possible provided the ;; statement started there. It's nil as long as no invalid ;; label content has been found (according to - ;; `c-nonlabel-token-key'. It's `start' if no valid label + ;; `c-nonlabel-token-key'). It's `start' if no valid label ;; content was found in the label. Note that we might still ;; regard it a label if it starts with `c-label-kwds'. label-good-pos @@ -1035,7 +1035,12 @@ comment at the start of cc-engine.el for more info." ;; (including a case label) or something like C++'s "public:"? ;; A case label might use an expression rather than a token. (setq after-case:-pos (or tok start)) - (if (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'" + (if (or (looking-at c-nonlabel-token-key) ; e.g. "while" or "'a'" + ;; Catch C++'s inheritance construct "class foo : bar". + (save-excursion + (and + (c-safe (c-backward-sexp) t) + (looking-at c-nonlabel-token-2-key)))) (setq c-maybe-labelp nil) (if after-labels-pos ; Have we already encountered a label? (if (not last-label-pos) @@ -2456,7 +2461,7 @@ comment at the start of cc-engine.el for more info." (<= from (cdr c-state-brace-pair-desert))) ;; Only search what we absolutely need to: (if (and c-state-brace-pair-desert - (> from (cdr c-state-brace-pair-desert))) + (eq cache-pos (car c-state-brace-pair-desert))) (narrow-to-region (cdr c-state-brace-pair-desert) (point-max))) ;; In the next pair of nested loops, the inner one moves back past a @@ -3127,6 +3132,33 @@ comment at the start of cc-engine.el for more info." (unless (fboundp 'c-real-parse-state) (fset 'c-real-parse-state (symbol-function 'c-parse-state))) (cc-bytecomp-defun c-real-parse-state) + +(defvar c-parse-state-state nil) +(defun c-record-parse-state-state () + (setq c-parse-state-state + (mapcar + (lambda (arg) + (cons arg (symbol-value arg))) + '(c-state-cache + c-state-cache-good-pos + c-state-nonlit-pos-cache + c-state-nonlit-pos-cache-limit + c-state-brace-pair-desert + c-state-point-min + c-state-point-min-lit-type + c-state-point-min-lit-start + c-state-min-scan-pos + c-state-old-cpp-beg + c-state-old-cpp-end)))) +(defun c-replay-parse-state-state () + (message + (concat "(setq " + (mapconcat + (lambda (arg) + (format "%s %s%s" (car arg) (if (atom (cdr arg)) "" "'") (cdr arg))) + c-parse-state-state " ") + ")"))) + (defun c-debug-parse-state () (let ((here (point)) (res1 (c-real-parse-state)) res2) (let ((c-state-cache nil) @@ -3145,15 +3177,21 @@ comment at the start of cc-engine.el for more info." ;; The cache can actually go further back due to the ad-hoc way ;; the first paren is found, so try to whack off a bit of its ;; start before complaining. - (save-excursion - (goto-char (or (c-least-enclosing-brace res2) (point))) - (c-beginning-of-defun-1) - (while (not (or (bobp) (eq (char-after) ?{))) - (c-beginning-of-defun-1)) - (unless (equal (c-whack-state-before (point) res1) res2) - (message (concat "c-parse-state inconsistency at %s: " - "using cache: %s, from scratch: %s") - here res1 res2)))) + ;; (save-excursion + ;; (goto-char (or (c-least-enclosing-brace res2) (point))) + ;; (c-beginning-of-defun-1) + ;; (while (not (or (bobp) (eq (char-after) ?{))) + ;; (c-beginning-of-defun-1)) + ;; (unless (equal (c-whack-state-before (point) res1) res2) + ;; (message (concat "c-parse-state inconsistency at %s: " + ;; "using cache: %s, from scratch: %s") + ;; here res1 res2))) + (message (concat "c-parse-state inconsistency at %s: " + "using cache: %s, from scratch: %s") + here res1 res2) + (message "Old state:") + (c-replay-parse-state-state)) + (c-record-parse-state-state) res1)) (defun c-toggle-parse-state-debug (&optional arg) @@ -8004,6 +8042,29 @@ comment at the start of cc-engine.el for more info." (back-to-indentation) (vector (point) open-paren-pos)))))) +(defmacro c-pull-open-brace (ps) + ;; Pull the next open brace from PS (which has the form of paren-state), + ;; skipping over any brace pairs. Returns NIL when PS is exhausted. + `(progn + (while (consp (car ,ps)) + (setq ,ps (cdr ,ps))) + (prog1 (car ,ps) + (setq ,ps (cdr ,ps))))) + +(defun c-most-enclosing-decl-block (paren-state) + ;; Return the buffer position of the most enclosing decl-block brace (in the + ;; sense of c-looking-at-decl-block) in the PAREN-STATE structure, or nil if + ;; none was found. + (let* ((open-brace (c-pull-open-brace paren-state)) + (next-open-brace (c-pull-open-brace paren-state))) + (while (and open-brace + (save-excursion + (goto-char open-brace) + (not (c-looking-at-decl-block next-open-brace nil)))) + (setq open-brace next-open-brace + next-open-brace (c-pull-open-brace paren-state))) + open-brace)) + (defun c-inside-bracelist-p (containing-sexp paren-state) ;; return the buffer position of the beginning of the brace list ;; statement if we're inside a brace list, otherwise return nil.