;; 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
;; (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)
pos))
(defsubst c-state-cache-non-literal-place (pos state)
- ;; Return a position outside of a string/comment at or before POS.
+ ;; Return a position outside of a string/comment/macro at or before POS.
;; STATE is the parse-partial-sexp state at POS.
- (if (or (nth 3 state) ; in a string?
- (nth 4 state)) ; in a comment?
- (nth 8 state)
- pos))
-
+ (let ((res (if (or (nth 3 state) ; in a string?
+ (nth 4 state)) ; in a comment?
+ (nth 8 state)
+ pos)))
+ (save-excursion
+ (goto-char res)
+ (if (c-beginning-of-macro)
+ (point)
+ res))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Stuff to do with point-min, and coping with any literal there.
(<= 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
(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)
;; 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)
(let* ((start (point)) kwd-sym kwd-clause-end found-type)
;; Look for a specifier keyword clause.
- (when (looking-at c-prefix-spec-kwds-re)
+ (when (or (looking-at c-prefix-spec-kwds-re)
+ (and (c-major-mode-is 'java-mode)
+ (looking-at "@[A-Za-z0-9]+")))
(if (looking-at c-typedef-key)
(setq at-typedef t))
(setq kwd-sym (c-keyword-sym (match-string 1)))
(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.