summaryrefslogtreecommitdiff
path: root/lisp/progmodes/cc-engine.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/cc-engine.el')
-rw-r--r--lisp/progmodes/cc-engine.el1748
1 files changed, 1365 insertions, 383 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index eb015acf32..ccdc1b15a6 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -83,8 +83,9 @@
;;
;; 'syntax-table
;; Used to modify the syntax of some characters. It is used to
-;; mark the "<" and ">" of angle bracket parens with paren syntax, and
-;; to "hide" obtrusive characters in preprocessor lines.
+;; mark the "<" and ">" of angle bracket parens with paren syntax, to
+;; "hide" obtrusive characters in preprocessor lines, and to mark C++
+;; raw strings to enable their fontification.
;;
;; This property is used on single characters and is therefore
;; always treated as front and rear nonsticky (or start and end open
@@ -129,6 +130,10 @@
;; 'c-decl-type-start is used when the declarators are types,
;; 'c-decl-id-start otherwise.
;;
+;; 'c-not-decl
+;; Put on the brace which introduces a brace list and on the commas
+;; which separate the element within it.
+;;
;; 'c-awk-NL-prop
;; Used in AWK mode to mark the various kinds of newlines. See
;; cc-awk.el.
@@ -229,8 +234,12 @@
;; The starting position from where we determined `c-macro-cache'.
(defvar c-macro-cache-syntactic nil)
(make-variable-buffer-local 'c-macro-cache-syntactic)
-;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a
-;; syntactic end of macro, not merely an apparent one.
+;; Either nil, or the syntactic end of the macro currently represented by
+;; `c-macro-cache'.
+(defvar c-macro-cache-no-comment nil)
+(make-variable-buffer-local 'c-macro-cache-no-comment)
+;; Either nil, or the last character of the macro currently represented by
+;; `c-macro-cache' which isn't in a comment. */
(defun c-invalidate-macro-cache (beg end)
;; Called from a before-change function. If the change region is before or
@@ -242,12 +251,14 @@
((< beg (car c-macro-cache))
(setq c-macro-cache nil
c-macro-cache-start-pos nil
- c-macro-cache-syntactic nil))
+ c-macro-cache-syntactic nil
+ c-macro-cache-no-comment nil))
((and (cdr c-macro-cache)
(< beg (cdr c-macro-cache)))
(setcdr c-macro-cache nil)
(setq c-macro-cache-start-pos beg
- c-macro-cache-syntactic nil))))
+ c-macro-cache-syntactic nil
+ c-macro-cache-no-comment nil))))
(defun c-macro-is-genuine-p ()
;; Check that the ostensible CPP construct at point is a real one. In
@@ -288,7 +299,8 @@ comment at the start of cc-engine.el for more info."
t))
(setq c-macro-cache nil
c-macro-cache-start-pos nil
- c-macro-cache-syntactic nil)
+ c-macro-cache-syntactic nil
+ c-macro-cache-no-comment nil)
(save-restriction
(if lim (narrow-to-region lim (point-max)))
@@ -297,7 +309,7 @@ comment at the start of cc-engine.el for more info."
(forward-line -1))
(back-to-indentation)
(if (and (<= (point) here)
- (looking-at c-opt-cpp-start)
+ (save-match-data (looking-at c-opt-cpp-start))
(c-macro-is-genuine-p))
(progn
(setq c-macro-cache (cons (point) nil)
@@ -323,7 +335,8 @@ comment at the start of cc-engine.el for more info."
(>= (point) (car c-macro-cache)))
(setq c-macro-cache nil
c-macro-cache-start-pos nil
- c-macro-cache-syntactic nil))
+ c-macro-cache-syntactic nil
+ c-macro-cache-no-comment nil))
(while (progn
(end-of-line)
(when (and (eq (char-before) ?\\)
@@ -347,14 +360,38 @@ comment at the start of cc-engine.el for more info."
(let* ((here (point))
(there (progn (c-end-of-macro) (point)))
s)
- (unless c-macro-cache-syntactic
+ (if c-macro-cache-syntactic
+ (goto-char c-macro-cache-syntactic)
(setq s (parse-partial-sexp here there))
(while (and (or (nth 3 s) ; in a string
(nth 4 s)) ; in a comment (maybe at end of line comment)
(> there here)) ; No infinite loops, please.
(setq there (1- (nth 8 s)))
(setq s (parse-partial-sexp here there)))
- (setq c-macro-cache-syntactic (car c-macro-cache)))
+ (setq c-macro-cache-syntactic (point)))
+ (point)))
+
+(defun c-no-comment-end-of-macro ()
+ ;; Go to the end of a CPP directive, or a pos just before which isn't in a
+ ;; comment. For this purpose, open strings are ignored.
+ ;;
+ ;; This function must only be called from the beginning of a CPP construct.
+ ;;
+ ;; Note that this function might do hidden buffer changes. See the comment
+ ;; at the start of cc-engine.el for more info.
+ (let* ((here (point))
+ (there (progn (c-end-of-macro) (point)))
+ s)
+ (if c-macro-cache-no-comment
+ (goto-char c-macro-cache-no-comment)
+ (setq s (parse-partial-sexp here there))
+ (while (and (nth 3 s) ; in a string
+ (> there here)) ; No infinite loops, please.
+ (setq here (1+ (nth 8 s)))
+ (setq s (parse-partial-sexp here there)))
+ (when (nth 4 s)
+ (goto-char (1- (nth 8 s))))
+ (setq c-macro-cache-no-comment (point)))
(point)))
(defun c-forward-over-cpp-define-id ()
@@ -385,6 +422,25 @@ comment at the start of cc-engine.el for more info."
;;; Basic utility functions.
+(defun c-delq-from-dotted-list (elt dlist)
+ ;; If ELT is a member of the (possibly dotted) list DLIST, remove all
+ ;; occurrences of it (except for any in the last cdr of DLIST).
+ ;;
+ ;; Call this as (setq DLIST (c-delq-from-dotted-list ELT DLIST)), as
+ ;; sometimes the original structure is changed, sometimes it's not.
+ ;;
+ ;; This function is needed in Emacs < 24.5, and possibly XEmacs, because
+ ;; `delq' throws an error in these versions when given a dotted list.
+ (let ((tail dlist) prev)
+ (while (consp tail)
+ (if (eq (car tail) elt)
+ (if prev
+ (setcdr prev (cdr tail))
+ (setq dlist (cdr dlist)))
+ (setq prev tail))
+ (setq tail (cdr tail)))
+ dlist))
+
(defun c-syntactic-content (from to paren-level)
;; Return the given region as a string where all syntactic
;; whitespace is removed or, where necessary, replaced with a single
@@ -1248,7 +1304,7 @@ comment at the start of cc-engine.el for more info."
c-stmt-delim-chars))
(non-skip-list
(append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
- lit-range vsemi-pos)
+ lit-range lit-start vsemi-pos)
(save-restriction
(widen)
(save-excursion
@@ -1263,8 +1319,8 @@ comment at the start of cc-engine.el for more info."
((and (bolp)
(save-excursion
(progn
- (if (setq lit-range (c-literal-limits from)) ; Have we landed in a string/comment?
- (goto-char (car lit-range)))
+ (if (setq lit-start (c-literal-start from)) ; Have we landed in a string/comment?
+ (goto-char lit-start))
(c-backward-syntactic-ws) ; ? put a limit here, maybe?
(setq vsemi-pos (point))
(c-at-vsemi-p))))
@@ -1543,7 +1599,7 @@ comment at the start of cc-engine.el for more info."
;; two newlines with horizontal whitespace between them.
;;
;; The reason to include the first following char is to cope with
-;; "rung positions" that doesn't have any ordinary whitespace. If
+;; "rung positions" that don't have any ordinary whitespace. If
;; `c-is-sws' is put on a token character it does not have
;; `c-in-sws' set simultaneously. That's the only case when that
;; can occur, and the reason for not extending the `c-in-sws'
@@ -1714,7 +1770,9 @@ comment at the start of cc-engine.el for more info."
;; if it's anything that can't start syntactic ws, so we can bail out
;; early in the majority of cases when there just are a few ws chars.
(skip-chars-forward " \t\n\r\f\v")
- (when (looking-at c-syntactic-ws-start)
+ (when (or (looking-at c-syntactic-ws-start)
+ (and c-opt-cpp-prefix
+ (looking-at c-noise-macro-name-re)))
(setq rung-end-pos (min (1+ (point)) (point-max)))
(if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
@@ -1733,6 +1791,10 @@ comment at the start of cc-engine.el for more info."
(with-silent-modifications
(while
(progn
+ ;; In the following while form, we move over a "ladder" and
+ ;; following simple WS each time round the loop, appending the WS
+ ;; onto the ladder, joining adjacent ladders, and terminating when
+ ;; there is no more WS or we reach EOB.
(while
(when (and rung-is-marked
(get-text-property (point) 'c-in-sws))
@@ -1776,6 +1838,7 @@ comment at the start of cc-engine.el for more info."
(setq rung-pos (point)
last-put-in-sws-pos rung-pos)))
+ ;; Now move over any comments (x)or a CPP construct.
(setq simple-ws-end (point))
(c-forward-comments)
@@ -1801,6 +1864,13 @@ comment at the start of cc-engine.el for more info."
(forward-line 1)
(setq safe-start t)
;; Don't cache at eob in case the buffer is narrowed.
+ (not (eobp)))
+
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-name-re))
+ ;; Skip over a noise macro.
+ (goto-char (match-end 1))
+ (setq safe-start t)
(not (eobp)))))
;; We've searched over a piece of non-white syntactic ws. See if this
@@ -1907,8 +1977,11 @@ comment at the start of cc-engine.el for more info."
(when (and (not (bobp))
(save-excursion
(backward-char)
- (looking-at c-syntactic-ws-end)))
-
+ (or (looking-at c-syntactic-ws-end)
+ (and c-opt-cpp-prefix
+ (looking-at c-symbol-char-key)
+ (progn (c-beginning-of-current-token)
+ (looking-at c-noise-macro-name-re))))))
;; Try to find a rung position in the simple ws preceding point, so that
;; we can get a cache hit even if the last bit of the simple ws has
;; changed recently.
@@ -1927,6 +2000,9 @@ comment at the start of cc-engine.el for more info."
(with-silent-modifications
(while
(progn
+ ;; Each time round the next while form, we move back over a ladder
+ ;; and append any simple WS preceding it, if possible joining with
+ ;; the previous ladder.
(while
(when (and rung-is-marked
(not (bobp))
@@ -2035,6 +2111,15 @@ comment at the start of cc-engine.el for more info."
;; narrowed out, and we can't risk marking the simple ws
;; at the end of it.
(goto-char next-rung-pos)
+ t)
+
+ ((and c-opt-cpp-prefix
+ (save-excursion
+ (and (< (skip-syntax-backward "w_") 0)
+ (progn (setq next-rung-pos (point))
+ (looking-at c-noise-macro-name-re)))))
+ ;; Skipped over a noise macro
+ (goto-char next-rung-pos)
t)))
;; We've searched over a piece of non-white syntactic ws. See if this
@@ -2198,22 +2283,128 @@ comment at the start of cc-engine.el for more info."
(defvar c-state-semi-nonlit-pos-cache nil)
(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache)
-;; A list of buffer positions which are known not to be in a literal. This is
-;; ordered with higher positions at the front of the list. Only those which
-;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid.
+;; A list of elements which are either buffer positions (when such positions
+;; are not in literals) or lists of the form (POS TYPE START), where POS is
+;; a buffer position inside a literal, TYPE is the type of the literal
+;; ('string, 'c, or 'c++) and START is the start of the literal.
(defvar c-state-semi-nonlit-pos-cache-limit 1)
(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit)
-;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This is
-;; reduced by buffer changes, and increased by invocations of
-;; `c-state-literal-at'. FIXME!!!
+;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This
+;; is reduced by buffer changes, and increased by invocations of
+;; `c-parse-ps-state-below'.
+
+(defsubst c-truncate-semi-nonlit-pos-cache (pos)
+ ;; Truncate the upper bound of the cache `c-state-semi-nonlit-pos-cache' to
+ ;; POS, if it is higher than that position.
+ (setq c-state-semi-nonlit-pos-cache-limit
+ (min c-state-semi-nonlit-pos-cache-limit pos)))
+
+(defun c-state-semi-pp-to-literal (here &optional not-in-delimiter)
+ ;; Do a parse-partial-sexp from a position in the buffer before HERE which
+ ;; isn't in a literal, and return information about HERE, either:
+ ;; (STATE TYPE BEG) if HERE is in a literal; or
+ ;; (STATE) otherwise,
+ ;; where STATE is the parsing state at HERE, TYPE is the type of the literal
+ ;; enclosing HERE, (one of 'string, 'c, 'c++) and BEG is the starting
+ ;; position of that literal (including the delimiter).
+ ;;
+ ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
+ ;; comment opener, this is recognized as being in a comment literal.
+ ;;
+ ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), 7
+ ;; (comment type), and 8 (start of comment/string), and possibly 10 (in
+ ;; newer Emacsen only, the syntax of a position after a potential first char
+ ;; of a two char construct) of STATE are valid.
+ (save-excursion
+ (save-restriction
+ (widen)
+ (save-match-data
+ (let* ((base-and-state (c-parse-ps-state-below here))
+ (base (car base-and-state))
+ (s (cdr base-and-state))
+ (s (parse-partial-sexp base here nil nil s))
+ ty)
+ (cond
+ ((or (nth 3 s) (nth 4 s)) ; in a string or comment
+ (setq ty (cond
+ ((nth 3 s) 'string)
+ ((nth 7 s) 'c++)
+ (t 'c)))
+ (list s ty (nth 8 s)))
+
+ ((and (not not-in-delimiter) ; inside a comment starter
+ (not (bobp))
+ (progn (backward-char)
+ (and (not (and (memq 'category-properties c-emacs-features)
+ (looking-at "\\s!")))
+ (looking-at c-comment-start-regexp))))
+ (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++))
+ (list s ty (point)))
+
+ (t (list s))))))))
+
+(defun c-state-full-pp-to-literal (here &optional not-in-delimiter)
+ ;; This function will supersede c-state-pp-to-literal.
+ ;;
+ ;; Do a parse-partial-sexp from a position in the buffer before HERE which
+ ;; isn't in a literal, and return information about HERE, either:
+ ;; (STATE TYPE (BEG . END)) if HERE is in a literal; or
+ ;; (STATE) otherwise,
+ ;; where STATE is the parsing state at HERE, TYPE is the type of the literal
+ ;; enclosing HERE, (one of 'string, 'c, 'c++) and (BEG . END) is the
+ ;; boundaries of that literal (including the delimiters).
+ ;;
+ ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
+ ;; comment opener, this is recognized as being in a comment literal.
+ ;;
+ ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote), 7
+ ;; (comment type), and 8 (start of comment/string), and possibly 10 (in
+ ;; newer Emacsen only, the syntax of a position after a potential first char
+ ;; of a two char construct) of STATE are valid.
+ (save-excursion
+ (save-restriction
+ (widen)
+ (save-match-data
+ (let* ((base-and-state (c-parse-ps-state-below here))
+ (base (car base-and-state))
+ (s (cdr base-and-state))
+ (s (parse-partial-sexp base here nil nil s))
+ ty start)
+ (cond
+ ((or (nth 3 s) (nth 4 s)) ; in a string or comment
+ (setq ty (cond
+ ((nth 3 s) 'string)
+ ((nth 7 s) 'c++)
+ (t 'c)))
+ (setq start (nth 8 s))
+ (parse-partial-sexp here (point-max)
+ nil ; TARGETDEPTH
+ nil ; STOPBEFORE
+ s ; OLDSTATE
+ 'syntax-table) ; stop at end of literal
+ (list s ty (cons start (point))))
+
+ ((and (not not-in-delimiter) ; inside a comment starter
+ (not (bobp))
+ (progn (backward-char)
+ (and (not (and (memq 'category-properties c-emacs-features)
+ (looking-at "\\s!")))
+ (looking-at c-comment-start-regexp))))
+ (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
+ start (point))
+ (forward-comment 1)
+ (list s ty (cons start (point))))
+
+ (t (list s))))))))
(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter)
;; Do a parse-partial-sexp from FROM to TO, returning either
;; (STATE TYPE (BEG . END)) if TO is in a literal; or
;; (STATE) otherwise,
;; where STATE is the parsing state at TO, TYPE is the type of the literal
- ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
+ ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal,
+ ;; including the delimiters.
;;
;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
;; comment opener, this is recognized as being in a comment literal.
@@ -2222,32 +2413,130 @@ comment at the start of cc-engine.el for more info."
;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
;; STATE are valid.
(save-excursion
- (let ((s (parse-partial-sexp from to))
- ty co-st)
- (cond
- ((or (nth 3 s) (nth 4 s)) ; in a string or comment
- (setq ty (cond
- ((nth 3 s) 'string)
- ((nth 7 s) 'c++)
- (t 'c)))
- (parse-partial-sexp (point) (point-max)
- nil ; TARGETDEPTH
- nil ; STOPBEFORE
- s ; OLDSTATE
- 'syntax-table) ; stop at end of literal
- `(,s ,ty (,(nth 8 s) . ,(point))))
-
- ((and (not not-in-delimiter) ; inside a comment starter
- (not (bobp))
- (progn (backward-char)
- (and (not (looking-at "\\s!"))
- (looking-at c-comment-start-regexp))))
- (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
- co-st (point))
- (forward-comment 1)
- `(,s ,ty (,co-st . ,(point))))
-
- (t `(,s))))))
+ (save-match-data
+ (let ((s (parse-partial-sexp from to))
+ ty co-st)
+ (cond
+ ((or (nth 3 s) (nth 4 s)) ; in a string or comment
+ (setq ty (cond
+ ((nth 3 s) 'string)
+ ((nth 7 s) 'c++)
+ (t 'c)))
+ (parse-partial-sexp (point) (point-max)
+ nil ; TARGETDEPTH
+ nil ; STOPBEFORE
+ s ; OLDSTATE
+ 'syntax-table) ; stop at end of literal
+ `(,s ,ty (,(nth 8 s) . ,(point))))
+
+ ((and (not not-in-delimiter) ; inside a comment starter
+ (not (bobp))
+ (progn (backward-char)
+ (and (not (looking-at "\\s!"))
+ (looking-at c-comment-start-regexp))))
+ (setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
+ co-st (point))
+ (forward-comment 1)
+ `(,s ,ty (,co-st . ,(point))))
+
+ (t `(,s)))))))
+
+(defun c-cache-to-parse-ps-state (elt)
+ ;; Create a list suitable to use as the old-state parameter to
+ ;; `parse-partial-sexp', out of ELT. ELT is either just a number, a buffer
+ ;; position, or it is a list (POS TYPE STARTING-POS). Here POS is the
+ ;; buffer position the other elements are pertinent for, TYPE is either 'c
+ ;; or 'c++ (for a comment) or a character (for a string delimiter) or t
+ ;; (meaning a string fence opened the string), STARTING-POS is the starting
+ ;; position of the comment or string.
+ (if (consp elt)
+ (let ((depth 0) (containing nil) (last nil)
+ in-string in-comment (after-quote nil)
+ (min-depth 0) com-style com-str-start (intermediate nil)
+ (between-syntax nil)
+ (type (cadr elt)))
+ (setq com-str-start (car (cddr elt)))
+ (cond
+ ((or (numberp type) (eq type t)) ; A string
+ (setq in-string type))
+ ((memq type '(c c++)) ; A comment
+ (setq in-comment t
+ com-style (if (eq type 'c++) 1 nil)))
+ (t (c-benign-error "Invalid type %s in c-cache-to-parse-ps-state"
+ elt)))
+ (list depth containing last
+ in-string in-comment after-quote
+ min-depth com-style com-str-start
+ intermediate nil))
+ (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
+
+(defun c-parse-ps-state-to-cache (state)
+ ;; Convert STATE, a `parse-partial-sexp' state valid at POINT, to an element
+ ;; for the `c-state-semi-nonlit-pos-cache' cache. This is either POINT
+ ;; (when point is not in a literal) or a list (POINT TYPE STARTING-POS),
+ ;; where TYPE is the type of the literal, either 'string, 'c, or 'c++, and
+ ;; STARTING-POS is the starting position of the comment or string.
+ (cond
+ ((nth 3 state) ; A string
+ (list (point) (nth 3 state) (nth 8 state)))
+ ((nth 4 state) ; A comment
+ (list (point)
+ (if (eq (nth 7 state) 1) 'c++ 'c)
+ (nth 8 state)))
+ (t ; Neither string nor comment.
+ (point))))
+
+(defsubst c-ps-state-cache-pos (elt)
+ ;; Get the buffer position from ELT, an element from the cache
+ ;; `c-state-semi-nonlit-pos-cache'.
+ (if (atom elt)
+ elt
+ (car elt)))
+
+(defun c-parse-ps-state-below (here)
+ ;; Given a buffer position HERE, Return a cons (CACHE-POS . STATE), where
+ ;; CACHE-POS is a position not very far before HERE for which the
+ ;; parse-partial-sexp STATE is valid. Note that the only valid elements of
+ ;; STATE are those concerning comments and strings; STATE is the state of a
+ ;; null `parse-partial-sexp' scan when CACHE-POS is not in a comment or
+ ;; string.
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let ((c c-state-semi-nonlit-pos-cache)
+ elt state pos npos high-elt)
+ ;; Trim the cache to take account of buffer changes.
+ (while (and c (> (c-ps-state-cache-pos (car c))
+ c-state-semi-nonlit-pos-cache-limit))
+ (setq c (cdr c)))
+ (setq c-state-semi-nonlit-pos-cache c)
+
+ (while (and c (> (c-ps-state-cache-pos (car c)) here))
+ (setq high-elt (car c))
+ (setq c (cdr c)))
+ (setq pos (or (and c (c-ps-state-cache-pos (car c)))
+ (point-min)))
+
+ (if high-elt
+ (setq state (c-cache-to-parse-ps-state (car c)))
+ (setq elt (if c (car c) (point-min)))
+ (setq state
+ (if c
+ (c-cache-to-parse-ps-state (car c))
+ (copy-tree '(0 nil nil nil nil nil 0 nil nil nil nil))))
+ (while
+ ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
+ (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
+ (setq state (parse-partial-sexp pos npos nil nil state))
+ (setq elt (c-parse-ps-state-to-cache state))
+ (setq c-state-semi-nonlit-pos-cache
+ (cons elt c-state-semi-nonlit-pos-cache))
+ (setq pos npos)))
+
+ (if (> pos c-state-semi-nonlit-pos-cache-limit)
+ (setq c-state-semi-nonlit-pos-cache-limit pos))
+
+ (cons pos state)))))
(defun c-state-safe-place (here)
;; Return a buffer position before HERE which is "safe", i.e. outside any
@@ -2314,45 +2603,6 @@ comment at the start of cc-engine.el for more info."
(setq c-state-nonlit-pos-cache-limit pos))
pos))))
-(defun c-state-semi-safe-place (here)
- ;; Return a buffer position before HERE which is "safe", i.e. outside any
- ;; string or comment. It may be in a macro.
- (save-restriction
- (widen)
- (save-excursion
- (let ((c c-state-semi-nonlit-pos-cache)
- pos npos high-pos lit macro-beg macro-end)
- ;; Trim the cache to take account of buffer changes.
- (while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
- (setq c (cdr c)))
- (setq c-state-semi-nonlit-pos-cache c)
-
- (while (and c (> (car c) here))
- (setq high-pos (car c))
- (setq c (cdr c)))
- (setq pos (or (car c) (point-min)))
-
- (unless high-pos
- (while
- ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
- (and
- (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
-
- ;; Test for being in a literal. If so, go to after it.
- (progn
- (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
- (or (null lit)
- (prog1 (<= (cdr lit) here)
- (setq npos (cdr lit))))))
-
- (setq pos npos)
- (setq c-state-semi-nonlit-pos-cache
- (cons pos c-state-semi-nonlit-pos-cache))))
-
- (if (> pos c-state-semi-nonlit-pos-cache-limit)
- (setq c-state-semi-nonlit-pos-cache-limit pos))
- pos))))
-
(defun c-state-literal-at (here)
;; If position HERE is inside a literal, return (START . END), the
;; boundaries of the literal (which may be outside the accessible bit of the
@@ -2670,7 +2920,11 @@ comment at the start of cc-engine.el for more info."
(setq ptr (cdr ptr)))
(when (consp ptr)
- (if (eq (cdr ptr) c-state-cache)
+ (if (or (eq (cdr ptr) c-state-cache)
+ (and (consp (cadr ptr))
+ (> (cdr (cadr ptr)) (point-min)))) ; Our new point-min is
+ ; inside a recorded
+ ; brace pair.
(setq c-state-cache nil
c-state-cache-good-pos c-state-min-scan-pos)
(setcdr ptr nil)
@@ -3249,8 +3503,7 @@ comment at the start of cc-engine.el for more info."
;; HERE.
(if (<= here c-state-nonlit-pos-cache-limit)
(setq c-state-nonlit-pos-cache-limit (1- here)))
- (if (<= here c-state-semi-nonlit-pos-cache-limit)
- (setq c-state-semi-nonlit-pos-cache-limit (1- here)))
+ (c-truncate-semi-nonlit-pos-cache here)
;; `c-state-cache':
;; Case 1: if `here' is in a literal containing point-min, everything
@@ -3521,7 +3774,7 @@ comment at the start of cc-engine.el for more info."
conses-not-ok))
(defun c-debug-parse-state ()
- (let ((here (point)) (res1 (c-real-parse-state)) res2)
+ (let ((here (point)) (min-point (point-min)) (res1 (c-real-parse-state)) res2)
(let ((c-state-cache nil)
(c-state-cache-good-pos 1)
(c-state-nonlit-pos-cache nil)
@@ -3548,8 +3801,8 @@ comment at the start of cc-engine.el for more info."
;; "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)
+ "using cache: %s, from scratch: %s. POINT-MIN: %s")
+ here res1 res2 min-point)
(message "Old state:")
(c-replay-parse-state-state))
@@ -4088,7 +4341,19 @@ comment at the start of cc-engine.el for more info."
(and
(progn
(setq search-pos (point))
- (re-search-forward regexp bound noerror))
+ (if (re-search-forward regexp bound noerror)
+ t
+ ;; Without the following, when PAREN-LEVEL it non-nil, and
+ ;; NOERROR is not nil or t, and the very first search above
+ ;; has just failed, point would end up at BOUND rather than
+ ;; just before the next close paren.
+ (when (and (eq search-pos start)
+ paren-level
+ (not (memq noerror '(nil t))))
+ (setq state (parse-partial-sexp start bound -1))
+ (if (eq (car state) -1)
+ (setq bound (1- (point)))))
+ nil))
(progn
(setq state (parse-partial-sexp
@@ -4546,8 +4811,7 @@ Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(save-restriction
(widen)
- (let* ((safe-place (c-state-semi-safe-place (point)))
- (lit (c-state-pp-to-literal safe-place (point))))
+ (let ((lit (c-state-semi-pp-to-literal (point))))
(or (cadr lit)
(and detect-cpp
(save-excursion (c-beginning-of-macro))
@@ -4569,14 +4833,20 @@ Note that this function might do hidden buffer changes. See the
comment at the start of cc-engine.el for more info."
(save-excursion
- (let* ((pos (point))
- (lim (or lim (c-state-semi-safe-place pos)))
- (pp-to-lit (save-restriction
- (widen)
- (c-state-pp-to-literal lim pos not-in-delimiter)))
- (state (car pp-to-lit))
- (lit-limits (car (cddr pp-to-lit))))
-
+ (let*
+ ((pos (point))
+ (lit-limits
+ (if lim
+ (let ((s (parse-partial-sexp lim (point))))
+ (when (or (nth 3 s) (nth 4 s))
+ (cons (nth 8 s)
+ (progn (parse-partial-sexp (point) (point-max)
+ nil nil
+ s
+ 'syntax-table)
+ (point)))))
+ (let ((pp-to-lit (c-state-full-pp-to-literal pos not-in-delimiter)))
+ (car (cddr pp-to-lit))))))
(cond
(lit-limits)
@@ -4615,6 +4885,16 @@ comment at the start of cc-engine.el for more info."
(if beg (cons beg end))))))
))))
+(defun c-literal-start (&optional safe-pos)
+ "Return the start of the string or comment surrounding point, or nil if
+point isn't in one. SAFE-POS, if non-nil, is a position before point which is
+a known \"safe position\", i.e. outside of any string or comment."
+ (if safe-pos
+ (let ((s (parse-partial-sexp safe-pos (point))))
+ (and (or (nth 3 s) (nth 4 s))
+ (nth 8 s)))
+ (car (cddr (c-state-semi-pp-to-literal (point))))))
+
;; In case external callers use this; it did have a docstring.
(defalias 'c-literal-limits-fast 'c-literal-limits)
@@ -4679,13 +4959,10 @@ comment at the start of cc-engine.el for more info."
(defsubst c-determine-limit-get-base (start try-size)
;; Get a "safe place" approximately TRY-SIZE characters before START.
- ;; This doesn't preserve point.
+ ;; This defsubst doesn't preserve point.
(let* ((pos (max (- start try-size) (point-min)))
- (base (c-state-semi-safe-place pos))
- (s (parse-partial-sexp base pos)))
- (if (or (nth 4 s) (nth 3 s)) ; comment or string
- (nth 8 s)
- (point))))
+ (s (c-state-semi-pp-to-literal pos)))
+ (or (car (cddr s)) pos)))
(defun c-determine-limit (how-far-back &optional start try-size)
;; Return a buffer position HOW-FAR-BACK non-literal characters from START
@@ -4895,6 +5172,14 @@ comment at the start of cc-engine.el for more info."
(and (< (point) cfd-limit)
(c-got-face-at (point) c-literal-faces))))
t) ; Continue the loop over pseudo matches.
+ ((and c-opt-identifier-concat-key
+ (match-string 1)
+ (save-excursion
+ (goto-char (match-beginning 1))
+ (save-match-data
+ (looking-at c-opt-identifier-concat-key))))
+ ;; Found, e.g., "::" in C++
+ t)
((and (match-string 1)
(string= (match-string 1) ":")
(save-excursion
@@ -5065,8 +5350,9 @@ comment at the start of cc-engine.el for more info."
;; arrived at something that looks like a start or else
;; resort to `c-literal-limits'.
(unless (looking-at c-literal-start-regexp)
- (let ((range (c-literal-limits)))
- (if range (goto-char (car range)))))
+ (let ((lit-start (c-literal-start)))
+ (if lit-start (goto-char lit-start)))
+ )
(setq start-in-literal (point))) ; end of `and' arm.
@@ -5577,6 +5863,9 @@ comment at the start of cc-engine.el for more info."
;; Set by c-common-init in cc-mode.el.
(defvar c-new-BEG)
(defvar c-new-END)
+;; Set by c-after-change in cc-mode.el.
+(defvar c-old-BEG)
+(defvar c-old-END)
(defun c-before-change-check-<>-operators (beg end)
;; Unmark certain pairs of "< .... >" which are currently marked as
@@ -5600,12 +5889,12 @@ comment at the start of cc-engine.el for more info."
;; 2010-01-29.
(save-excursion
(c-save-buffer-state
- ((beg-lit-limits (progn (goto-char beg) (c-literal-limits)))
+ ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
(end-lit-limits (progn (goto-char end) (c-literal-limits)))
new-beg new-end beg-limit end-limit)
;; Locate the earliest < after the barrier before the changed region,
;; which isn't already marked as a paren.
- (goto-char (if beg-lit-limits (car beg-lit-limits) beg))
+ (goto-char (or beg-lit-start beg))
(setq beg-limit (c-determine-limit 512))
;; Remove the syntax-table/category properties from each pertinent <...>
@@ -5697,6 +5986,350 @@ comment at the start of cc-engine.el for more info."
'c-decl-arg-start)))))))
(or (c-forward-<>-arglist nil)
(forward-char)))))
+
+
+;; Functions to handle C++ raw strings.
+;;
+;; A valid C++ raw string looks like
+;; R"<id>(<contents>)<id>"
+;; , where <id> is an identifier from 0 to 16 characters long, not containing
+;; spaces, control characters, double quote or left/right paren. <contents>
+;; can include anything which isn't the terminating )<id>", including new
+;; lines, "s, parentheses, etc.
+;;
+;; CC Mode handles C++ raw strings by the use of `syntax-table' text
+;; properties as follows:
+;;
+;; (i) On a validly terminated raw string, no `syntax-table' text properties
+;; are applied to the opening and closing delimiters, but any " in the
+;; contents is given the property value "punctuation" (`(1)') to prevent it
+;; interacting with the "s in the delimiters.
+;;
+;; The font locking routine `c-font-lock-c++-raw-strings' (in cc-fonts.el)
+;; recognizes valid raw strings, and fontifies the delimiters (apart from
+;; the parentheses) with the default face and the parentheses and the
+;; <contents> with font-lock-string-face.
+;;
+;; (ii) A valid, but unterminated, raw string opening delimiter gets the
+;; "punctuation" value (`(1)') of the `syntax-table' text property, and the
+;; open parenthesis gets the "string fence" value (`(15)').
+;;
+;; `c-font-lock-c++-raw-strings' puts c-font-lock-warning-face on the entire
+;; unmatched opening delimiter (from the R up to the open paren), and allows
+;; the rest of the buffer to get font-lock-string-face, caused by the
+;; unmatched "string fence" `syntax-table' text property value.
+;;
+;; (iii) Inside a macro, a valid raw string is handled as in (i). An
+;; unmatched opening delimiter is handled slightly differently. In addition
+;; to the "punctuation" and "string fence" properties on the delimiter,
+;; another "string fence" `syntax-table' property is applied to the last
+;; possible character of the macro before the terminating linefeed (if there
+;; is such a character after the "("). This "last possible" character is
+;; never a backslash escaping the end of line. If the character preceding
+;; this "last possible" character is itself a backslash, this preceding
+;; character gets a "punctuation" `syntax-table' value. If the "(" is
+;; already at the end of the macro, it gets the "punctuation" value, and no
+;; "string fence"s are used.
+;;
+;; The effect on the fontification of either of these tactics is that rest of
+;; the macro (if any) after the "(" gets font-lock-string-face, but the rest
+;; of the file is fontified normally.
+
+
+(defun c-raw-string-pos ()
+ ;; Get POINT's relationship to any containing raw string.
+ ;; If point isn't in a raw string, return nil.
+ ;; Otherwise, return the following list:
+ ;;
+ ;; (POS B\" B\( E\) E\")
+ ;;
+ ;; , where POS is the symbol `open-delim' if point is in the opening
+ ;; delimiter, the symbol `close-delim' if it's in the closing delimiter, and
+ ;; nil if it's in the string body. B\", B\(, E\), E\" are the positions of
+ ;; the opening and closing quotes and parentheses of a correctly terminated
+ ;; raw string. (N.B.: E\) and E\" are NOT on the "outside" of these
+ ;; characters.) If the raw string is not terminated, E\) and E\" are set to
+ ;; nil.
+ ;;
+ ;; Note: this routine is dependant upon the correct syntax-table text
+ ;; properties being set.
+ (let ((state (c-state-semi-pp-to-literal (point)))
+ open-quote-pos open-paren-pos close-paren-pos close-quote-pos id)
+ (save-excursion
+ (when
+ (and
+ (cond
+ ((null (cadr state))
+ (or (eq (char-after) ?\")
+ (search-backward "\"" (max (- (point) 17) (point-min)) t)))
+ ((and (eq (cadr state) 'string)
+ (goto-char (nth 2 state))
+ (or (eq (char-after) ?\")
+ (search-backward "\"" (max (- (point) 17) (point-min)) t))
+ (not (bobp)))))
+ (eq (char-before) ?R)
+ (looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)("))
+ (setq open-quote-pos (point)
+ open-paren-pos (match-end 1)
+ id (match-string-no-properties 1))
+ (goto-char (1+ open-paren-pos))
+ (when (and (not (c-get-char-property open-paren-pos 'syntax-table))
+ (search-forward (concat ")" id "\"") nil t))
+ (setq close-paren-pos (match-beginning 0)
+ close-quote-pos (1- (point))))))
+ (and open-quote-pos
+ (list
+ (cond
+ ((<= (point) open-paren-pos)
+ 'open-delim)
+ ((and close-paren-pos
+ (> (point) close-paren-pos))
+ 'close-delim)
+ (t nil))
+ open-quote-pos open-paren-pos close-paren-pos close-quote-pos))))
+
+(defun c-depropertize-raw-string (id open-quote open-paren bound)
+ ;; Point is immediately after a raw string opening delimiter. Remove any
+ ;; `syntax-table' text properties associated with the delimiter (if it's
+ ;; unmatched) or the raw string.
+ ;;
+ ;; ID, a string, is the delimiter's identifier. OPEN-QUOTE and OPEN-PAREN
+ ;; are the buffer positions of the delimiter's components. BOUND is the
+ ;; bound for searching for a matching closing delimiter; it is usually nil,
+ ;; but if we're inside a macro, it's the end of the macro.
+ ;;
+ ;; Point is moved to after the (terminated) raw string, or left after the
+ ;; unmatched opening delimiter, as the case may be. The return value is of
+ ;; no significance.
+ (let ((open-paren-prop (c-get-char-property open-paren 'syntax-table)))
+ (cond
+ ((null open-paren-prop)
+ ;; A terminated raw string
+ (when (search-forward (concat ")" id "\"") nil t)
+ (let* ((closing-paren (match-beginning 0))
+ (first-punctuation
+ (save-match-data
+ (goto-char (1+ open-paren))
+ (and (c-search-forward-char-property 'syntax-table '(1)
+ closing-paren)
+ (1- (point)))))
+ )
+ (when first-punctuation
+ (c-clear-char-property-with-value
+ first-punctuation (match-beginning 0) 'syntax-table '(1))
+ (c-truncate-semi-nonlit-pos-cache first-punctuation)
+ ))))
+ ((or (and (equal open-paren-prop '(15)) (null bound))
+ (equal open-paren-prop '(1)))
+ ;; An unterminated raw string either not in a macro, or in a macro with
+ ;; the open parenthesis right up against the end of macro
+ (c-clear-char-property open-quote 'syntax-table)
+ (c-truncate-semi-nonlit-pos-cache open-quote)
+ (c-clear-char-property open-paren 'syntax-table))
+ (t
+ ;; An unterminated string in a macro, with at least one char after the
+ ;; open paren
+ (c-clear-char-property open-quote 'syntax-table)
+ (c-truncate-semi-nonlit-pos-cache open-quote)
+ (c-clear-char-property open-paren 'syntax-table)
+ (let ((after-string-fence-pos
+ (save-excursion
+ (goto-char (1+ open-paren))
+ (c-search-forward-char-property 'syntax-table '(15) bound))))
+ (when after-string-fence-pos
+ (c-clear-char-property (1- after-string-fence-pos) 'syntax-table)))
+ ))))
+
+(defun c-depropertize-raw-strings-in-region (start finish)
+ ;; Remove any `syntax-table' text properties associated with C++ raw strings
+ ;; contained in the region (START FINISH). Point is undefined at entry and
+ ;; exit, and the return value has no significance.
+ (goto-char start)
+ (while (and (< (point) finish)
+ (re-search-forward
+ (concat "\\(" ; 1
+ c-anchored-cpp-prefix ; 2
+ "\\)\\|\\(" ; 3
+ "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" ; 4
+ "\\)")
+ finish t))
+ (when (save-excursion
+ (goto-char (match-beginning 0)) (not (c-in-literal)))
+ (if (match-beginning 4) ; the id
+ ;; We've found a raw string
+ (c-depropertize-raw-string
+ (match-string-no-properties 4) ; id
+ (1+ (match-beginning 3)) ; open quote
+ (match-end 4) ; open paren
+ nil) ; bound
+ ;; We've found a CPP construct. Search for raw strings within it.
+ (goto-char (match-beginning 2)) ; the "#"
+ (c-end-of-macro)
+ (let ((eom (point)))
+ (goto-char (match-end 2)) ; after the "#".
+ (while (and (< (point) eom)
+ (c-syntactic-re-search-forward
+ "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" eom t))
+ (c-depropertize-raw-string
+ (match-string-no-properties 1) ; id
+ (1+ (match-beginning 0)) ; open quote
+ (match-end 1) ; open paren
+ eom))))))) ; bound.
+
+(defun c-before-change-check-raw-strings (beg end)
+ ;; This function clears `syntax-table' text properties from C++ raw strings
+ ;; in the region (c-new-BEG c-new-END). BEG and END are the standard
+ ;; arguments supplied to any before-change function.
+ ;;
+ ;; Point is undefined on both entry and exit, and the return value has no
+ ;; significance.
+ ;;
+ ;; This function is called as a before-change function solely due to its
+ ;; membership of the C++ value of `c-get-state-before-change-functions'.
+ (c-save-buffer-state
+ ((beg-rs (progn (goto-char beg) (c-raw-string-pos)))
+ (beg-plus (if (null beg-rs)
+ beg
+ (max beg
+ (1+ (or (nth 4 beg-rs) (nth 2 beg-rs))))))
+ (end-rs (progn (goto-char end) (c-raw-string-pos))) ; FIXME!!!
+ ; Optimize this so that we don't call
+ ; `c-raw-string-pos' twice when once
+ ; will do. (2016-06-02).
+ (end-minus (if (null end-rs)
+ end
+ (min end (cadr end-rs))))
+ )
+ (when beg-rs
+ (setq c-new-BEG (min c-new-BEG (1- (cadr beg-rs)))))
+ (c-depropertize-raw-strings-in-region c-new-BEG beg-plus)
+
+ (when end-rs
+ (setq c-new-END (max c-new-END
+ (1+ (or (nth 4 end-rs)
+ (nth 2 end-rs))))))
+ (c-depropertize-raw-strings-in-region end-minus c-new-END)))
+
+(defun c-propertize-raw-string-opener (id open-quote open-paren bound)
+ ;; Point is immediately after a raw string opening delimiter. Apply any
+ ;; pertinent `syntax-table' text properties to the delimiter and also the
+ ;; raw string, should there be a valid matching closing delimiter.
+ ;;
+ ;; ID, a string, is the delimiter's identifier. OPEN-QUOTE and OPEN-PAREN
+ ;; are the buffer positions of the delimiter's components. BOUND is the
+ ;; bound for searching for a matching closing delimiter; it is usually nil,
+ ;; but if we're inside a macro, it's the end of the macro.
+ ;;
+ ;; Point is moved to after the (terminated) raw string, or left after the
+ ;; unmatched opening delimiter, as the case may be. The return value is of
+ ;; no significance.
+ (if (search-forward (concat ")" id "\"") bound t)
+ (let ((end-string (match-beginning 0))
+ (after-quote (match-end 0)))
+ (goto-char open-paren)
+ (while (progn (skip-syntax-forward "^\"" end-string)
+ (< (point) end-string))
+ (c-put-char-property (point) 'syntax-table '(1)) ; punctuation
+ (c-truncate-semi-nonlit-pos-cache (point))
+ (forward-char))
+ (goto-char after-quote))
+ (c-put-char-property open-quote 'syntax-table '(1)) ; punctuation
+ (c-truncate-semi-nonlit-pos-cache open-quote)
+ (c-put-char-property open-paren 'syntax-table '(15)) ; generic string
+ (when bound
+ ;; In a CPP construct, we try to apply a generic-string `syntax-table'
+ ;; text property to the last possible character in the string, so that
+ ;; only characters within the macro get "stringed out".
+ (goto-char bound)
+ (if (save-restriction
+ (narrow-to-region (1+ open-paren) (point-max))
+ (re-search-backward
+ (eval-when-compile
+ ;; This regular expression matches either an escape pair (which
+ ;; isn't an escaped NL) (submatch 5) or a non-escaped character
+ ;; (which isn't itself a backslash) (submatch 10). The long
+ ;; preambles to these (respectively submatches 2-4 and 6-9)
+ ;; ensure that we have the correct parity for sequences of
+ ;; backslashes, etc..
+ (concat "\\(" ; 1
+ "\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)*" ; 2-4
+ "\\(\\\\.\\)" ; 5
+ "\\|"
+ "\\(\\`\\|[^\\]\\|\\(\\`[^\\]?\\|[^\\][^\\]\\)\\(\\\\\\(.\\|\n\\)\\)+\\)" ; 6-9
+ "\\([^\\]\\)" ; 10
+ "\\)"
+ "\\(\\\\\n\\)*\\=")) ; 11
+ (1+ open-paren) t))
+ (if (match-beginning 10)
+ (progn
+ (c-put-char-property (match-beginning 10) 'syntax-table '(15))
+ (c-truncate-semi-nonlit-pos-cache (match-beginning 10)))
+ (c-put-char-property (match-beginning 5) 'syntax-table '(1))
+ (c-put-char-property (1+ (match-beginning 5)) 'syntax-table '(15))
+ (c-truncate-semi-nonlit-pos-cache (1+ (match-beginning 5))))
+ (c-put-char-property open-paren 'syntax-table '(1)))
+ (goto-char bound))))
+
+(defun c-after-change-re-mark-raw-strings (beg end old-len)
+ ;; This function applies `syntax-table' text properties to C++ raw strings
+ ;; beginning in the region (c-new-BEG c-new-END). BEG, END, and OLD-LEN are
+ ;; the standard arguments supplied to any after-change function.
+ ;;
+ ;; Point is undefined on both entry and exit, and the return value has no
+ ;; significance.
+ ;;
+ ;; This function is called as an after-change function solely due to its
+ ;; membership of the C++ value of `c-before-font-lock-functions'.
+ (c-save-buffer-state ()
+ ;; If the region (c-new-BEG c-new-END) has expanded, remove
+ ;; `syntax-table' text-properties from the new piece(s).
+ (when (< c-new-BEG c-old-BEG)
+ (let ((beg-rs (progn (goto-char c-old-BEG) (c-raw-string-pos))))
+ (c-depropertize-raw-strings-in-region
+ c-new-BEG
+ (if beg-rs
+ (1+ (or (nth 4 beg-rs) (nth 2 beg-rs)))
+ c-old-BEG))))
+ (when (> c-new-END c-old-END)
+ (let ((end-rs (progn (goto-char c-old-END) (c-raw-string-pos))))
+ (c-depropertize-raw-strings-in-region
+ (if end-rs
+ (cadr end-rs)
+ c-old-END)
+ c-new-END)))
+
+ (goto-char c-new-BEG)
+ (while (and (< (point) c-new-END)
+ (re-search-forward
+ (concat "\\(" ; 1
+ c-anchored-cpp-prefix ; 2
+ "\\)\\|\\(" ; 3
+ "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" ; 4
+ "\\)")
+ c-new-END t))
+ (when (save-excursion
+ (goto-char (match-beginning 0)) (not (c-in-literal)))
+ (if (match-beginning 4) ; the id
+ ;; We've found a raw string.
+ (c-propertize-raw-string-opener
+ (match-string-no-properties 4) ; id
+ (1+ (match-beginning 3)) ; open quote
+ (match-end 4) ; open paren
+ nil) ; bound
+ ;; We've found a CPP construct. Search for raw strings within it.
+ (goto-char (match-beginning 2)) ; the "#"
+ (c-end-of-macro)
+ (let ((eom (point)))
+ (goto-char (match-end 2)) ; after the "#".
+ (while (and (< (point) eom)
+ (c-syntactic-re-search-forward
+ "R\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" eom t))
+ (c-propertize-raw-string-opener
+ (match-string-no-properties 1) ; id
+ (1+ (match-beginning 0)) ; open quote
+ (match-end 1) ; open paren
+ eom)))))))) ; bound
+
;; Handling of small scale constructs like types and names.
@@ -5811,13 +6444,16 @@ comment at the start of cc-engine.el for more info."
`(c-forward-type)
`(c-forward-name)))
nil
- (and (looking-at c-keywords-regexp)
- (c-forward-keyword-clause 1))))
+ (cond ((looking-at c-keywords-regexp)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause)))))
(when (memq res '(t known found prefix maybe))
(when c-record-type-identifiers
- ,(if (eq type 'type)
- `(c-record-type-id c-last-identifier-range)
- `(c-record-ref-id c-last-identifier-range)))
+ ,(if (eq type 'type)
+ `(c-record-type-id c-last-identifier-range)
+ `(c-record-ref-id c-last-identifier-range)))
t)))
(defmacro c-forward-id-comma-list (type update-safe-pos)
@@ -5835,6 +6471,17 @@ comment at the start of cc-engine.el for more info."
(c-forward-syntactic-ws)
(c-forward-keyword-prefixed-id ,type)))))
+(defun c-forward-noise-clause ()
+ ;; Point is at a c-noise-macro-with-parens-names macro identifier. Go
+ ;; forward over this name, any parenthesis expression which follows it, and
+ ;; any syntactic WS, ending up at the next token. If there is an unbalanced
+ ;; paren expression, leave point at it. Always Return t.
+ (c-forward-token-2)
+ (if (and (eq (char-after) ?\()
+ (c-go-list-forward))
+ (c-forward-syntactic-ws))
+ t)
+
(defun c-forward-keyword-clause (match)
;; Submatch MATCH in the current match data is assumed to surround a
;; token. If it's a keyword, move over it and any immediately
@@ -5984,7 +6631,6 @@ comment at the start of cc-engine.el for more info."
;; `nconc' doesn't mind that the tail of
;; `c-record-found-types' is t.
(nconc c-record-found-types c-record-type-identifiers)))
- (if (c-major-mode-is 'java-mode) (c-fontify-recorded-types-and-refs))
t)
(goto-char start)
@@ -6030,28 +6676,31 @@ comment at the start of cc-engine.el for more info."
(progn
(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)
+ (not (equal c-inside-<>-type-key "\\(\\<\\>\\)")))
+ (c-forward-syntactic-ws)
+ (cond
+ ((eq (char-after) ??)
+ (forward-char))
+ ((and (looking-at c-identifier-start)
+ (not (looking-at c-keywords-regexp)))
+ (if (or (and all-types c-record-type-identifiers)
+ (c-major-mode-is 'java-mode))
+ ;; All encountered identifiers are types, so set the
+ ;; promote flag and parse the type.
(let ((c-promote-possible-types t)
(c-record-found-types t))
- (c-forward-type))))
+ (c-forward-type))
+ (c-forward-token-2))))
- (c-forward-syntactic-ws)
+ (c-forward-syntactic-ws)
- (when (or (looking-at "extends")
- (looking-at "super"))
- (forward-word-strictly)
- (c-forward-syntactic-ws)
- (let ((c-promote-possible-types t)
- (c-record-found-types t))
- (c-forward-type)
- (c-forward-syntactic-ws)))))
+ (when (looking-at c-inside-<>-type-key)
+ (goto-char (match-end 1))
+ (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 '<'
@@ -6372,9 +7021,7 @@ comment at the start of cc-engine.el for more info."
((and c-recognize-<>-arglists
(eq (char-after) ?<))
;; Maybe an angle bracket arglist.
- (when (let ((c-record-type-identifiers t)
- (c-record-found-types t)
- (c-last-identifier-range))
+ (when (let (c-last-identifier-range)
(c-forward-<>-arglist nil))
(c-forward-syntactic-ws)
@@ -6468,6 +7115,17 @@ comment at the start of cc-engine.el for more info."
; "typedef".
(goto-char (match-end 1))
(c-forward-syntactic-ws)
+
+ (while (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((looking-at c-pack-key)
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
+
(setq pos (point))
(setq name-res (c-forward-name))
@@ -6694,6 +7352,31 @@ comment at the start of cc-engine.el for more info."
(prog1 (car ,ps)
(setq ,ps (cdr ,ps)))))
+(defun c-back-over-compound-identifier ()
+ ;; Point is putatively just after a "compound identifier", i.e. something
+ ;; looking (in C++) like this "FQN::of::base::Class". Move to the start of
+ ;; this construct and return t. If the parsing fails, return nil, leaving
+ ;; point unchanged.
+ (let ((here (point))
+ end)
+ (if (not (c-on-identifier))
+ nil
+ (c-simple-skip-symbol-backward)
+ (while
+ (progn
+ (setq end (point))
+ (c-backward-syntactic-ws)
+ (c-backward-token-2)
+ (and
+ c-opt-identifier-concat-key
+ (looking-at c-opt-identifier-concat-key)
+ (progn
+ (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward))))
+ (setq end (point)))
+ (goto-char end)
+ t)))
+
(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 ":"
@@ -6704,7 +7387,7 @@ comment at the start of cc-engine.el for more info."
(when (not (c-go-list-backward))
(throw 'done nil))
(c-backward-syntactic-ws)
- (when (not (c-simple-skip-symbol-backward))
+ (when (not (c-back-over-compound-identifier))
(throw 'done nil))
(c-backward-syntactic-ws)
@@ -6716,7 +7399,7 @@ comment at the start of cc-engine.el for more info."
(when (not (c-go-list-backward))
(throw 'done nil))
(c-backward-syntactic-ws)
- (when (not (c-simple-skip-symbol-backward))
+ (when (not (c-back-over-compound-identifier))
(throw 'done nil))
(c-backward-syntactic-ws))
@@ -6740,7 +7423,7 @@ comment at the start of cc-engine.el for more info."
(when (not (c-go-list-backward))
(throw 'done nil))
(c-backward-syntactic-ws)
- (when (not (c-simple-skip-symbol-backward))
+ (when (not (c-back-over-compound-identifier))
(throw 'level nil))
(c-backward-syntactic-ws)))
@@ -6762,7 +7445,7 @@ comment at the start of cc-engine.el for more info."
(when (not (c-go-list-backward))
(throw 'done nil))
(c-backward-syntactic-ws))
- (when (c-simple-skip-symbol-backward)
+ (when (c-back-over-compound-identifier)
(c-backward-syntactic-ws))
(c-back-over-list-of-member-inits)
(and (eq (char-before) ?:)
@@ -6778,7 +7461,7 @@ comment at the start of cc-engine.el for more info."
(catch 'level
(goto-char pos)
(c-backward-syntactic-ws)
- (when (not (c-simple-skip-symbol-backward))
+ (when (not (c-back-over-compound-identifier))
(throw 'level nil))
(c-backward-syntactic-ws)
(c-back-over-list-of-member-inits)
@@ -6875,31 +7558,39 @@ comment at the start of cc-engine.el for more info."
;; of the while. These are, e.g. "*" in "int *foo" or "(" and
;; "*" in "int (*foo) (void)" (Note similar code in
;; `c-forward-decl-or-cast-1'.)
- (while (and (looking-at c-type-decl-prefix-key)
- (if (and (c-major-mode-is 'c++-mode)
- (match-beginning 3))
- ;; If the third submatch matches in C++ then
- ;; we're looking at an identifier that's a
- ;; prefix only if it specifies a member pointer.
- (progn
- (setq id-start (point))
- (c-forward-name)
- (if (looking-at "\\(::\\)")
- ;; We only check for a trailing "::" and
- ;; let the "*" that should follow be
- ;; matched in the next round.
- t
- ;; It turned out to be the real identifier,
- ;; so flag that and stop.
- (setq got-identifier t)
- nil))
- t))
- (if (eq (char-after) ?\()
- (progn
- (setq paren-depth (1+ paren-depth))
- (forward-char))
- (goto-char (match-end 1)))
- (c-forward-syntactic-ws))
+ (while
+ (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))
+ ((and (looking-at c-type-decl-prefix-key)
+ (if (and (c-major-mode-is 'c++-mode)
+ (match-beginning 3))
+ ;; If the third submatch matches in C++ then
+ ;; we're looking at an identifier that's a
+ ;; prefix only if it specifies a member pointer.
+ (progn
+ (setq id-start (point))
+ (c-forward-name)
+ (if (looking-at "\\(::\\)")
+ ;; We only check for a trailing "::" and
+ ;; let the "*" that should follow be
+ ;; matched in the next round.
+ t
+ ;; It turned out to be the real identifier,
+ ;; so flag that and stop.
+ (setq got-identifier t)
+ nil))
+ t))
+ (if (eq (char-after) ?\()
+ (progn
+ (setq paren-depth (1+ paren-depth))
+ (forward-char))
+ (goto-char (match-end 1)))
+ (c-forward-syntactic-ws)
+ t)))
;; If we haven't passed the identifier already, do it now.
(unless got-identifier
@@ -6924,9 +7615,13 @@ comment at the start of cc-engine.el for more info."
;; Skip over any trailing bit, such as "__attribute__".
(progn
- (when (looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
- (<= (point) limit))
+ (while (cond
+ ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
+ (<= (point) limit))
;; Search syntactically to the end of the declarator (";",
;; ",", a closing paren, eob etc) or to the beginning of an
@@ -6957,9 +7652,9 @@ comment at the start of cc-engine.el for more info."
;; If a declaration is parsed:
;;
;; The point is left at the first token after the first complete
- ;; declarator, if there is one. The return value is a cons where
- ;; the car is the position of the first token in the declarator. (See
- ;; below for the cdr.)
+ ;; declarator, if there is one. The return value is a list of 4 elements,
+ ;; where the first is the position of the first token in the declarator.
+ ;; (See below for the other three.)
;; Some examples:
;;
;; void foo (int a, char *b) stuff ...
@@ -6990,7 +7685,7 @@ comment at the start of cc-engine.el for more info."
;;
;;
;;
- ;; The cdr of the return value is non-nil when a
+ ;; The second element 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
;; `c-typedef-kwds' ("typedef") is present, and A is t when some
@@ -6998,6 +7693,10 @@ comment at the start of cc-engine.el for more info."
;; specifier is present. I.e., (some of) the declared
;; identifier(s) are types.
;;
+ ;; The third element of the return value is non-nil when the declaration
+ ;; parsed might be an expression. The fourth element is the position of
+ ;; the start of the type identifier.
+ ;;
;; If a cast is parsed:
;;
;; The point is left at the first token after the closing paren of
@@ -7017,6 +7716,8 @@ comment at the start of cc-engine.el for more info."
;; 'arglist Some other type of arglist.
;; nil Some other context or unknown context. Includes
;; within the parens of an if, for, ... construct.
+ ;; 'not-decl This value is never supplied to this function. It
+ ;; would mean we're definitely not in a declaration.
;;
;; LAST-CAST-END is the first token after the closing paren of a
;; preceding cast, or nil if none is known. If
@@ -7090,12 +7791,27 @@ comment at the start of cc-engine.el for more info."
cast-end
;; Have we got a new-style C++11 "auto"?
new-style-auto
+ ;; Set when the symbol before `preceding-token-end' is known to
+ ;; terminate the previous construct, or when we're at point-min.
+ at-decl-start
;; Save `c-record-type-identifiers' and
;; `c-record-ref-identifiers' since ranges are recorded
;; speculatively and should be thrown away if it turns out
;; that it isn't a declaration or cast.
(save-rec-type-ids c-record-type-identifiers)
- (save-rec-ref-ids c-record-ref-identifiers))
+ (save-rec-ref-ids c-record-ref-identifiers)
+ ;; Set when we parse a declaration which might also be an expression,
+ ;; such as "a *b". See CASE 16 and CASE 17.
+ maybe-expression)
+
+ (save-excursion
+ (goto-char preceding-token-end)
+ (setq at-decl-start
+ (or (bobp)
+ (let ((tok-end (point)))
+ (c-backward-token-2)
+ (member (buffer-substring-no-properties (point) tok-end)
+ c-pre-start-tokens)))))
(while (c-forward-annotation)
(c-forward-syntactic-ws))
@@ -7105,18 +7821,25 @@ comment at the start of cc-engine.el for more info."
;; macros like __INLINE__, so we recognize both types and known
;; specifiers after them too.
(while
- (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+ (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
+ (cond
;; Look for a specifier keyword clause.
- (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 (save-match-data (looking-at c-typedef-key))
- (setq at-typedef t))
+ ((or (looking-at c-prefix-spec-kwds-re)
+ (and (c-major-mode-is 'java-mode)
+ (looking-at "@[A-Za-z0-9]+")))
+ (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)
(setq kwd-clause-end (point))))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (setq noise-start (point))
+ (c-forward-noise-clause)
+ (setq kwd-clause-end (point))))
(when (setq found-type (c-forward-type t)) ; brace-block-too
;; Found a known or possible type or a prefix of a known type.
@@ -7154,16 +7877,17 @@ comment at the start of cc-engine.el for more info."
backup-at-type-decl nil
backup-maybe-typeless nil))
- (if kwd-sym
+ (if (or kwd-sym noise-start)
(progn
;; Handle known specifier keywords and
;; `c-decl-hangon-kwds' which can occur after known
;; types.
- (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
- ;; It's a hang-on keyword that can occur anywhere.
+ (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+ noise-start)
+ ;; It's a hang-on keyword or noise clause that can occur
+ ;; anywhere.
(progn
- (setq at-decl-or-cast t)
(if at-type
;; Move the identifier start position if
;; we've passed a type.
@@ -7215,8 +7939,12 @@ comment at the start of cc-engine.el for more info."
;; If a known type was found, we still need to skip over any
;; hangon keyword clauses after it. Otherwise it has already
;; been done in the loop above.
- (while (looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
+ (while
+ (cond ((looking-at c-decl-hangon-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
(setq id-start (point)))
((eq at-type 'prefix)
@@ -7297,7 +8025,10 @@ comment at the start of cc-engine.el for more info."
;; arglist paren that gets entered.
c-parse-and-markup-<>-arglists
;; Start of the identifier for which `got-identifier' was set.
- name-start)
+ name-start
+ ;; Position after (innermost) open parenthesis encountered in the
+ ;; prefix operators.
+ after-paren-pos)
(goto-char id-start)
@@ -7308,7 +8039,8 @@ comment at the start of cc-engine.el for more info."
(when (eq (char-after) ?\()
(progn
(setq paren-depth (1+ paren-depth))
- (forward-char)))
+ (forward-char)
+ (setq after-paren-pos (point))))
(while (and (looking-at c-type-decl-prefix-key)
(if (and (c-major-mode-is 'c++-mode)
(match-beginning 3))
@@ -7331,7 +8063,8 @@ comment at the start of cc-engine.el for more info."
(if (eq (char-after) ?\()
(progn
(setq paren-depth (1+ paren-depth))
- (forward-char))
+ (forward-char)
+ (setq after-paren-pos (point)))
(unless got-prefix-before-parens
(setq got-prefix-before-parens (= paren-depth 0)))
(setq got-prefix t)
@@ -7340,55 +8073,69 @@ comment at the start of cc-engine.el for more info."
(setq got-parens (> paren-depth 0))
- ;; Skip over an identifier.
+ ;; Try to skip over an identifier.
(or got-identifier
(and (looking-at c-identifier-start)
(setq pos (point))
(setq got-identifier (c-forward-name))
(setq name-start pos)))
- ;; Skip over type decl suffix operators.
- (while (if (looking-at c-type-decl-suffix-key)
+ ;; Skip over type decl suffix operators and trailing noise macros.
+ (while
+ (cond
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))
+
+ ((looking-at c-type-decl-suffix-key)
+ (if (eq (char-after) ?\))
+ (when (> paren-depth 0)
+ (setq paren-depth (1- paren-depth))
+ (forward-char)
+ t)
+ (when (if (save-match-data (looking-at "\\s("))
+ (c-safe (c-forward-sexp 1) t)
+ (goto-char (match-end 1))
+ t)
+ (when (and (not got-suffix-after-parens)
+ (= paren-depth 0))
+ (setq got-suffix-after-parens (match-beginning 0)))
+ (setq got-suffix t))))
- (if (eq (char-after) ?\))
- (when (> paren-depth 0)
- (setq paren-depth (1- paren-depth))
- (forward-char)
- t)
- (when (if (save-match-data (looking-at "\\s("))
- (c-safe (c-forward-sexp 1) t)
- (goto-char (match-end 1))
- t)
- (when (and (not got-suffix-after-parens)
- (= paren-depth 0))
- (setq got-suffix-after-parens (match-beginning 0)))
- (setq got-suffix t)))
-
- ;; No suffix matched. We might have matched the
- ;; identifier as a type and the open paren of a
- ;; function arglist as a type decl prefix. In that
- ;; case we should "backtrack": Reinterpret the last
- ;; type as the identifier, move out of the arglist and
- ;; continue searching for suffix operators.
- ;;
- ;; Do this even if there's no preceding type, to cope
- ;; with old style function declarations in K&R C,
- ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
- ;; style declarations. That isn't applicable in an
- ;; arglist context, though.
- (when (and (= paren-depth 1)
+ (t
+ ;; No suffix matched. We might have matched the
+ ;; identifier as a type and the open paren of a
+ ;; function arglist as a type decl prefix. In that
+ ;; case we should "backtrack": Reinterpret the last
+ ;; type as the identifier, move out of the arglist and
+ ;; continue searching for suffix operators.
+ ;;
+ ;; Do this even if there's no preceding type, to cope
+ ;; with old style function declarations in K&R C,
+ ;; (con|de)structors in C++ and `c-typeless-decl-kwds'
+ ;; style declarations. That isn't applicable in an
+ ;; arglist context, though.
+ (when (and (= paren-depth 1)
(not got-prefix-before-parens)
(not (eq at-type t))
(or backup-at-type
maybe-typeless
backup-maybe-typeless
(when c-recognize-typeless-decls
- (not context)))
+ (and (not context)
+ ;; Deal with C++11's "copy-initialization"
+ ;; where we have <type>(<constant>), by
+ ;; contraasting with a typeless
+ ;; <name>(<type><parameter>, ...).
+ (save-excursion
+ (goto-char after-paren-pos)
+ (c-forward-syntactic-ws)
+ (c-forward-type)))))
(setq pos (c-up-list-forward (point)))
(eq (char-before pos) ?\)))
(c-fdoc-shift-type-backward)
(goto-char pos)
- t))
+ t)))
(c-forward-syntactic-ws))
@@ -7421,11 +8168,15 @@ comment at the start of cc-engine.el for more info."
;; 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)))
+ ;; not confuse the cast check below. If we don't manage this and
+ ;; `at-decl-or-cast' is 'ids we might have an expression like
+ ;; "foo bar ({ ..." which is a valid C++11 initialization.
+ (if (and (not (c-safe (goto-char (scan-lists (point) 1 paren-depth))))
+ (eq at-decl-or-cast 'ids))
+ (c-fdoc-shift-type-backward))
;; If we've found a specifier keyword then it's a
;; declaration regardless.
- (throw 'at-decl-or-cast (eq at-decl-or-cast t)))
+ (throw 'at-decl-or-cast (memq at-decl-or-cast '(t ids))))
(setq at-decl-end
(looking-at (cond ((eq context '<>) "[,>]")
@@ -7454,16 +8205,32 @@ comment at the start of cc-engine.el for more info."
maybe-typeless
backup-maybe-typeless
(eq at-decl-or-cast t)
+ ;; Check whether we have "bar (gnu);" where we
+ ;; are directly inside a class (etc.) called "bar".
(save-excursion
- (goto-char name-start)
- (not (memq (c-forward-type) '(nil maybe))))))
+ (and
+ (progn
+ (goto-char name-start)
+ (not (memq (c-forward-type) '(nil maybe))))
+ (progn
+ (goto-char id-start)
+ (c-directly-in-class-called-p
+ (buffer-substring
+ type-start
+ (progn
+ (goto-char type-start)
+ (c-forward-type)
+ (c-backward-syntactic-ws)
+ (point)))))))))
;; Got a declaration of the form "foo bar (gnu);" or "bar
;; (gnu);" where we've recognized "bar" as the type and "gnu"
- ;; as the declarator. In this case it's however more likely
- ;; that "bar" is the declarator and "gnu" a function argument
- ;; or initializer (if `c-recognize-paren-inits' is set),
- ;; since the parens around "gnu" would be superfluous if it's
- ;; a declarator. Shift the type one step backward.
+ ;; as the declarator, and in the latter case, checked that
+ ;; "bar (gnu)" appears directly inside the class "bar". In
+ ;; this case it's however more likely that "bar" is the
+ ;; declarator and "gnu" a function argument or initializer
+ ;; (if `c-recognize-paren-inits' is set), since the parens
+ ;; around "gnu" would be superfluous if it's a declarator.
+ ;; Shift the type one step backward.
(c-fdoc-shift-type-backward)))
;; Found no identifier.
@@ -7697,12 +8464,16 @@ comment at the start of cc-engine.el for more info."
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.
+ (or (not got-suffix)
+ at-decl-start))
+ ;; 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. We only allow a suffix (which makes
+ ;; the construct look like a function call) when
+ ;; `at-decl-start' provides additional evidence that we do
+ ;; have a declaration.
+ (setq maybe-expression t)
(throw 'at-decl-or-cast t))
;; CASE 17
@@ -7714,6 +8485,7 @@ comment at the start of cc-engine.el for more info."
;; 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).
+ (setq maybe-expression t)
(throw 'at-decl-or-cast t)))
;; CASE 18
@@ -7837,9 +8609,11 @@ comment at the start of cc-engine.el for more info."
(goto-char type-start)
(c-forward-type))))
- (cons id-start
+ (list id-start
(and (or at-type-decl at-typedef)
- (cons at-type-decl at-typedef))))
+ (cons at-type-decl at-typedef))
+ maybe-expression
+ type-start))
(t
;; False alarm. Restore the recorded ranges.
@@ -8598,7 +9372,8 @@ comment at the start of cc-engine.el for more info."
(/= last-stmt-start (point))
(progn
(c-backward-syntactic-ws lim)
- (not (memq (char-before) '(?\; ?} ?: nil))))
+ (not (or (memq (char-before) '(?\; ?} ?: nil))
+ (c-at-vsemi-p))))
(save-excursion
(backward-char)
(not (looking-at "\\s(")))
@@ -8773,6 +9548,22 @@ comment at the start of cc-engine.el for more info."
(c-syntactic-skip-backward c-block-prefix-charset limit t)
(eq (char-before) ?>))))))
+ ;; Skip back over noise clauses.
+ (while (and
+ c-opt-cpp-prefix
+ (eq (char-before) ?\))
+ (let ((after-paren (point)))
+ (if (and (c-go-list-backward)
+ (progn (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward))
+ (or (looking-at c-paren-nontype-key)
+ (looking-at c-noise-macro-with-parens-name-re)))
+ (progn
+ (c-syntactic-skip-backward c-block-prefix-charset limit t)
+ t)
+ (goto-char after-paren)
+ nil))))
+
;; Note: Can't get bogus hits inside template arglists below since they
;; have gotten paren syntax above.
(when (and
@@ -8879,6 +9670,26 @@ comment at the start of cc-engine.el for more info."
kwd-start)))
+(defun c-directly-in-class-called-p (name)
+ ;; Check whether point is directly inside a brace block which is the brace
+ ;; block of a class, struct, or union which is called NAME, a string.
+ (let* ((paren-state (c-parse-state))
+ (brace-pos (c-pull-open-brace paren-state))
+ )
+ (when (eq (char-after brace-pos) ?{)
+ (goto-char brace-pos)
+ (save-excursion
+ ; *c-looking-at-decl-block
+ ; containing-sexp goto-start &optional
+ ; limit)
+ (when (and (c-looking-at-decl-block
+ (c-pull-open-brace paren-state)
+ nil)
+ (looking-at c-class-key))
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws)
+ (looking-at name))))))
+
(defun c-search-uplist-for-classkey (paren-state)
;; Check if the closest containing paren sexp is a declaration
;; block, returning a 2 element vector in that case. Aref 0
@@ -8986,6 +9797,12 @@ comment at the start of cc-engine.el for more info."
t)
((looking-at c-after-brace-list-key) t)
((looking-at c-brace-list-key) nil)
+ ((eq (char-after) ?\()
+ (and (eq (c-backward-token-2) 0)
+ (or (looking-at c-decl-hangon-key)
+ (and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re)))))
+
((and c-recognize-<>-arglists
(eq (char-after) ?<)
(looking-at "\\s("))
@@ -8994,6 +9811,169 @@ comment at the start of cc-engine.el for more info."
(or (looking-at c-brace-list-key)
(progn (goto-char here) nil))))
+(defun c-looking-at-or-maybe-in-bracelist (containing-sexp &optional lim)
+ ;; Point is at an open brace. If this starts a brace list, return the
+ ;; buffer position of the start of the construct which introduces the list.
+ ;; Otherwise, if point might be inside an enclosing brace list, return t.
+ ;; If point is definitely neither at nor in a brace list, return nil.
+ ;;
+ ;; CONTAINING-SEXP is the position of the brace/paren/braacket enclosing
+ ;; POINT, or nil if there is no such position. LIM is a backward search
+ ;; limit.
+ ;;
+ ;; Here, "brace list" does not include the body of an enum.
+ (save-excursion
+ (let ((start (point))
+ (class-key
+ ;; Pike can have class definitions anywhere, so we must
+ ;; check for the class key here.
+ (and (c-major-mode-is 'pike-mode)
+ c-decl-block-key))
+ (braceassignp 'dontknow)
+ bufpos macro-start res after-type-id-pos)
+
+ (setq res (c-backward-token-2 1 t lim))
+ ;; Checks to do only on the first sexp before the brace.
+ ;; Have we a C++ initialisation, without an "="?
+ (if (and (c-major-mode-is 'c++-mode)
+ (cond
+ ((and (not (eq res 0))
+ (c-go-up-list-backward nil lim) ; FIXME!!! Check ; `lim' 2016-07-12.
+ (eq (char-after) ?\())
+ (setq braceassignp 'c++-noassign))
+ ((looking-at c-pre-id-bracelist-key))
+ ((looking-at c-return-key))
+ ((and (looking-at c-symbol-start)
+ (not (looking-at c-keywords-regexp)))
+ (setq after-type-id-pos (point)))
+ (t nil))
+ (save-excursion
+ (cond
+ ((not (eq res 0))
+ (and (c-go-up-list-backward nil lim) ; FIXME!!! Check `lim' 2016-07-12.
+ (eq (char-after) ?\()))
+ ((looking-at c-pre-id-bracelist-key))
+ ((looking-at c-return-key))
+ (t (setq after-type-id-pos (point))
+ nil))))
+ (setq braceassignp 'c++-noassign))
+
+ (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.
+ (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)))
+
+ (cond
+ (braceassignp
+ ;; We've hit the beginning of the aggregate list.
+ (c-beginning-of-statement-1 containing-sexp)
+ (point))
+ ((and after-type-id-pos
+ (save-excursion
+ (when (eq (char-after) ?\;)
+ (c-forward-token-2 1 t))
+ (setq bufpos (point))
+ (when (looking-at c-opt-<>-sexp-key)
+ (c-forward-token-2)
+ (when (and (eq (char-after) ?<)
+ (c-get-char-property (point) 'syntax-table))
+ (c-go-list-forward nil after-type-id-pos)
+ (c-forward-syntactic-ws)))
+ (and
+ (or (not (looking-at c-class-key))
+ (save-excursion
+ (goto-char (match-end 1))
+ (c-forward-syntactic-ws)
+ (not (eq (point) after-type-id-pos))))
+ (progn
+ (setq res
+ (c-forward-decl-or-cast-1
+ (save-excursion (c-backward-syntactic-ws) (point))
+ nil nil))
+ (and (consp res)
+ (eq (car res) after-type-id-pos))))))
+ bufpos)
+ ((eq (char-after) ?\;)
+ ;; Brace lists can't contain a semicolon, so we're done.
+ ;; (setq containing-sexp nil)
+ nil)
+ ((and (setq macro-start (point))
+ (c-forward-to-cpp-define-body)
+ (eq (point) start))
+ ;; We've a macro whose expansion starts with the '{'.
+ ;; Heuristically, if we have a ';' in it we've not got a
+ ;; brace list, otherwise we have.
+ (let ((macro-end (progn (c-end-of-macro) (point))))
+ (goto-char start)
+ (forward-char)
+ (if (and (c-syntactic-re-search-forward "[;,]" macro-end t t)
+ (eq (char-before) ?\;))
+ nil
+ macro-start)))
+ (t t)) ;; The caller can go up one level.
+ )))
+
(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.
@@ -9013,13 +9993,9 @@ comment at the start of cc-engine.el for more info."
(c-backward-over-enum-header))
;; this will pick up array/aggregate init lists, even if they are nested.
(save-excursion
- (let ((class-key
- ;; Pike can have class definitions anywhere, so we must
- ;; check for the class key here.
- (and (c-major-mode-is 'pike-mode)
- c-decl-block-key))
- bufpos braceassignp lim next-containing macro-start)
- (while (and (not bufpos)
+ (let ((bufpos t)
+ lim next-containing)
+ (while (and (eq bufpos t)
containing-sexp)
(when paren-state
(if (consp (car paren-state))
@@ -9029,113 +10005,22 @@ comment at the start of cc-engine.el for more info."
(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.
- (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)))
- (cond
- (braceassignp
- ;; We've hit the beginning of the aggregate list.
- (c-beginning-of-statement-1
- (c-most-enclosing-brace paren-state))
- (setq bufpos (point)))
- ((eq (char-after) ?\;)
- ;; Brace lists can't contain a semicolon, so we're done.
- (setq containing-sexp nil))
- ((and (setq macro-start (point))
- (c-forward-to-cpp-define-body)
- (eq (point) containing-sexp))
- ;; We've a macro whose expansion starts with the '{'.
- ;; Heuristically, if we have a ';' in it we've not got a
- ;; brace list, otherwise we have.
- (let ((macro-end (progn (c-end-of-macro) (point))))
- (goto-char containing-sexp)
- (forward-char)
- (if (and (c-syntactic-re-search-forward "[;,]" macro-end t t)
- (eq (char-before) ?\;))
- (setq bufpos nil
- containing-sexp nil)
- (setq bufpos macro-start))))
- (t
- ;; Go up one level
+ (setq bufpos nil)
+ (when (or (not (eq (char-after) ?{))
+ (eq (setq bufpos (c-looking-at-or-maybe-in-bracelist
+ next-containing lim))
+ t))
(setq containing-sexp next-containing
lim nil
- next-containing nil)))))
-
- bufpos))
- ))
+ next-containing nil))))
+ (and (numberp bufpos) bufpos)))))
(defun c-looking-at-special-brace-list (&optional lim)
;; If we're looking at the start of a pike-style list, i.e., `({ })',
@@ -9231,12 +10116,27 @@ comment at the start of cc-engine.el for more info."
;; This function might do hidden buffer changes.
(save-excursion
- (let ((res 'maybe) passed-paren
+ (let ((res 'maybe) (passed-bracket-pairs 0) bracket-pos passed-paren
+ haskell-op-pos
(closest-lim (or containing-sexp lim (point-min)))
;; Look at the character after point only as a last resort
;; when we can't disambiguate.
(block-follows (and (eq (char-after) ?{) (point))))
+ ;; Search for a C++11 "->" which suggests a lambda declaration.
+ (when (and (c-major-mode-is 'c++-mode)
+ (setq haskell-op-pos
+ (save-excursion
+ (while
+ (progn
+ (c-syntactic-skip-backward "^;=}>" closest-lim t)
+ (and (eq (char-before) ?>)
+ (c-backward-token-2)
+ (not (looking-at c-haskell-op-re)))))
+ (and (looking-at c-haskell-op-re)
+ (point)))))
+ (goto-char haskell-op-pos))
+
(while (and (eq res 'maybe)
(progn (c-backward-syntactic-ws)
(> (point) closest-lim))
@@ -9274,6 +10174,11 @@ comment at the start of cc-engine.el for more info."
(zerop (c-forward-token-2 1 t)))
(eq (char-after) ?\())))
(cons 'inexpr-class (point))))
+ ((c-keyword-member kw-sym 'c-paren-any-kwds) ; e.g. C++11 "throw" or "noexcept"
+ (setq passed-paren nil)
+ (setq passed-bracket-pairs 0)
+ (setq bracket-pos nil)
+ 'maybe)
((c-keyword-member kw-sym 'c-inexpr-block-kwds)
(when (not passed-paren)
(cons 'inexpr-statement (point))))
@@ -9288,20 +10193,49 @@ comment at the start of cc-engine.el for more info."
(if (looking-at "\\s(")
(if passed-paren
- (if (and (eq passed-paren ?\[)
- (eq (char-after) ?\[))
- ;; Accept several square bracket sexps for
- ;; Java array initializations.
- 'maybe)
- (setq passed-paren (char-after))
+ (cond
+ ((and (eq passed-paren ?\[)
+ (eq (char-after) ?\[)
+ (not (eq (char-after (1+ (point))) ?\[))) ; C++ attribute.
+ ;; Accept several square bracket sexps for
+ ;; Java array initializations.
+ (setq passed-bracket-pairs (1+ passed-bracket-pairs))
+ 'maybe)
+ ((and (eq passed-paren ?\()
+ (eq (char-after) ?\[)
+ (not (eq (char-after (1+ (point))) ?\[))
+ (eq passed-bracket-pairs 0))
+ ;; C++11 lambda function declaration
+ (setq passed-bracket-pairs 1)
+ (setq bracket-pos (point))
+ 'maybe)
+ (t nil))
+ (when (not (looking-at "\\[\\["))
+ (setq passed-paren (char-after))
+ (when (eq passed-paren ?\[)
+ (setq passed-bracket-pairs 1)
+ (setq bracket-pos (point))))
'maybe)
'maybe))))
(if (eq res 'maybe)
- (when (and c-recognize-paren-inexpr-blocks
- block-follows
- containing-sexp
- (eq (char-after containing-sexp) ?\())
+ (cond
+ ((and (c-major-mode-is 'c++-mode)
+ block-follows
+ (eq passed-bracket-pairs 1)
+ (save-excursion
+ (goto-char bracket-pos)
+ (or (<= (point) (or lim (point-min)))
+ (progn
+ (c-backward-token-2 1 nil lim)
+ (and
+ (not (c-on-identifier))
+ (not (looking-at c-opt-op-identifier-prefix)))))))
+ (cons 'inlambda bracket-pos))
+ ((and c-recognize-paren-inexpr-blocks
+ block-follows
+ containing-sexp
+ (eq (char-after containing-sexp) ?\())
(goto-char containing-sexp)
(if (or (save-excursion
(c-backward-syntactic-ws lim)
@@ -9313,9 +10247,21 @@ comment at the start of cc-engine.el for more info."
(and (> (point) (or lim (point-min)))
(c-on-identifier)))
(and c-special-brace-lists
- (c-looking-at-special-brace-list)))
+ (c-looking-at-special-brace-list))
+ (and (c-major-mode-is 'c++-mode)
+ (save-excursion
+ (goto-char block-follows)
+ (if (c-go-list-forward)
+ (progn
+ (backward-char)
+ (c-syntactic-skip-backward
+ "^;," block-follows t)
+ (not (eq (char-before) ?\;)))
+ (or (not (c-syntactic-re-search-forward
+ "[;,]" nil t t))
+ (not (eq (char-before) ?\;)))))))
nil
- (cons 'inexpr-statement (point))))
+ (cons 'inexpr-statement (point)))))
res))))
@@ -9341,6 +10287,18 @@ comment at the start of cc-engine.el for more info."
paren-state)
containing-sexp)))))
+(defun c-looking-at-c++-lambda-capture-list ()
+ ;; Return non-nil if we're at the opening "[" of the capture list of a C++
+ ;; lambda function, nil otherwise.
+ (and
+ (eq (char-after) ?\[)
+ (not (eq (char-before) ?\[))
+ (not (eq (char-after (1+ (point))) ?\[))
+ (save-excursion
+ (or (eq (c-backward-token-2 1) 1)
+ (looking-at c-pre-lambda-tokens-re)))
+ (not (c-in-literal))))
+
(defun c-at-macro-vsemi-p (&optional pos)
;; Is there a "virtual semicolon" at POS or point?
;; (See cc-defs.el for full details of "virtual semicolons".)
@@ -9710,10 +10668,10 @@ comment at the start of cc-engine.el for more info."
;; CASE B.2: brace-list-open
((or (consp special-brace-list)
- (save-excursion
- (goto-char beg-of-same-or-containing-stmt)
- (c-syntactic-re-search-forward "=\\([^=]\\|$\\)"
- indent-point t t t)))
+ (numberp
+ (c-looking-at-or-maybe-in-bracelist
+ containing-sexp beg-of-same-or-containing-stmt))
+ )
;; The most semantically accurate symbol here is
;; brace-list-open, but we normally report it simply as a
;; statement-cont. The reason is that one normally adjusts
@@ -9746,6 +10704,14 @@ comment at the start of cc-engine.el for more info."
(c-add-stmt-syntax 'defun-open nil t
containing-sexp paren-state))
+ ;; CASE B.5: We have a C++11 "return \n { ..... }" Note that we're
+ ;; not at the "{", currently.
+ ((progn (goto-char indent-point)
+ (backward-sexp)
+ (looking-at c-return-key))
+ (c-add-stmt-syntax 'statement-cont nil t
+ containing-sexp paren-state))
+
;; CASE B.4: Continued statement with block open. The most
;; accurate analysis is perhaps `statement-cont' together with
;; `block-open' but we play DWIM and use `substatement-open'
@@ -9973,8 +10939,8 @@ comment at the start of cc-engine.el for more info."
;; versions, which results in that we get nil from
;; `c-literal-limits' even when `c-in-literal' claims
;; we're inside a comment.
- (setq placeholder (c-literal-limits lim)))
- (c-add-syntax literal (car placeholder)))
+ (setq placeholder (c-literal-start lim)))
+ (c-add-syntax literal placeholder))
;; CASE 3: in a cpp preprocessor macro continuation.
((and (save-excursion
@@ -10246,9 +11212,12 @@ comment at the start of cc-engine.el for more info."
;; CASE 5A.3: brace list open
((save-excursion
(c-beginning-of-decl-1 lim)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws indent-point))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
(setq placeholder (c-point 'boi))
(or (consp special-brace-list)
(and (or (save-excursion
@@ -10262,7 +11231,14 @@ comment at the start of cc-engine.el for more info."
(looking-at c-opt-inexpr-brace-list-key)
(setq tmpsymbol 'topmost-intro-cont)))
(looking-at "=\\([^=]\\|$\\)"))
- (looking-at c-brace-list-key))
+ (looking-at c-brace-list-key)
+ (looking-at c-return-key)
+ (save-excursion
+ (and (c-forward-type)
+ (looking-at c-identifier-start)
+ (not (looking-at c-keywords-regexp))
+ (c-forward-token-2)
+ (eq (point) (c-point 'boi indent-point)))))
(save-excursion
(while (and (< (point) indent-point)
(zerop (c-forward-token-2 1 t))
@@ -10300,9 +11276,12 @@ comment at the start of cc-engine.el for more info."
(t
(save-excursion
(c-beginning-of-decl-1 lim)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws indent-point))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
(c-add-syntax 'defun-open (c-point 'boi))
;; Bogus to use bol here, but it's the legacy. (Resolved,
;; 2007-11-09)
@@ -10933,9 +11912,12 @@ comment at the start of cc-engine.el for more info."
(c-beginning-of-statement-1
(c-safe-position (1- containing-sexp) paren-state))
(c-forward-token-2 0)
- (while (looking-at c-specifier-key)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws))
+ (while (cond
+ ((looking-at c-specifier-key)
+ (c-forward-keyword-clause 1))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))))
(c-add-syntax 'brace-list-open (c-point 'boi))))
;; CASE 9B: brace-list-close brace