Add handling of the C11 _Generic construct to C Mode
This fixes bug #61481. * lisp/progmodes/cc-engine.el (c-guess-basic-syntax): Add a new CASE 6 for _Generic. * lisp/progmodes/cc-fonts.el (c-fontify-types-and-refs): Use `let*' rather than `let'. (c-get-fontification-context): Add the new result `generic', and add handling to determine it. (c-font-lock-declarations): Call c-font-lock-c11-generic-clause when needed. (c-font-lock-c11-generic-clause): New function. * lisp/progmodes/cc-langs.el (c-generic-kwds, c-generic-key): New lang constants/variable.
This commit is contained in:
parent
23089f1cf2
commit
d4346a7cc7
3 changed files with 101 additions and 13 deletions
|
@ -14911,7 +14911,49 @@ 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.)
|
||||
;; ((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
|
||||
|
|
|
@ -259,14 +259,14 @@
|
|||
|
||||
(defmacro c-fontify-types-and-refs (varlist &rest body)
|
||||
(declare (indent 1) (debug let*))
|
||||
;; Like `let', but additionally activates `c-record-type-identifiers'
|
||||
;; Like `let*', but additionally activates `c-record-type-identifiers'
|
||||
;; and `c-record-ref-identifiers', and fontifies the recorded ranges
|
||||
;; accordingly on exit.
|
||||
;;
|
||||
;; This function does hidden buffer changes.
|
||||
`(let ((c-record-type-identifiers t)
|
||||
c-record-ref-identifiers
|
||||
,@varlist)
|
||||
`(let* ((c-record-type-identifiers t)
|
||||
c-record-ref-identifiers
|
||||
,@varlist)
|
||||
(prog1 (progn ,@body)
|
||||
(c-fontify-recorded-types-and-refs))))
|
||||
|
||||
|
@ -1219,6 +1219,7 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
;; inside a function declaration arglist).
|
||||
;; '<> In an angle bracket arglist.
|
||||
;; 'arglist Some other type of arglist.
|
||||
;; 'generic In a C11 _Generic construct.
|
||||
;; 'top Some other context and point is at the top-level (either
|
||||
;; outside any braces or directly inside a class or namespace,
|
||||
;; etc.)
|
||||
|
@ -1345,6 +1346,15 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(c-back-over-member-initializers)))
|
||||
(c-put-char-property (1- match-pos) 'c-type 'c-not-decl)
|
||||
(cons 'not-decl nil))
|
||||
;; In a C11 _Generic construct.
|
||||
((and c-generic-key
|
||||
(eq (char-before match-pos) ?,)
|
||||
(save-excursion
|
||||
(and (c-go-up-list-backward match-pos
|
||||
(max (- (point) 2000) (point-min)))
|
||||
(zerop (c-backward-token-2))
|
||||
(looking-at c-generic-key))))
|
||||
(cons 'generic nil))
|
||||
;; At start of a declaration inside a declaration paren.
|
||||
((save-excursion
|
||||
(goto-char match-pos)
|
||||
|
@ -1616,13 +1626,16 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(c-forward-syntactic-ws))
|
||||
|
||||
;; Now analyze the construct.
|
||||
(if (eq context 'not-decl)
|
||||
(progn
|
||||
(setq decl-or-cast nil)
|
||||
(if (c-syntactic-re-search-forward
|
||||
"," (min limit (point-max)) 'at-limit t)
|
||||
(c-put-char-property (1- (point)) 'c-type 'c-not-decl))
|
||||
nil)
|
||||
(cond
|
||||
((eq context 'not-decl)
|
||||
(setq decl-or-cast nil)
|
||||
(if (c-syntactic-re-search-forward
|
||||
"," (min limit (point-max)) 'at-limit t)
|
||||
(c-put-char-property (1- (point)) 'c-type 'c-not-decl))
|
||||
nil)
|
||||
((eq context 'generic)
|
||||
(c-font-lock-c11-generic-clause))
|
||||
(t
|
||||
(setq decl-or-cast
|
||||
(c-forward-decl-or-cast-1
|
||||
match-pos context last-cast-end inside-macro))
|
||||
|
@ -1683,7 +1696,7 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
context
|
||||
(or toplev (nth 4 decl-or-cast))))
|
||||
|
||||
(t t))))
|
||||
(t t)))))
|
||||
|
||||
;; It was a false alarm. Check if we're in a label (or other
|
||||
;; construct with `:' except bitfield) instead.
|
||||
|
@ -1713,6 +1726,28 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
|
||||
nil))))
|
||||
|
||||
(defun c-font-lock-c11-generic-clause ()
|
||||
;; Fontify a type inside the C11 _Generic clause. Point will be at the
|
||||
;; type and will be left at the next comma of the clause (if any) or the
|
||||
;; closing parenthesis, if any, or at the end of the type, otherwise.
|
||||
;; The return value is always nil.
|
||||
(c-fontify-types-and-refs
|
||||
((here (point))
|
||||
(type-type (c-forward-type t))
|
||||
(c-promote-possible-types (if (eq type-type 'maybe) 'just-one t))
|
||||
(pos (point)) pos1)
|
||||
(when (and type-type (eq (char-after) ?:))
|
||||
(goto-char here)
|
||||
(c-forward-type t)) ; Fontify the type.
|
||||
(cond
|
||||
((c-syntactic-re-search-forward "," nil t t t)
|
||||
(backward-char))
|
||||
((and (setq pos1 (c-up-list-forward))
|
||||
(eq (char-before pos1) ?\)))
|
||||
(goto-char (1- pos1)))
|
||||
(t (goto-char pos))))
|
||||
nil)
|
||||
|
||||
(defun c-font-lock-enum-body (limit)
|
||||
;; Fontify the identifiers of each enum we find by searching forward.
|
||||
;;
|
||||
|
|
|
@ -3085,6 +3085,17 @@ Keywords here should also be in `c-block-stmt-1-kwds'."
|
|||
t (c-make-keywords-re t (c-lang-const c-block-stmt-2-kwds)))
|
||||
(c-lang-defvar c-block-stmt-2-key (c-lang-const c-block-stmt-2-key))
|
||||
|
||||
(c-lang-defconst c-generic-kwds
|
||||
"The keyword \"_Generic\" which introduces a C11 generic statement."
|
||||
t nil
|
||||
c '("_Generic"))
|
||||
|
||||
(c-lang-defconst c-generic-key
|
||||
;; Regexp matching the keyword(s) in `c-generic-kwds'.
|
||||
t (if (c-lang-const c-generic-kwds)
|
||||
(c-make-keywords-re t (c-lang-const c-generic-kwds))))
|
||||
(c-lang-defvar c-generic-key (c-lang-const c-generic-key))
|
||||
|
||||
(c-lang-defconst c-block-stmt-kwds
|
||||
;; Union of `c-block-stmt-1-kwds' and `c-block-stmt-2-kwds'.
|
||||
t (c--delete-duplicates (append (c-lang-const c-block-stmt-1-kwds)
|
||||
|
|
Loading…
Add table
Reference in a new issue