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.el858
1 files changed, 616 insertions, 242 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 2631c24f8db..f7320da5629 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -146,11 +146,6 @@
;; "typedef" keyword. It's value is a list of the identifiers that
;; the "typedef" declares as types.
;;
-;; 'c-<>-c-types-set
-;; This property is set on an opening angle bracket, and indicates that
-;; any "," separators within the template/generic expression have been
-;; marked with a 'c-type property value 'c-<>-arg-sep (see above).
-;;
;; 'c-awk-NL-prop
;; Used in AWK mode to mark the various kinds of newlines. See
;; cc-awk.el.
@@ -1651,7 +1646,7 @@ This function does not do any hidden buffer changes."
;; comment, but XEmacs doesn't. We depend on the Emacs
;; behavior (which also is symmetric).
(if (and (eolp) (elt (parse-partial-sexp start (point)) 7))
- (condition-case nil (forward-char 1)))
+ (forward-char 1))
t))))
@@ -5915,19 +5910,21 @@ comment at the start of cc-engine.el for more info."
(cond
((> pos start) ; Nothing but literals
base)
- ((> base (point-min))
+ ((and
+ (> base (point-min))
+ (> (- base try-size) (point-min))) ; prevent infinite recursion.
(c-determine-limit how-far-back base (* 2 try-size) org-start))
(t base)))
((>= count how-far-back)
(c-determine-limit-no-macro
- (+ (car elt) (- count how-far-back))
- org-start))
+ (+ (car elt) (- count how-far-back))
+ org-start))
((eq base (point-min))
(point-min))
((> base (- start try-size)) ; Can only happen if we hit point-min.
(c-determine-limit-no-macro
- (car elt)
- org-start))
+ (car elt)
+ org-start))
(t
(c-determine-limit (- how-far-back count) base (* 2 try-size)
org-start))))))
@@ -6170,12 +6167,18 @@ comment at the start of cc-engine.el for more info."
(cons (point)
(cons bound-<> s)))))
+(defvar c-record-type-identifiers) ; Specially for `c-brace-stack-at'.
+
(defun c-brace-stack-at (here)
;; Given a buffer position HERE, Return the value of the brace stack there.
(save-excursion
(save-restriction
(widen)
- (let ((c c-bs-cache)
+ (let (c-record-type-identifiers ; In case `c-forward-<>-arglist' would
+ ; otherwise record identifiers outside
+ ; of the restriction in force before
+ ; this function.
+ (c c-bs-cache)
(can-use-prev (<= c-bs-prev-pos c-bs-cache-limit))
elt stack pos npos high-elt)
;; Trim the cache to take account of buffer changes.
@@ -8288,10 +8291,17 @@ multi-line strings (but not C++, for example)."
(setq c-record-ref-identifiers
(cons range c-record-ref-identifiers))))))
-(defmacro c-forward-keyword-prefixed-id (type)
+(defmacro c-forward-keyword-prefixed-id (type &optional stop-at-end)
;; Used internally in `c-forward-keyword-clause' to move forward
;; over a type (if TYPE is 'type) or a name (otherwise) which
;; possibly is prefixed by keywords and their associated clauses.
+ ;; Point should be at the type/name or a preceding keyword at the start of
+ ;; the macro, and it is left at the first token following the type/name,
+ ;; or (when STOP-AT-END is non-nil) immediately after that type/name.
+ ;;
+ ;; Note that both parameters are evaluated at compile time, not run time,
+ ;; so they must be constants.
+ ;;
;; Try with a type/name first to not trip up on those that begin
;; with a keyword. Return t if a known or found type is moved
;; over. The point is clobbered if nil is returned. If range
@@ -8300,51 +8310,84 @@ multi-line strings (but not C++, for example)."
;;
;; This macro might do hidden buffer changes.
(declare (debug t))
- `(let (res)
+ `(let (res pos)
(setq c-last-identifier-range nil)
(while (if (setq res ,(if (eq type 'type)
- '(c-forward-type)
- '(c-forward-name)))
- nil
- (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)))))
+ `(c-forward-type nil ,stop-at-end)
+ `(c-forward-name ,stop-at-end)))
+ (progn
+ (setq pos (point))
+ nil)
+ (and
+ (cond ((looking-at c-keywords-regexp)
+ (c-forward-keyword-clause 1 t))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause t)))
+ (progn
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ t))))
(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)))
+ (when pos
+ (goto-char pos)
+ ,(unless stop-at-end
+ `(c-forward-syntactic-ws)))
t)))
-(defmacro c-forward-id-comma-list (type update-safe-pos)
+(defmacro c-forward-id-comma-list (type update-safe-pos &optional stop-at-end)
;; Used internally in `c-forward-keyword-clause' to move forward
;; over a comma separated list of types or names using
- ;; `c-forward-keyword-prefixed-id'.
+ ;; `c-forward-keyword-prefixed-id'. Point should start at the first token
+ ;; after the already scanned type/name, or (if STOP-AT-END is non-nil)
+ ;; immediately after that type/name. Point is left either before or
+ ;; after the whitespace following the last type/name in the list, depending
+ ;; on whether STOP-AT-END is non-nil or nil. The return value is without
+ ;; significance.
+ ;;
+ ;; Note that all three parameters are evaluated at compile time, not run
+ ;; time, so they must be constants.
;;
;; This macro might do hidden buffer changes.
(declare (debug t))
- `(while (and (progn
- ,(when update-safe-pos
- '(setq safe-pos (point)))
- (eq (char-after) ?,))
- (progn
- (forward-char)
- (c-forward-syntactic-ws)
- (c-forward-keyword-prefixed-id ,type)))))
+ `(let ((pos (point)))
+ (while (and (progn
+ ,(when update-safe-pos
+ `(setq safe-pos (point)))
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (eq (char-after) ?,))
+ (progn
+ (forward-char)
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-keyword-prefixed-id ,type t))))
+ (goto-char pos)
+ ,(unless stop-at-end
+ `(c-forward-syntactic-ws))))
-(defun c-forward-noise-clause ()
+(defun c-forward-noise-clause (&optional stop-at-end)
;; 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 or EOB. If there is an
+ ;; any syntactic WS, ending up either at the next token or EOB or (when
+ ;; STOP-AT-END is non-nil) directly after the clause. If there is an
;; unbalanced paren expression, leave point at it. Always Return t.
- (or (zerop (c-forward-token-2))
- (goto-char (point-max)))
- (if (and (eq (char-after) ?\()
- (c-go-list-forward))
+ (let (pos)
+ (or (c-forward-over-token)
+ (goto-char (point-max)))
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (when (and (eq (char-after) ?\()
+ (c-go-list-forward))
+ (setq pos (point)))
+ (goto-char pos)
+ (unless stop-at-end
(c-forward-syntactic-ws))
- t)
+ t))
(defun c-forward-noise-clause-not-macro-decl (maybe-parens)
;; Point is at a noise macro identifier, which, when MAYBE-PARENS is
@@ -8378,11 +8421,12 @@ multi-line strings (but not C++, for example)."
(goto-char here)
nil)))
-(defun c-forward-keyword-clause (match)
+(defun c-forward-keyword-clause (match &optional stop-at-end)
;; Submatch MATCH in the current match data is assumed to surround a
;; token. If it's a keyword, move over it and any immediately
- ;; following clauses associated with it, stopping at the start of
- ;; the next token. t is returned in that case, otherwise the point
+ ;; following clauses associated with it, stopping either at the start
+ ;; of the next token, or (when STOP-AT-END is non-nil) at the end
+ ;; of the clause. t is returned in that case, otherwise the point
;; stays and nil is returned. The kind of clauses that are
;; recognized are those specified by `c-type-list-kwds',
;; `c-ref-list-kwds', `c-colon-type-list-kwds',
@@ -8412,19 +8456,23 @@ multi-line strings (but not C++, for example)."
(when kwd-sym
(goto-char (match-end match))
- (c-forward-syntactic-ws)
(setq safe-pos (point))
+ (c-forward-syntactic-ws)
(cond
((and (c-keyword-member kwd-sym 'c-type-list-kwds)
- (c-forward-keyword-prefixed-id type))
+ (c-forward-keyword-prefixed-id type t))
;; There's a type directly after a keyword in `c-type-list-kwds'.
- (c-forward-id-comma-list type t))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list type t t))
((and (c-keyword-member kwd-sym 'c-ref-list-kwds)
- (c-forward-keyword-prefixed-id ref))
+ (c-forward-keyword-prefixed-id ref t))
;; There's a name directly after a keyword in `c-ref-list-kwds'.
- (c-forward-id-comma-list ref t))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list ref t t))
((and (c-keyword-member kwd-sym 'c-paren-any-kwds)
(eq (char-after) ?\())
@@ -8444,20 +8492,20 @@ multi-line strings (but not C++, for example)."
(goto-char (match-end 0)))))
(goto-char pos)
- (c-forward-syntactic-ws)
- (setq safe-pos (point))))
+ (setq safe-pos (point)))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds)
(eq (char-after) ?<)
(c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)))
- (c-forward-syntactic-ws)
- (setq safe-pos (point)))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds)
(not (looking-at c-symbol-start))
(c-safe (c-forward-sexp) t))
- (c-forward-syntactic-ws)
- (setq safe-pos (point)))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-protection-kwds)
(or (null c-post-protection-token)
@@ -8467,8 +8515,8 @@ multi-line strings (but not C++, for example)."
(not (c-end-of-current-token))))))
(if c-post-protection-token
(goto-char (match-end 0)))
- (c-forward-syntactic-ws)
- (setq safe-pos (point))))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)))
(when (c-keyword-member kwd-sym 'c-colon-type-list-kwds)
(if (eq (char-after) ?:)
@@ -8477,8 +8525,10 @@ multi-line strings (but not C++, for example)."
(progn
(forward-char)
(c-forward-syntactic-ws)
- (when (c-forward-keyword-prefixed-id type)
- (c-forward-id-comma-list type t)))
+ (when (c-forward-keyword-prefixed-id type t)
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list type t t)))
;; Not at the colon, so stop here. But the identifier
;; ranges in the type list later on should still be
;; recorded.
@@ -8488,15 +8538,18 @@ multi-line strings (but not C++, for example)."
;; this one, we move forward to the colon following the
;; clause matched above.
(goto-char safe-pos)
+ (c-forward-syntactic-ws)
(c-forward-over-colon-type-list))
(progn
(c-forward-syntactic-ws)
- (c-forward-keyword-prefixed-id type))
+ (c-forward-keyword-prefixed-id type t))
;; There's a type after the `c-colon-type-list-re' match
;; after a keyword in `c-colon-type-list-kwds'.
(c-forward-id-comma-list type nil))))
(goto-char safe-pos)
+ (unless stop-at-end
+ (c-forward-syntactic-ws))
t)))
;; cc-mode requires cc-fonts.
@@ -8578,11 +8631,9 @@ multi-line strings (but not C++, for example)."
;; List that collects the positions after the argument
;; separating ',' in the arglist.
arg-start-pos)
- ;; If the '<' has paren open syntax then we've marked it as an angle
- ;; bracket arglist before, so skip to the end.
- (if (and syntax-table-prop-on-<
- (or (not c-parse-and-markup-<>-arglists)
- (c-get-char-property (point) 'c-<>-c-types-set)))
+ (if (and (not c-parse-and-markup-<>-arglists)
+ syntax-table-prop-on-<)
+
(progn
(forward-char)
(if (and (c-go-up-list-forward)
@@ -8679,7 +8730,6 @@ multi-line strings (but not C++, for example)."
(c-unmark-<->-as-paren (point)))))
(c-mark-<-as-paren start)
(c-mark->-as-paren (1- (point)))
- (c-put-char-property start 'c-<>-c-types-set t)
(c-truncate-lit-pos-cache start))
(setq res t)
nil)) ; Exit the loop.
@@ -8827,11 +8877,12 @@ multi-line strings (but not C++, for example)."
(/= (point) start))))
-(defun c-forward-name ()
- ;; Move forward over a complete name if at the beginning of one,
- ;; stopping at the next following token. A keyword, as such,
- ;; doesn't count as a name. If the point is not at something that
- ;; is recognized as a name then it stays put.
+(defun c-forward-name (&optional stop-at-end)
+ ;; Move forward over a complete name if at the beginning of one, stopping
+ ;; either at the next following token or (when STOP-AT-END is non-nil) at
+ ;; the end of the name. A keyword, as such, doesn't count as a name. If
+ ;; the point is not at something that is recognized as a name then it stays
+ ;; put.
;;
;; A name could be something as simple as "foo" in C or something as
;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> ::
@@ -8853,7 +8904,7 @@ multi-line strings (but not C++, for example)."
;;
;; This function might do hidden buffer changes.
- (let ((pos (point)) (start (point)) res id-start id-end
+ (let ((pos (point)) pos2 pos3 (start (point)) res id-start id-end
;; Turn off `c-promote-possible-types' here since we might
;; call `c-forward-<>-arglist' and we don't want it to promote
;; every suspect thing in the arglist to a type. We're
@@ -8895,7 +8946,7 @@ multi-line strings (but not C++, for example)."
(c-forward-syntactic-ws lim+)
(cond ((eq (char-before id-end) ?e)
;; Got "... ::template".
- (let ((subres (c-forward-name)))
+ (let ((subres (c-forward-name t)))
(when subres
(setq pos (point)
res subres))))
@@ -8907,7 +8958,7 @@ multi-line strings (but not C++, for example)."
(and (eq (c-forward-token-2) 0)
(not (eq (char-after) ?\())))))
;; Got a cast operator.
- (when (c-forward-type)
+ (when (c-forward-type nil t)
(setq pos (point)
res 'operator)
;; Now we should match a sequence of either
@@ -8931,8 +8982,8 @@ multi-line strings (but not C++, for example)."
(forward-char)
t)))))
(while (progn
- (c-forward-syntactic-ws lim+)
(setq pos (point))
+ (c-forward-syntactic-ws lim+)
(and
(<= (point) lim+)
(looking-at c-opt-type-modifier-key)))
@@ -8947,30 +8998,34 @@ multi-line strings (but not C++, for example)."
;; operator"" has an (?)optional tag after it.
(progn
(goto-char (match-end 0))
+ (setq pos2 (point))
(c-forward-syntactic-ws lim+)
(when (c-on-identifier)
- (c-forward-token-2 1 nil lim+)))
- (goto-char (match-end 0))
- (c-forward-syntactic-ws lim+))
- (setq pos (point)
+ (c-forward-over-token nil lim+)))
+ (goto-char (match-end 0))
+ (setq pos2 (point))
+ (c-forward-syntactic-ws lim+))
+ (setq pos pos2
res 'operator)))
nil)
;; `id-start' is equal to `id-end' if we've jumped over
;; an identifier that doesn't end with a symbol token.
- ;; That can occur e.g. for Java import directives on the
+ ;; That can occur e.g. for Java import directives of the
;; form "foo.bar.*".
(when (and id-start (/= id-start id-end))
(setq c-last-identifier-range
(cons id-start id-end)))
(goto-char id-end)
+ (setq pos (point))
(c-forward-syntactic-ws lim+)
- (setq pos (point)
- res t)))
+ (setq res t)))
(progn
(goto-char pos)
+ (c-forward-syntactic-ws lim+)
+ (setq pos3 (point))
(when (or c-opt-identifier-concat-key
c-recognize-<>-arglists)
@@ -8981,7 +9036,6 @@ multi-line strings (but not C++, for example)."
;; cases with tricky syntactic whitespace that aren't
;; covered in `c-identifier-key'.
(goto-char (match-end 0))
- (c-forward-syntactic-ws lim+)
t)
((and c-recognize-<>-arglists
@@ -8993,11 +9047,12 @@ multi-line strings (but not C++, for example)."
;; `lim+'.
(setq lim+ (c-determine-+ve-limit 500))
+ (setq pos2 (point))
(c-forward-syntactic-ws lim+)
(unless (eq (char-after) ?\()
(setq c-last-identifier-range nil)
- (c-add-type start (1+ pos)))
- (setq pos (point))
+ (c-add-type start (1+ pos3)))
+ (setq pos pos2)
(if (and c-opt-identifier-concat-key
(looking-at c-opt-identifier-concat-key))
@@ -9007,7 +9062,7 @@ multi-line strings (but not C++, for example)."
(progn
(when (and c-record-type-identifiers id-start)
(c-record-ref-id (cons id-start id-end)))
- (forward-char 2)
+ (goto-char (match-end 0))
(c-forward-syntactic-ws lim+)
t)
@@ -9019,11 +9074,14 @@ multi-line strings (but not C++, for example)."
)))))
(goto-char pos)
+ (unless stop-at-end
+ (c-forward-syntactic-ws lim+))
res))
-(defun c-forward-type (&optional brace-block-too)
+(defun c-forward-type (&optional brace-block-too stop-at-end)
;; Move forward over a type spec if at the beginning of one,
- ;; stopping at the next following token. The keyword "typedef"
+ ;; stopping at the next following token (if STOP-AT-END is nil) or
+ ;; at the end of the type spec (otherwise). The keyword "typedef"
;; isn't part of a type spec here.
;;
;; BRACE-BLOCK-TOO, when non-nil, means move over the brace block in
@@ -9062,7 +9120,7 @@ multi-line strings (but not C++, for example)."
(c-forward-syntactic-ws))
(let ((start (point)) pos res name-res id-start id-end id-range
- post-prefix-pos)
+ post-prefix-pos prefix-end-pos)
;; Skip leading type modifiers. If any are found we know it's a
;; prefix of a type.
@@ -9072,6 +9130,8 @@ multi-line strings (but not C++, for example)."
(when (looking-at c-no-type-key)
(setq res 'no-id)))
(goto-char (match-end 1))
+ (setq prefix-end-pos (point))
+ (setq pos (point))
(c-forward-syntactic-ws)
(or (eq res 'no-id)
(setq res 'prefix))))
@@ -9080,32 +9140,41 @@ multi-line strings (but not C++, for example)."
(cond
((looking-at c-typeof-key) ; e.g. C++'s "decltype".
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
(setq res (and (eq (char-after) ?\()
(c-safe (c-forward-sexp))
'decltype))
(if res
- (c-forward-syntactic-ws)
+ (progn
+ (setq pos (point))
+ (c-forward-syntactic-ws))
(goto-char start)))
((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT
; "typedef".
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
(while (cond
((looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
+ (c-forward-keyword-clause 1 t)
+ (setq pos (point))
+ (c-forward-syntactic-ws))
((looking-at c-pack-key)
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws))
((and c-opt-cpp-prefix
(looking-at c-noise-macro-with-parens-name-re))
- (c-forward-noise-clause))))
+ (c-forward-noise-clause t)
+ (setq pos (point))
+ (c-forward-syntactic-ws))))
+ (setq id-start (point))
+ (setq name-res (c-forward-name t))
(setq pos (point))
-
- (setq name-res (c-forward-name))
(setq res (not (null name-res)))
(when (eq name-res t)
;; With some keywords the name can be used without the prefix, so we
@@ -9113,21 +9182,21 @@ multi-line strings (but not C++, for example)."
(when (save-excursion
(goto-char post-prefix-pos)
(looking-at c-self-contained-typename-key))
- (c-add-type pos (save-excursion
- (c-backward-syntactic-ws)
- (point))))
+ (c-add-type id-start
+ (point)))
(when (and c-record-type-identifiers
c-last-identifier-range)
(c-record-type-id c-last-identifier-range)))
+ (c-forward-syntactic-ws)
(when (and brace-block-too
(memq res '(t nil))
(eq (char-after) ?\{)
(save-excursion
(c-safe
(progn (c-forward-sexp)
- (c-forward-syntactic-ws)
(setq pos (point))))))
(goto-char pos)
+ (c-forward-syntactic-ws)
(setq res t))
(unless res (goto-char start))) ; invalid syntax
@@ -9141,7 +9210,7 @@ multi-line strings (but not C++, for example)."
(if (looking-at c-identifier-start)
(save-excursion
(setq id-start (point)
- name-res (c-forward-name))
+ name-res (c-forward-name t))
(when name-res
(setq id-end (point)
id-range c-last-identifier-range))))
@@ -9154,8 +9223,9 @@ multi-line strings (but not C++, for example)."
(>= (save-excursion
(save-match-data
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
- (setq pos (point))))
+ pos))
id-end)
(setq res nil)))))
;; Looking at a primitive or known type identifier. We've
@@ -9173,57 +9243,67 @@ multi-line strings (but not C++, for example)."
(looking-at c-opt-type-component-key)))
;; There might be more keywords for the type.
(let (safe-pos)
- (c-forward-keyword-clause 1)
+ (c-forward-keyword-clause 1 t)
(while (progn
(setq safe-pos (point))
+ (c-forward-syntactic-ws)
(looking-at c-opt-type-component-key))
(when (and c-record-type-identifiers
(looking-at c-primitive-type-key))
(c-record-type-id (cons (match-beginning 1)
(match-end 1))))
- (c-forward-keyword-clause 1))
+ (c-forward-keyword-clause 1 t))
(if (looking-at c-primitive-type-key)
(progn
(when c-record-type-identifiers
(c-record-type-id (cons (match-beginning 1)
(match-end 1))))
- (c-forward-keyword-clause 1)
+ (c-forward-keyword-clause 1 t)
(setq res t))
(goto-char safe-pos)
- (setq res 'prefix)))
- (unless (save-match-data (c-forward-keyword-clause 1))
+ (setq res 'prefix))
+ (setq pos (point)))
+ (if (save-match-data (c-forward-keyword-clause 1 t))
+ (setq pos (point))
(if pos
(goto-char pos)
(goto-char (match-end 1))
- (c-forward-syntactic-ws)))))
+ (setq pos (point)))))
+ (c-forward-syntactic-ws))
((and (eq name-res t)
(eq res 'prefix)
(c-major-mode-is 'c-mode)
(save-excursion
(goto-char id-end)
+ (setq pos (point))
+ (c-forward-syntactic-ws)
(and (not (looking-at c-symbol-start))
(not (looking-at c-type-decl-prefix-key)))))
;; A C specifier followed by an implicit int, e.g.
;; "register count;"
- (goto-char id-start)
+ (goto-char prefix-end-pos)
+ (setq pos (point))
+ (unless stop-at-end
+ (c-forward-syntactic-ws))
(setq res 'no-id))
(name-res
(cond ((eq name-res t)
;; A normal identifier.
(goto-char id-end)
+ (setq pos (point))
+ (c-forward-syntactic-ws)
(if (or res c-promote-possible-types)
(progn
(when (not (eq c-promote-possible-types 'just-one))
- (c-add-type id-start (save-excursion
- (goto-char id-end)
- (c-backward-syntactic-ws)
- (point))))
+ (c-add-type id-start id-end))
(when (and c-record-type-identifiers id-range)
(c-record-type-id id-range))
(unless res
- (setq res 'found)))
+ (setq res 'found))
+ (when (eq res 'prefix)
+ (setq res t)))
(setq res (if (c-check-qualified-type id-start)
;; It's an identifier that has been used as
;; a type somewhere else.
@@ -9233,6 +9313,7 @@ multi-line strings (but not C++, for example)."
((eq name-res 'template)
;; A template is sometimes a type.
(goto-char id-end)
+ (setq pos (point))
(c-forward-syntactic-ws)
(setq res
(if (eq (char-after) ?\()
@@ -9258,6 +9339,7 @@ multi-line strings (but not C++, for example)."
(when c-opt-type-modifier-key
(while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
(setq res t)))
@@ -9268,11 +9350,13 @@ multi-line strings (but not C++, for example)."
(when c-opt-type-suffix-key ; e.g. "..."
(while (looking-at c-opt-type-suffix-key)
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)))
;; Skip any "WS" identifiers (e.g. "final" or "override" in C++)
(while (looking-at c-type-decl-suffix-ws-ids-key)
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
(setq res t))
@@ -9296,7 +9380,8 @@ multi-line strings (but not C++, for example)."
(progn
(goto-char (match-end 1))
(c-forward-syntactic-ws)
- (setq subres (c-forward-type))))
+ (setq subres (c-forward-type nil t))
+ (setq pos (point))))
(progn
;; If either operand certainly is a type then both are, but we
@@ -9332,9 +9417,11 @@ multi-line strings (but not C++, for example)."
;; `nconc' doesn't mind that the tail of
;; `c-record-found-types' is t.
(nconc c-record-found-types
- c-record-type-identifiers))))
+ c-record-type-identifiers)))))))
- (goto-char pos))))
+ (goto-char pos)
+ (unless stop-at-end
+ (c-forward-syntactic-ws))
(when (and c-record-found-types (memq res '(known found)) id-range)
(setq c-record-found-types
@@ -9373,19 +9460,24 @@ multi-line strings (but not C++, for example)."
(setq ,ps (cdr ,ps)))))
(defun c-forward-over-compound-identifier ()
- ;; Go over a possibly compound identifier, such as C++'s Foo::Bar::Baz,
- ;; returning that identifier (with any syntactic WS removed). Return nil if
- ;; we're not at an identifier.
- (when (c-on-identifier)
+ ;; Go over a possibly compound identifier (but not any following
+ ;; whitespace), such as C++'s Foo::Bar::Baz, returning that identifier (with
+ ;; any syntactic WS removed). Return nil if we're not at an identifier, in
+ ;; which case point is not moved.
+ (when
+ (eq (c-on-identifier)
+ (point))
(let ((consolidated "") (consolidated-:: "")
- start end)
+ (here (point))
+ start end end-token)
(while
(progn
(setq start (point))
(c-forward-over-token)
(setq consolidated
(concat consolidated-::
- (buffer-substring-no-properties start (point))))
+ (buffer-substring-no-properties start (point)))
+ end-token (point))
(c-forward-syntactic-ws)
(and c-opt-identifier-concat-key
(looking-at c-opt-identifier-concat-key)
@@ -9400,7 +9492,9 @@ multi-line strings (but not C++, for example)."
(concat consolidated
(buffer-substring-no-properties start end))))))))
(if (equal consolidated "")
- nil
+ (progn (goto-char here)
+ nil)
+ (goto-char end-token)
consolidated))))
(defun c-back-over-compound-identifier ()
@@ -9573,13 +9667,16 @@ point unchanged and return nil."
;; Handling of large scale constructs like statements and declarations.
-(defun c-forward-primary-expression (&optional limit)
- ;; Go over the primary expression (if any) at point, moving to the next
- ;; token and return non-nil. If we're not at a primary expression leave
- ;; point unchanged and return nil.
+(defun c-forward-primary-expression (&optional limit stop-at-end)
+ ;; Go over the primary expression (if any) at point, and unless STOP-AT-END
+ ;; is non-nil, move to the next token then return non-nil. If we're not at
+ ;; a primary expression leave point unchanged and return nil.
;;
;; Note that this function is incomplete, handling only those cases expected
;; to be common in a C++20 requires clause.
+ ;;
+ ;; Note also that (...) is not recognised as a primary expression if the
+ ;; next token is an open brace.
(let ((here (point))
(c-restricted-<>-arglists t)
(c-parse-and-markup-<>-arglists nil)
@@ -9587,28 +9684,38 @@ point unchanged and return nil."
(if (cond
((looking-at c-constant-key)
(goto-char (match-end 1))
- (c-forward-syntactic-ws limit)
+ (unless stop-at-end (c-forward-syntactic-ws limit))
t)
((eq (char-after) ?\()
(and (c-go-list-forward (point) limit)
(eq (char-before) ?\))
- (progn (c-forward-syntactic-ws limit)
- t)))
+ (let ((after-paren (point)))
+ (c-forward-syntactic-ws limit)
+ (prog1
+ (not (eq (char-after) ?{))
+ (when stop-at-end
+ (goto-char after-paren))))))
((c-forward-over-compound-identifier)
- (c-forward-syntactic-ws limit)
- (while (cond
- ((looking-at "<")
- (prog1
- (c-forward-<>-arglist nil)
- (c-forward-syntactic-ws limit)))
- ((looking-at c-opt-identifier-concat-key)
- (and
- (zerop (c-forward-token-2 1 nil limit))
- (prog1
- (c-forward-over-compound-identifier)
- (c-forward-syntactic-ws limit))))))
- t)
- ((looking-at c-fun-name-substitute-key) ; "requires"
+ (let ((after-id (point)))
+ (c-forward-syntactic-ws limit)
+ (while (cond
+ ((and
+ (looking-at "<")
+ (prog1
+ (and
+ (c-forward-<>-arglist nil)
+ (setq after-id (point)))))
+ (c-forward-syntactic-ws limit))
+ ((looking-at c-opt-identifier-concat-key)
+ (and
+ (zerop (c-forward-token-2 1 nil limit))
+ (prog1
+ (c-forward-over-compound-identifier)
+ (c-forward-syntactic-ws limit))))))
+ (goto-char after-id)))
+ ((and
+ (looking-at c-fun-name-substitute-key) ; "requires"
+ (not (eq (char-after (match-end 0)) ?_)))
(goto-char (match-end 1))
(c-forward-syntactic-ws limit)
(and
@@ -9621,36 +9728,47 @@ point unchanged and return nil."
(and (c-go-list-forward (point) limit)
(eq (char-before) ?}))
(progn
- (c-forward-syntactic-ws limit)
+ (unless stop-at-end (c-forward-syntactic-ws limit))
t))))
t
(goto-char here)
nil)))
-(defun c-forward-c++-requires-clause (&optional limit)
- ;; Point is at the keyword "requires". Move forward over the requires
- ;; clause to the next token after it and return non-nil. If there is no
- ;; valid requires clause at point, leave point unmoved and return nil.
+(defun c-forward-constraint-clause (&optional limit stop-at-end)
+ ;; Point is at the putative start of a constraint clause. Move to its end
+ ;; (when STOP-AT-END is non-zero) or the token after that (otherwise) and
+ ;; return non-nil. Return nil without moving if we fail to find a
+ ;; constraint.
(let ((here (point))
final-point)
(or limit (setq limit (point-max)))
- (if (and
- (zerop (c-forward-token-2 1 nil limit)) ; over "requires".
- (prog1
- (c-forward-primary-expression limit)
- (setq final-point (point))
- (while
- (and (looking-at "\\(?:&&\\|||\\)")
- (progn (goto-char (match-end 0))
- (c-forward-syntactic-ws limit)
- (and (< (point) limit)
- (c-forward-primary-expression limit))))
- (setq final-point (point)))))
- (progn (goto-char final-point)
- t)
+ (if (c-forward-primary-expression limit t)
+ (progn
+ (setq final-point (point))
+ (c-forward-syntactic-ws limit)
+ (while
+ (and (looking-at "\\(?:&&\\|||\\)")
+ (<= (match-end 0) limit)
+ (progn (goto-char (match-end 0))
+ (c-forward-syntactic-ws limit)
+ (and (<= (point) limit)))
+ (c-forward-primary-expression limit t)
+ (setq final-point (point))))
+ (goto-char final-point)
+ (or stop-at-end (c-forward-syntactic-ws limit))
+ t)
(goto-char here)
nil)))
+(defun c-forward-c++-requires-clause (&optional limit stop-at-end)
+ ;; Point is at the keyword "requires". Move forward over the requires
+ ;; clause to its end (if STOP-AT-END is non-nil) or the next token after it
+ ;; (otherwise) and return non-nil. If there is no valid requires clause at
+ ;; point, leave point unmoved and return nil.
+ (or limit (setq limit (point-max)))
+ (and (zerop (c-forward-token-2)) ; over "requires".
+ (c-forward-constraint-clause limit stop-at-end)))
+
(defun c-forward-decl-arglist (not-top id-in-parens &optional limit)
;; Point is at an open parenthesis, assumed to be the arglist of a function
;; declaration. Move over this arglist and following syntactic whitespace,
@@ -9737,7 +9855,7 @@ point unchanged and return nil."
;; (e.g. "," or ";" or "}").
(let ((here (point))
id-start id-end brackets-after-id paren-depth decorated
- got-init arglist double-double-quote)
+ got-init arglist double-double-quote pos)
(or limit (setq limit (point-max)))
(if (and
(< (point) limit)
@@ -9771,6 +9889,7 @@ point unchanged and return nil."
(eq (char-after (1+ (point))) ?\"))
(setq double-double-quote t))
(goto-char (match-end 0))
+ (setq pos (point))
(c-forward-syntactic-ws limit)
(setq got-identifier t)
nil)
@@ -9783,7 +9902,10 @@ point unchanged and return nil."
;; prefix only if it specifies a member pointer.
(progn
(setq id-start (point))
- (when (c-forward-name)
+ (when (c-forward-name t)
+ (setq pos (point))
+ (c-forward-syntactic-ws limit)
+
(if (save-match-data
(looking-at "\\(::\\)"))
;; We only check for a trailing "::" and
@@ -9812,10 +9934,12 @@ point unchanged and return nil."
(setq id-start (point)))
(cond
((or got-identifier
- (c-forward-name))
- (save-excursion
- (c-backward-syntactic-ws)
- (setq id-end (point))))
+ (c-forward-name t))
+ (setq id-end
+ (or pos
+ (point)))
+ (c-forward-syntactic-ws limit)
+ t)
(accept-anon
(setq id-start nil id-end nil)
t)
@@ -9846,7 +9970,9 @@ point unchanged and return nil."
((looking-at c-type-decl-suffix-key)
(cond
((save-match-data
- (looking-at c-fun-name-substitute-key))
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
(c-forward-c++-requires-clause))
((eq (char-after) ?\()
(if (c-forward-decl-arglist not-top decorated limit)
@@ -10060,6 +10186,24 @@ This function might do hidden buffer changes."
;; This identifier is bound only in the inner let.
'(setq start id-start))))
+(defmacro c-fdoc-assymetric-space-about-asterisk ()
+ ;; We've got a "*" at `id-start' between two identifiers, the first at
+ ;; `type-start'. Return non-nil when there is either whitespace between the
+ ;; first id and the "*" or between the "*" and the second id, but not both.
+ `(let ((space-before-id
+ (save-excursion
+ (goto-char id-start) ; Position of "*".
+ (and (> (skip-chars-forward "* \t\n\r") 0)
+ (memq (char-before) '(?\ ?\t ?\n ?\r)))))
+ (space-after-type
+ (save-excursion
+ (goto-char type-start)
+ (and (c-forward-type nil t)
+ (or (eolp)
+ (memq (char-after) '(?\ ?\t)))))))
+ (not (eq (not space-before-id)
+ (not space-after-type)))))
+
(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end
&optional inside-macro)
;; Move forward over a declaration or a cast if at the start of one.
@@ -10282,7 +10426,9 @@ This function might do hidden buffer changes."
(when (and (c-major-mode-is 'c++-mode)
(c-keyword-member kwd-sym 'c-<>-sexp-kwds)
(save-match-data
- (looking-at c-fun-name-substitute-key)))
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))))
(c-forward-c++-requires-clause))
(setq kwd-clause-end (point))))
((and c-opt-cpp-prefix
@@ -10569,11 +10715,11 @@ This function might do hidden buffer changes."
(or got-identifier
(and (looking-at c-identifier-start)
(setq pos (point))
- (setq got-identifier (c-forward-name))
+ (setq got-identifier (c-forward-name t))
(save-excursion
- (c-backward-syntactic-ws)
(c-simple-skip-symbol-backward)
(setq identifier-start (point)))
+ (progn (c-forward-syntactic-ws) t)
(setq name-start pos))
(when (looking-at "[0-9]")
(setq got-number t)) ; We probably have an arithmetic expression.
@@ -10632,7 +10778,9 @@ This function might do hidden buffer changes."
((save-match-data (looking-at "\\s("))
(c-safe (c-forward-sexp 1) t))
((save-match-data
- (looking-at c-fun-name-substitute-key)) ; C++ requires
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))) ; C++ requires
(c-forward-c++-requires-clause))
(t (goto-char (match-end 1))
t))
@@ -10796,8 +10944,7 @@ This function might do hidden buffer changes."
type-start
(progn
(goto-char type-start)
- (c-forward-type)
- (c-backward-syntactic-ws)
+ (c-forward-type nil t)
(point)))))))))
;; Got a declaration of the form "foo bar (gnu);" or "bar
;; (gnu);" where we've recognized "bar" as the type and "gnu"
@@ -11081,19 +11228,25 @@ This function might do hidden buffer changes."
;; CASE 16
(when (and got-prefix-before-parens
at-type
- (or at-decl-end (looking-at "=[^=]"))
(memq context '(nil top))
(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.
+ ;; it as a declaration when there's "symmetrical WS" around
+ ;; the "*" or the flag `c-assymetry-fontification-flag' is
+ ;; not set. 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))
+ (when (or (not c-asymmetry-fontification-flag)
+ (looking-at "=\\([^=]\\|$\\)\\|;")
+ (c-fdoc-assymetric-space-about-asterisk))
+ (when (eq at-type 'maybe)
+ (setq unsafe-maybe t))
+ (throw 'at-decl-or-cast t)))
;; CASE 17
(when (and (or got-suffix-after-parens
@@ -11112,25 +11265,12 @@ This function might do hidden buffer changes."
got-prefix-before-parens
at-type
(or (not got-suffix)
- at-decl-start))
- (let ((space-before-id
- (save-excursion
- (goto-char id-start) ; Position of "*".
- (and (> (skip-chars-forward "* \t\n\r") 0)
- (memq (char-before) '(?\ ?\t ?\n ?\r)))))
- (space-after-type
- (save-excursion
- (goto-char type-start)
- (and (c-forward-type)
- (progn (c-backward-syntactic-ws) t)
- (or (eolp)
- (memq (char-after) '(?\ ?\t)))))))
- (when (not (eq (not space-before-id)
- (not space-after-type)))
- (when (eq at-type 'maybe)
- (setq unsafe-maybe t))
- (setq maybe-expression t)
- (throw 'at-decl-or-cast t)))))
+ at-decl-start)
+ (c-fdoc-assymetric-space-about-asterisk))
+ (when (eq at-type 'maybe)
+ (setq unsafe-maybe t))
+ (setq maybe-expression t)
+ (throw 'at-decl-or-cast t)))
;; CASE 18
(when (and at-decl-end
@@ -12763,7 +12903,9 @@ comment at the start of cc-engine.el for more info."
in-paren 'in-paren))
((looking-at c-pre-brace-non-bracelist-key)
(setq braceassignp nil))
- ((looking-at c-fun-name-substitute-key)
+ ((and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))
(setq braceassignp nil))
((looking-at c-return-key))
((and (looking-at c-symbol-start)
@@ -12778,7 +12920,8 @@ comment at the start of cc-engine.el for more info."
;; Have we a requires with a parenthesis list?
(when (save-excursion
(and (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-fun-name-substitute-key)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
(setq braceassignp nil))
nil)
(t nil))
@@ -13109,6 +13252,120 @@ comment at the start of cc-engine.el for more info."
(t nil)))
(goto-char here))))
+(defun c-forward-concept-fragment (&optional limit stop-at-end)
+ ;; Are we currently at the "concept" keyword in a concept construct? If so
+ ;; we return the position of the first constraint expression following the
+ ;; "=" sign and move forward over the constraint. Otherwise we return nil.
+ ;; LIMIT is a forward search limit.
+ (let ((here (point)))
+ (if
+ (and
+ (looking-at c-equals-nontype-decl-key) ; "concept"
+ (goto-char (match-end 0))
+ (progn (c-forward-syntactic-ws limit)
+ (not (looking-at c-keywords-regexp)))
+ (looking-at c-identifier-key)
+ (goto-char (match-end 0))
+ (progn (c-forward-syntactic-ws limit)
+ (looking-at c-operator-re))
+ (equal (match-string 0) "=")
+ (goto-char (match-end 0)))
+ (prog1
+ (progn (c-forward-syntactic-ws limit)
+ (point))
+ (c-forward-constraint-clause limit stop-at-end))
+ (goto-char here)
+ nil)))
+
+(defun c-looking-at-concept (&optional limit)
+ ;; Are we currently at the start of a concept construct? I.e. at the
+ ;; "template" keyword followed by the construct? If so, we return a cons of
+ ;; the position of "concept" and the position of the first constraint
+ ;; expression following the "=" sign, otherwise we return nil. LIMIT is a
+ ;; forward search limit.
+ (save-excursion
+ (let (conpos)
+ (and (looking-at c-pre-concept-<>-key)
+ (goto-char (match-end 1))
+ (< (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (eq (char-after) ?<))
+ (let ((c-parse-and-markup-<>-arglists t)
+ c-restricted-<>-arglists)
+ (c-forward-<>-arglist nil))
+ (< (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (looking-at c-equals-nontype-decl-key)) ; "concept"
+ (setq conpos (match-beginning 0))
+ (goto-char (match-end 0))
+ (< (point) limit)
+ (c-syntactic-re-search-forward
+ "=" limit t t)
+ (goto-char (match-end 0))
+ (<= (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (cons conpos (point)))))))
+
+(defun c-in-requires-or-at-end-of-clause (&optional pos)
+ ;; Is POS (default POINT) in a C++ "requires" expression or "requires"
+ ;; clause or at the end of a "requires" clause? If so return a cons
+ ;; (POSITION . END) where POSITION is that of the "requires" keyword, and
+ ;; END is `expression' if POS is in an expression, nil if it's in a clause
+ ;; or t if it's at the end of a clause. "End of a clause" means just after
+ ;; the non syntactic WS on the line where the clause ends.
+ ;;
+ ;; Note we can't use `c-beginning-of-statement-1' in this function because
+ ;; of this function's use in `c-at-vsemi-p' for C++ Mode.
+ (save-excursion
+ (if pos (goto-char pos) (setq pos (point)))
+ (let ((limit (max (- (point) 2000) (point-min)))
+ found-req req-pos found-clause res pe-start pe-end
+ )
+ (while ; Loop around syntactically significant "requires" keywords.
+ (progn
+ (while
+ (and
+ (setq found-req (re-search-backward
+ c-fun-name-substitute-key
+ limit t)) ; Fast!
+ (or (not (setq found-req
+ (not (eq (char-after (match-end 0)) ?_))))
+ (not (setq found-req (not (c-in-literal))))))) ; Slow!
+ (setq req-pos (point))
+ (cond
+ ((not found-req) ; No "requires" found
+ nil)
+ ((save-excursion ; A primary expression `pos' is in
+ (setq pe-end nil)
+ (while (and (setq pe-start (point))
+ (< (point) pos)
+ (c-forward-primary-expression nil t)
+ (setq pe-end (point))
+ (progn (c-forward-syntactic-ws)
+ (looking-at "&&\\|||"))
+ (c-forward-over-token-and-ws)))
+ pe-end)
+ (if (<= pe-end pos)
+ t ; POS is not in a primary expression.
+ (setq res (cons pe-start 'expression))
+ nil))
+ ((progn
+ (goto-char req-pos)
+ (if (looking-at c-fun-name-substitute-key)
+ (setq found-clause (c-forward-c++-requires-clause nil t))
+ (and (c-forward-concept-fragment)
+ (setq found-clause (point))))
+ nil))
+ ((and found-clause (>= (point) pos))
+ (setq res (cons req-pos (eq (point) pos)))
+ nil)
+ (found-clause ; We found a constraint clause, but it did not
+ ; extend far enough forward to reach POS.
+ (c-go-up-list-backward req-pos limit))
+ (t (goto-char req-pos)
+ t))))
+ res)))
+
(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
;; Return non-nil if we're looking at the beginning of a block
;; inside an expression. The value returned is actually a cons of
@@ -13305,6 +13562,19 @@ comment at the start of cc-engine.el for more info."
(looking-at c-pre-lambda-tokens-re)))
(not (c-in-literal))))
+(defun c-c++-vsemi-p (&optional pos)
+ ;; C++ Only - Is there a "virtual semicolon" at POS or point?
+ ;; (See cc-defs.el for full details of "virtual semicolons".)
+ ;;
+ ;; This is true when point is at the last non syntactic WS position on the
+ ;; line, and either there is a "macro with semicolon" just before it (see
+ ;; `c-at-macro-vsemi-p') or there is a "requires" clause which ends there.
+ (let (res)
+ (cond
+ ((setq res (c-in-requires-or-at-end-of-clause pos))
+ (and res (eq (cdr res) t)))
+ ((c-at-macro-vsemi-p)))))
+
(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".)
@@ -13856,7 +14126,7 @@ comment at the start of cc-engine.el for more info."
literal char-before-ip before-ws-ip char-after-ip macro-start
in-macro-expr c-syntactic-context placeholder
step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos
- tmp-pos2 containing-<
+ tmp-pos2 containing-< tmp constraint-detail
;; The following record some positions for the containing
;; declaration block if we're directly within one:
;; `containing-decl-open' is the position of the open
@@ -14271,6 +14541,33 @@ comment at the start of cc-engine.el for more info."
containing-decl-start
containing-decl-kwd))
+ ;; CASE 5A.7: "defun" open in a requires expression.
+ ((save-excursion
+ (goto-char indent-point)
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))
+ (setq placeholder (point))))
+ (goto-char placeholder)
+ (back-to-indentation)
+ (c-add-syntax 'defun-open (point)))
+
+ ;; CASE 5A.6: "defun" open in concept.
+ ;; ((save-excursion
+ ;; (goto-char indent-point)
+ ;; (skip-chars-forward " \t")
+ ;; (and (eq (char-after) ?{)
+ ;; (eq (c-beginning-of-statement-1 lim) 'same)
+ ;; (setq placeholder
+ ;; (cdr (c-looking-at-concept indent-point)))))
+ ;; (goto-char placeholder)
+ ;; (back-to-indentation)
+ ;; (c-add-syntax 'defun-open (point)))
+
;; CASE 5A.5: ordinary defun open
(t
(save-excursion
@@ -14441,10 +14738,35 @@ comment at the start of cc-engine.el for more info."
nil nil
containing-sexp paren-state))
+ ;; CASE 5F: Close of a non-class declaration level block.
+ ((and (eq char-after-ip ?})
+ (c-keyword-member containing-decl-kwd
+ 'c-other-block-decl-kwds))
+ ;; This is inconsistent: Should use `containing-decl-open'
+ ;; here if it's at boi, like in case 5J.
+ (goto-char containing-decl-start)
+ (c-add-stmt-syntax
+ (if (string-equal (symbol-name containing-decl-kwd) "extern")
+ ;; Special case for compatibility with the
+ ;; extern-lang syntactic symbols.
+ 'extern-lang-close
+ (intern (concat (symbol-name containing-decl-kwd)
+ "-close")))
+ nil t
+ (c-most-enclosing-brace paren-state (point))
+ paren-state))
+
+ ;; CASE 5T: Continuation of a concept clause.
+ ((save-excursion
+ (and (eq (c-beginning-of-statement-1 nil t) 'same)
+ (setq tmp (c-looking-at-concept indent-point))))
+ (c-add-syntax 'constraint-cont (car tmp)))
+
;; CASE 5D: this could be a top-level initialization, a
;; member init list continuation, or a template argument
;; list continuation.
((save-excursion
+ (setq constraint-detail (c-in-requires-or-at-end-of-clause))
;; Note: We use the fact that lim is always after any
;; preceding brace sexp.
(if c-recognize-<>-arglists
@@ -14474,8 +14796,9 @@ comment at the start of cc-engine.el for more info."
;; clause - we assume only C++ needs it.
(c-syntactic-skip-backward "^;,=" lim t))
(setq placeholder (point))
- (and (memq (char-before) '(?, ?= ?<))
- (not (c-crosses-statement-barrier-p (point) indent-point))))
+ (or constraint-detail
+ (and (memq (char-before) '(?, ?= ?<))
+ (not (c-crosses-statement-barrier-p (point) indent-point)))))
(cond
;; CASE 5D.6: Something like C++11's "using foo = <type-exp>"
@@ -14493,8 +14816,7 @@ comment at the start of cc-engine.el for more info."
(c-on-identifier))
(setq placeholder preserve-point)))))
(c-add-syntax
- 'statement-cont placeholder)
- )
+ 'statement-cont placeholder))
;; CASE 5D.3: perhaps a template list continuation?
((and (c-major-mode-is 'c++-mode)
@@ -14544,21 +14866,10 @@ comment at the start of cc-engine.el for more info."
;; CASE 5D.7: Continuation of a "concept foo =" line in C++20 (or
;; similar).
- ((and c-equals-nontype-decl-key
- (save-excursion
- (prog1
- (and (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-operator-re)
- (equal (match-string 0) "=")
- (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-symbol-start)
- (not (looking-at c-keywords-regexp))
- (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-equals-nontype-decl-key)
- (eq (c-beginning-of-statement-1 lim) 'same))
- (setq placeholder (point)))))
- (goto-char placeholder)
- (c-add-stmt-syntax 'topmost-intro-cont nil nil containing-sexp
+ ((and constraint-detail
+ (not (eq (cdr constraint-detail) 'expression)))
+ (goto-char (car constraint-detail))
+ (c-add-stmt-syntax 'constraint-cont nil nil containing-sexp
paren-state))
;; CASE 5D.5: Continuation of the "expression part" of a
@@ -14583,24 +14894,6 @@ comment at the start of cc-engine.el for more info."
nil nil containing-sexp paren-state))
))
- ;; CASE 5F: Close of a non-class declaration level block.
- ((and (eq char-after-ip ?})
- (c-keyword-member containing-decl-kwd
- 'c-other-block-decl-kwds))
- ;; This is inconsistent: Should use `containing-decl-open'
- ;; here if it's at boi, like in case 5J.
- (goto-char containing-decl-start)
- (c-add-stmt-syntax
- (if (string-equal (symbol-name containing-decl-kwd) "extern")
- ;; Special case for compatibility with the
- ;; extern-lang syntactic symbols.
- 'extern-lang-close
- (intern (concat (symbol-name containing-decl-kwd)
- "-close")))
- nil t
- (c-most-enclosing-brace paren-state (point))
- paren-state))
-
;; CASE 5G: we are looking at the brace which closes the
;; enclosing nested class decl
((and containing-sexp
@@ -14813,7 +15106,59 @@ comment at the start of cc-engine.el for more info."
(c-add-syntax 'topmost-intro-cont (c-point 'boi)))
))
- ;; (CASE 6 has been removed.)
+ ;; CASE 20: A C++ requires sub-clause.
+ ((and (setq tmp (c-in-requires-or-at-end-of-clause indent-point))
+ (not (eq (cdr tmp) 'expression))
+ (setq placeholder (car tmp)))
+ (c-add-syntax
+ (if (eq char-after-ip ?{)
+ 'substatement-open
+ 'substatement)
+ (c-point 'boi placeholder)))
+
+ ;; ((Old) CASE 6 has been removed.)
+ ;; CASE 6: line is within a C11 _Generic expression.
+ ((and c-generic-key
+ (eq (char-after containing-sexp) ?\()
+ (progn (setq tmp-pos (c-safe-scan-lists
+ containing-sexp 1 0
+ (min (+ (point) 2000) (point-max))))
+ t)
+ (save-excursion
+ (and
+ (progn (goto-char containing-sexp)
+ (zerop (c-backward-token-2)))
+ (looking-at c-generic-key)
+ (progn (goto-char (1+ containing-sexp))
+ (c-syntactic-re-search-forward
+ "," indent-point 'bound t t))
+ (setq placeholder (point)))))
+ (let ((res (c-syntactic-re-search-forward
+ "[,:)]"
+ (or tmp-pos (min (+ (point) 2000) (point-max)))
+ 'bound t t)))
+ (cond
+ ((and res
+ (eq (char-before) ?\))
+ (save-excursion
+ (backward-char)
+ (c-backward-syntactic-ws indent-point)
+ (eq (point) indent-point)))
+ (c-add-stmt-syntax
+ 'arglist-close (list containing-sexp) t
+ (c-most-enclosing-brace paren-state indent-point) paren-state))
+ ((or (not res)
+ (eq (char-before) ?\)))
+ (backward-char)
+ (c-syntactic-skip-backward "^,:" containing-sexp t)
+ (c-add-syntax (if (eq (char-before) ?:)
+ 'statement-case-intro
+ 'case-label)
+ (1+ containing-sexp)))
+ (t (c-add-syntax (if (eq (char-before) ?:)
+ 'case-label
+ 'statement-case-intro)
+ (1+ containing-sexp))))))
;; CASE 7: line is an expression, not a statement. Most
;; likely we are either in a function prototype or a function
@@ -15154,6 +15499,20 @@ comment at the start of cc-engine.el for more info."
(c-add-syntax 'defun-close (point))
(c-add-syntax 'inline-close (point))))
+ ;; CASE 16G: Do we have the closing brace of a "requires" clause
+ ;; of a C++20 "concept"?
+ ((save-excursion
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
+ (goto-char containing-sexp)
+ (back-to-indentation)
+ (c-add-stmt-syntax 'defun-close nil t lim paren-state))
+
;; CASE 16F: Can be a defun-close of a function declared
;; in a statement block, e.g. in Pike or when using gcc
;; extensions, but watch out for macros followed by
@@ -15304,6 +15663,21 @@ comment at the start of cc-engine.el for more info."
(if (eq char-after-ip ?{)
(c-add-syntax 'block-open)))
+ ;; CASE 17J: first "statement" inside a C++20 requires
+ ;; "function".
+ ((save-excursion
+ (goto-char containing-sexp)
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
+ (goto-char containing-sexp)
+ (back-to-indentation)
+ (c-add-syntax 'defun-block-intro (point)))
+
;; CASE 17F: first statement in an inline, or first
;; statement in a top-level defun. we can tell this is it
;; if there are no enclosing braces that haven't been