emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master d4346a7cc78: Add handling of the C11 _Generic construct to C Mode


From: Alan Mackenzie
Subject: master d4346a7cc78: Add handling of the C11 _Generic construct to C Mode
Date: Fri, 17 Feb 2023 04:17:23 -0500 (EST)

branch: master
commit d4346a7cc784349799552ec31ae66546408ae407
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    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.
---
 lisp/progmodes/cc-engine.el | 44 ++++++++++++++++++++++++++++++++-
 lisp/progmodes/cc-fonts.el  | 59 ++++++++++++++++++++++++++++++++++++---------
 lisp/progmodes/cc-langs.el  | 11 +++++++++
 3 files changed, 101 insertions(+), 13 deletions(-)

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 1899b522ab0..f8ae49c42dd 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -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
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index c220d8d8789..4ec21af1b25 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -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.
   ;;
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index daa23bd14fa..61f81f09b3e 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]