diff options
Diffstat (limited to 'lisp/progmodes/cc-engine.el')
-rw-r--r-- | lisp/progmodes/cc-engine.el | 446 |
1 files changed, 340 insertions, 106 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 81446c3c00b..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. @@ -6172,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. @@ -8630,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) @@ -8731,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. @@ -9122,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. @@ -9132,6 +9130,7 @@ 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) @@ -9283,7 +9282,10 @@ multi-line strings (but not C++, for example)." (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 @@ -9291,6 +9293,7 @@ multi-line strings (but not C++, for example)." ;; 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)) @@ -9298,7 +9301,9 @@ multi-line strings (but not C++, for example)." (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. @@ -9455,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) @@ -9482,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 () @@ -9655,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) @@ -9669,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 @@ -9703,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, @@ -9934,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) @@ -10388,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 @@ -10738,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)) @@ -11200,7 +11242,7 @@ This function might do hidden buffer changes." ;; declaration. (setq maybe-expression t) (when (or (not c-asymmetry-fontification-flag) - (looking-at "=[^=]") + (looking-at "=\\([^=]\\|$\\)\\|;") (c-fdoc-assymetric-space-about-asterisk)) (when (eq at-type 'maybe) (setq unsafe-maybe t)) @@ -12861,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) @@ -12876,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)) @@ -13207,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 @@ -13403,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".) @@ -13954,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 @@ -14369,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 @@ -14539,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 @@ -14572,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>" @@ -14591,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) @@ -14642,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 @@ -14681,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 @@ -14911,6 +15106,16 @@ comment at the start of cc-engine.el for more info." (c-add-syntax 'topmost-intro-cont (c-point 'boi))) )) + ;; 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 @@ -15294,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 @@ -15444,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 |