]> git.eshelyaron.com Git - emacs.git/commitdiff
Implement C23 features:
authorAlan Mackenzie <acm@muc.de>
Thu, 1 May 2025 16:12:18 +0000 (16:12 +0000)
committerEshel Yaron <me@eshelyaron.com>
Sat, 10 May 2025 06:53:55 +0000 (08:53 +0200)
Improve the handling of #error and #warning in C and C++ Modes.

* lisp/progmodes/cc-engine.el (c-looking-at-c++-attribute)
(c-enclosing-c++-attribute, c-forward-sws, c-backward-sws):
Handle attributes in C as they have been handled in C++.
(c-forward-align-clause-throw-if-invalid): New macro.
(c-forward-type): Handle alignas, alignof, and _BitInt, putting
a catch block around most of the function to catch invalid uses
of these new keywords.
(c-in-id-arglist): New function.
(c-forward-decl-or-cast-1): Recognize a "maybe" type identifier
as a type in arglists when there is no parameter identifier
associated with it.

* lisp/progmodes/cc-fonts.el (c-font-lock-cpp-messages): New
function.
(c-cpp-matchers): Move the handling of "invalid" comment
delimiters outside of the block handling CPP directives.
Remove the inline handling of #error and #warning, using the
new function c-font-lock-cpp-messages instead.
(c-get-fontification-context): Handle alignof, alignas,
_BitInt.
(c-font-lock-declarations): Adapt fontification of K&R
parameters to the C23 nameless parameter scheme.

* lisp/progmodes/cc-langs.el (c-has-quoted-numbers)
(c-stmt-boundary-skip-chars)
(c-recognize-post-brace-list-type-p, c-modifier-kwds)
(c-constant-kwds): Handle C the same as the existing C++
handling.
(c-cpp-message-directives-re, noncontinued-line-end)
(c-cpp-messages-re, c-cpp-message-match-no): New
c-lang-consts/vars.
(c-cpp-include-directives): New directive embed.
(c-cpp-expr-directives): New directives elifdef, elifndef.
(c-primitive-type-kwds): New types, _Decimal*, bool, char*_t,
nullptr_t.
(c-typeof-kwds): New keyword typeof_unqual.
(c-type-with-paren-kwds, c-type-with-paren-key): New
c-lang-const/vars.
(c-type-modifier-with-parens-kwds)
(c-type-modifier-with-parens-key, c-type-internal-paren-kwds)
(c-type-internal-paren-key): New c-lang-const/vars.
(c-type-modifier-prefix-kwds, c-type-start-kwds): Amend with
the above new c-lang-consts.
(c-no-type-with-equals-kwds, c-no-type-with-equals-key): New
c-lang-const/vars.
(c-modifier-kwds): Add constexpr, auto, and thread_local to the
C value.
(c-paren-nontype-kwds): Add static_assert to the C value.
(c-constant-kwds): Add nullptr to the C value.
(c-regular-keywords-regexp): Include c-type-with-paren-kwds.
(c-recognize-nameless-type-decls): New c-lang-const/var.

* lisp/progmodes/cc-mode.el (c-leave-cc-mode-mode): Also clear
c-digit-separator properties.

(cherry picked from commit 8ddb8b0e45f150a5866c86af8ed2054b792761ff)

lisp/progmodes/cc-engine.el
lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-mode.el

index c52ecd8291b185a9254e55d0dfd3eaab48163f5c..29b412f903adafc85e6d9953eaa8ea66a318bf3f 100644 (file)
@@ -84,8 +84,9 @@
 ;; 'syntax-table
 ;;   Used to modify the syntax of some characters.  It is used to
 ;;   mark the "<" and ">" of angle bracket parens with paren syntax, to
-;;   "hide" obtrusive characters in preprocessor lines, and to mark C++
-;;   raw strings to enable their fontification.
+;;   "hide" obtrusive characters in preprocessor lines, to mark C++ raw
+;;   strings to enable their fontification, and to mark syntactically
+;;   wrong single quotes, again for their fontification.
 ;;
 ;;   This property is used on single characters and is therefore
 ;;   always treated as front and rear nonsticky (or start and end open
 ;;       Put on the brace which introduces a brace list and on the commas
 ;;       which separate the elements within it.
 ;;
-;; 'c-typedef This property is applied to the first character of a
-;;   "typedef" keyword.  It's value is a list of the identifiers that
-;;   the "typedef" declares as types.
+;; 'c-digit-separator
+;;   Used for digit separators in numeric literals, where it gets set
+;;   with the value t.
+;;
+;; 'c-typedef
+;;   This property is applied to the first character of a "typedef"
+;;   keyword.  It's value is a list of the identifiers that the "typedef"
+;;   declares as types.
 ;;
 ;; 'c-awk-NL-prop
 ;;   Used in AWK mode to mark the various kinds of newlines.  See
@@ -713,11 +719,11 @@ comment at the start of cc-engine.el for more info."
 
 \f
 (defmacro c-looking-at-c++-attribute ()
-  ;; If we're in C++ Mode, and point is at the [[ introducing an attribute,
-  ;; return the position of the end of the attribute, otherwise return nil.
-  ;; The match data are NOT preserved over this macro.
+  ;; If we're in C or C++ Mode, and point is at the [[ introducing an
+  ;; attribute, return the position of the end of the attribute, otherwise
+  ;; return nil.  The match data are NOT preserved over this macro.
   `(and
-    (c-major-mode-is 'c++-mode)
+    (c-major-mode-is '(c-mode c++-mode))
     (looking-at "\\[\\[")
     (save-excursion
       (and
@@ -1511,7 +1517,7 @@ comment at the start of cc-engine.el for more info."
             ;; In a string/comment?
             ((setq lit-range (c-literal-limits from))
              (goto-char (cdr lit-range)))
-            ;; Skip over a C++ attribute?
+            ;; Skip over a C or C++ attribute?
             ((eq (char-after) ?\[)
              (if (setq attr-end (c-looking-at-c++-attribute))
                  (goto-char attr-end)
@@ -1946,11 +1952,11 @@ comment at the start of cc-engine.el for more info."
 (defvar c-sws-lit-limits nil)
 
 (defun c-enclosing-c++-attribute ()
-  ;; If we're in C++ Mode, and point is within a correctly balanced [[ ... ]]
-  ;; attribute structure, return a cons of its starting and ending positions.
-  ;; Otherwise, return nil.
+  ;; If we're in C or C++ Mode, and point is within a correctly balanced [[
+  ;; ... ]] attribute structure, return a cons of its starting and ending
+  ;; positions.  Otherwise, return nil.
   (and
-   (c-major-mode-is 'c++-mode)
+   (c-major-mode-is '(c-mode c++-mode))
    (save-excursion
      (let ((lim (max (- (point) 200) (point-min)))
           cand)
@@ -2139,7 +2145,7 @@ comment at the start of cc-engine.el for more info."
     (when (or (looking-at c-syntactic-ws-start)
              (and c-opt-cpp-prefix
                   (looking-at c-noise-macro-name-re))
-             (and (c-major-mode-is 'c++-mode)
+             (and (c-major-mode-is '(c-mode c++-mode))
                   (looking-at "\\[\\["))
              (looking-at c-doc-line-join-re))
 
@@ -2397,7 +2403,7 @@ comment at the start of cc-engine.el for more info."
                      (re-search-backward doc-line-join-here
                                          (c-point 'bopl) t))
                     (and
-                     (c-major-mode-is 'c++-mode)
+                     (c-major-mode-is '(c-mode c++-mode))
                      (eq (char-before) ?\])
                      (eq (char-before (1- (point))) ?\])
                      (save-excursion
@@ -2570,7 +2576,7 @@ comment at the start of cc-engine.el for more info."
              (goto-char next-rung-pos)
              t)
 
-            ((and (c-major-mode-is 'c++-mode)
+            ((and (c-major-mode-is '(c-mode c++-mode))
                   (eq (char-before) ?\])
                   (eq (char-before (1- (point))) ?\])
                   (save-excursion
@@ -8626,15 +8632,35 @@ multi-line strings (but not C++, for example)."
       (goto-char here)
       nil)))
 
+(defmacro c-forward-align-clause-throw-if-invalid (throw-tag)
+  ;; If we are at a `c-type-modifier-with-parens-key' keyword, try to go
+  ;; forward over the clause it introduces, and return t.  If the clause is
+  ;; ill formed (or absent), move point to START, set RES to nil, and throw
+  ;; nil to the tag THROW-TAG.  Otherwise, return nil.  The match data are
+  ;; preserved.
+  ;; This macro is intended only for use withing `c-forward-type'.
+  `(if (save-match-data
+        (looking-at c-type-modifier-with-parens-key))
+       (if (and (zerop (c-forward-token-2))
+               (eq (char-after) ?\()
+               (c-safe (c-go-list-forward))
+               (eq (char-before) ?\))
+               (setq pos (point))
+               (progn (c-forward-syntactic-ws) t))
+          t
+        (setq res nil)
+        (goto-char start)
+        (throw ,throw-tag nil))
+     nil))
+
 (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 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',
+  ;; Submatch MATCH in the current match data is assumed to surround a token.
+  ;; If it's a keyword, move over it and, if present, over any immediately
+  ;; 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',
   ;; `c-paren-nontype-kwds', `c-paren-type-kwds', `c-<>-type-kwds',
   ;; `c-<>-arglist-kwds', and `c-protection-kwds'.
   ;;
@@ -9321,7 +9347,7 @@ multi-line strings (but not C++, for example)."
   ;;   o - 'found if it's a type that matches one in `c-found-types';
   ;;   o - 'maybe if it's an identifier that might be a type;
   ;;   o - 'decltype if it's a decltype(variable) declaration; - or
-  ;;   o - 'no-id if "auto" precluded parsing a type identifier (C++)
+  ;;   o - 'no-id if "auto" precluded parsing a type identifier (C or C++)
   ;;      or the type int was implicit (C).
   ;;   o -  nil if it can't be a type (the point isn't moved then).
   ;;
@@ -9342,327 +9368,370 @@ 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 prefix-end-pos)
+       post-prefix-pos prefix-end-pos equals-makes-type)
 
     ;; Skip leading type modifiers.  If any are found we know it's a
     ;; prefix of a type.
-    (when c-maybe-typeless-specifier-re
-      (while (looking-at c-maybe-typeless-specifier-re)
-       (save-match-data
-         (when (looking-at c-no-type-key)
-           (setq res 'no-id)))
+    (catch 'type-error
+      (when c-maybe-typeless-specifier-re
+       (while (looking-at c-maybe-typeless-specifier-re)
+         (save-match-data
+           (when (looking-at c-no-type-key)
+             (setq res 'no-id))
+           (when (looking-at c-no-type-with-equals-key)
+             (setq equals-makes-type t)))
+         (if (c-forward-align-clause-throw-if-invalid 'type-error)
+             (setq prefix-end-pos pos)
+           (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)))))
+      (setq post-prefix-pos (point))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+      (cond
+       ((looking-at c-typeof-key)      ; e.g. C++'s "decltype".
        (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))))
-    (setq post-prefix-pos (point))
+       (setq res (and (eq (char-after) ?\()
+                      (c-safe (c-forward-sexp))
+                      'decltype))
+       (if res
+           (progn
+             (setq pos (point))
+             (c-forward-syntactic-ws))
+         (goto-char start)))
 
-    (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
-         (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)
+       ((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 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 t)
-              (setq pos (point))
-              (c-forward-syntactic-ws))))
+       (while (cond
+               ((looking-at c-decl-hangon-key)
+                (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 t)
+                (setq pos (point))
+                (c-forward-syntactic-ws))))
 
-      (setq id-start (point))
-      (setq name-res (c-forward-name t))
-      (setq pos (point))
-      (setq res (not (null name-res)))
-      (when (eq name-res t)
-       ;; With some keywords the name can be used without the prefix, so we
-       ;; add the name to `c-found-types' when this is the case.
-       (when (save-excursion
-               (goto-char post-prefix-pos)
-               (looking-at c-self-contained-typename-key))
-         (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)
-                           (setq pos (point))))))
-       (goto-char pos)
+       (setq id-start (point))
+       (setq name-res (c-forward-name t))
+       (setq pos (point))
+       (setq res (not (null name-res)))
+       (when (eq name-res t)
+         ;; With some keywords the name can be used without the prefix, so we
+         ;; add the name to `c-found-types' when this is the case.
+         (when (save-excursion
+                 (goto-char post-prefix-pos)
+                 (looking-at c-self-contained-typename-key))
+           (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)
-       (setq res t))
-      (unless res (goto-char start)))  ; invalid syntax
+       (when (and brace-block-too
+                  (memq res '(t nil))
+                  (eq (char-after) ?\{)
+                  (save-excursion
+                    (c-safe
+                      (progn (c-forward-sexp)
+                             (setq pos (point))))))
+         (goto-char pos)
+         (c-forward-syntactic-ws)
+         (setq res t))
+       (unless res (goto-char start))) ; invalid syntax
 
-     ((and
-       (not (eq res 'no-id))
-       (progn
-        (setq pos nil)
-        (while (and c-opt-cpp-prefix
-                    (looking-at c-noise-macro-with-parens-name-re))
-          (c-forward-noise-clause))
-        (if (looking-at c-identifier-start)
-            (save-excursion
-              (setq id-start (point)
-                    name-res (c-forward-name t))
-              (when name-res
-                (setq id-end (point)
-                      id-range c-last-identifier-range))))
-        (and (cond ((looking-at c-primitive-type-key)
-                    (setq res t))
-                   ((c-with-syntax-table c-identifier-syntax-table
-                      (looking-at c-known-type-key))
-                    (setq res 'known)))
-             (or (not id-end)
-                 (>= (save-excursion
-                       (save-match-data
-                         (goto-char (match-end 1))
-                         (setq pos (point))
-                         (c-forward-syntactic-ws)
-                         pos))
-                     id-end)
-                 (setq res nil)))))
-      ;; Looking at a primitive or known type identifier.  We've
-      ;; checked for a name first so that we don't go here if the
-      ;; known type match only is a prefix of another name.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-      (setq id-end (match-end 1))
+       ((looking-at c-type-with-paren-key) ; C's "_BitInt".
+       (goto-char (match-end 1))
+       (c-forward-syntactic-ws)
+       (if (and (eq (char-after) ?\()
+                (c-go-list-forward nil (min (+ (point) 500) (point-max)))
+                (eq (char-before) ?\)))
+           (progn
+             (setq pos (point))
+             (c-forward-syntactic-ws)
+             (setq res t))
+         (goto-char start)
+         (setq res nil)))              ; invalid syntax.
 
-      (when (and c-record-type-identifiers
-                (or c-promote-possible-types (eq res t)))
-       (c-record-type-id (cons (match-beginning 1) (match-end 1))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-      (cond
-       ((and c-opt-type-component-key
+       ((and
+        (not (eq res 'no-id))
+        (not (and equals-makes-type
+                  (save-excursion
+                    (and (zerop (c-forward-token-2))
+                         (looking-at "=\\([^=]\\|$\\)")))
+                  (setq res 'no-id)))
+        (progn
+          (setq pos nil)
+          (while (and c-opt-cpp-prefix
+                      (looking-at c-noise-macro-with-parens-name-re))
+            (c-forward-noise-clause))
+          (if (looking-at c-identifier-start)
+              (save-excursion
+                (setq id-start (point)
+                      name-res (c-forward-name t))
+                (when name-res
+                  (setq id-end (point)
+                        id-range c-last-identifier-range))))
+          (and (cond ((looking-at c-primitive-type-key)
+                      (setq res t))
+                     ((c-with-syntax-table c-identifier-syntax-table
+                        (looking-at c-known-type-key))
+                      (setq res 'known)))
+               (or (not id-end)
+                   (>= (save-excursion
+                         (save-match-data
+                           (goto-char (match-end 1))
+                           (setq pos (point))
+                           (c-forward-syntactic-ws)
+                           pos))
+                       id-end)
+                   (setq res nil)))))
+       ;; Looking at a primitive or known type identifier.  We've
+       ;; checked for a name first so that we don't go here if the
+       ;; known type match only is a prefix of another name.
+
+       (setq id-end (match-end 1))
+
+       (when (and c-record-type-identifiers
+                  (or c-promote-possible-types (eq res t)))
+         (c-record-type-id (cons (match-beginning 1) (match-end 1))))
+
+       (cond
+        ((and c-opt-type-component-key
               (save-match-data
                 (looking-at c-opt-type-component-key)))
          ;; There might be more keywords for the type.
-       (let (safe-pos)
-         (c-forward-keyword-clause 1 t)
+         (let (safe-pos)
+           (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))))
+             (or (c-forward-align-clause-throw-if-invalid 'type-error)
+                 (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 t)
+                 (setq res t)
+                 (while (progn
+                          (setq safe-pos (point))
+                          (c-forward-syntactic-ws)
+                          (looking-at c-opt-type-component-key))
+                   (c-forward-keyword-clause 1 t)))
+             (goto-char safe-pos)
+             (setq res 'prefix))
+           (setq pos (point))))
+        ((save-match-data (c-forward-keyword-clause 1 t))
          (while (progn
-                  (setq safe-pos (point))
+                  (setq 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 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 t)
-               (setq res t)
-               (while (progn
-                        (setq safe-pos (point))
-                        (c-forward-syntactic-ws)
-                        (looking-at c-opt-type-component-key))
-                 (c-forward-keyword-clause 1 t)))
-           (goto-char safe-pos)
-           (setq res 'prefix))
-         (setq pos (point))))
-       ((save-match-data (c-forward-keyword-clause 1 t))
-        (while (progn
-                 (setq pos (point))
-                 (c-forward-syntactic-ws)
-                 (and c-opt-type-component-key
-                      (looking-at c-opt-type-component-key)))
-          (c-forward-keyword-clause 1 t)))
-       (pos (goto-char pos))
-       (t (goto-char (match-end 1))
-          (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))
-                 (or
-                  (not (looking-at c-type-decl-prefix-key))
-                  (and (eq (char-after) ?\()
-                       (not (save-excursion
-                              (c-forward-declarator))))))))
-      ;; A C specifier followed by an implicit int, e.g.
-      ;; "register count;"
-      (goto-char prefix-end-pos)
-      (setq pos (point))
-      (unless stop-at-end
+                  (and c-opt-type-component-key
+                       (looking-at c-opt-type-component-key)))
+           (or (c-forward-align-clause-throw-if-invalid 'type-error)
+               (c-forward-keyword-clause 1 t))))
+        (pos (goto-char pos))
+        (t (goto-char (match-end 1))
+           (setq pos (point))))
        (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 id-end))
-                  (when (and c-record-type-identifiers id-range)
-                    (c-record-type-id id-range))
-                  (unless res
-                    (setq res 'found))
-                  (when (eq res 'prefix)
-                    (setq res t)))
-              (setq res (if (c-check-qualified-type id-start)
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+       ((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))
+                   (or
+                    (not (looking-at c-type-decl-prefix-key))
+                    (and (eq (char-after) ?\()
+                         (not (save-excursion
+                                (c-forward-declarator))))))))
+       ;; A C specifier followed by an implicit int, e.g.
+       ;; "register count;"
+       (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 id-end))
+                    (when (and c-record-type-identifiers id-range)
+                      (c-record-type-id id-range))
+                    (unless res
+                      (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.
+                              'found
+                            ;; It's an identifier that might be a type.
+                            'maybe))))
+             ((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) ?\()
+                        (if (c-check-qualified-type id-start)
                             ;; It's an identifier that has been used as
                             ;; a type somewhere else.
                             'found
                           ;; It's an identifier that might be a type.
-                          'maybe))))
-           ((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) ?\()
-                      (if (c-check-qualified-type id-start)
-                          ;; It's an identifier that has been used as
-                          ;; a type somewhere else.
-                          'found
-                        ;; It's an identifier that might be a type.
-                        'maybe)
-                    t)))
-           (t
-            ;; Otherwise it's an operator identifier, which is not a type.
-            (goto-char start)
-            (setq res nil))))
-
-     ((eq res 'prefix)
-      ;; Deal with "extern "C" foo_t my_foo;"
-      (setq res nil)))
-
-    (when (not (memq res '(nil no-id)))
-      ;; Skip trailing type modifiers.  If any are found we know it's
-      ;; a type.
-      (when c-opt-type-modifier-key
-       (while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
+                          'maybe)
+                      t)))
+             (t
+              ;; Otherwise it's an operator identifier, which is not a type.
+              (goto-char start)
+              (setq res nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+       ((eq res 'prefix)
+       ;; Deal with "extern "C" foo_t my_foo;"
+       (setq res nil)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+      (when (not (memq res '(nil no-id)))
+       ;; Skip trailing type modifiers.  If any are found we know it's
+       ;; a type.
+       (when c-opt-type-modifier-key
+         (while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
+           (unless (c-forward-align-clause-throw-if-invalid 'type-error)
+             (goto-char (match-end 1))
+             (setq pos (point))
+             (c-forward-syntactic-ws)
+             (setq res t))))
+
+       ;; Step over any type suffix operator.  Do not let the existence
+       ;; of these alter the classification of the found type, since
+       ;; these operators typically are allowed in normal expressions
+       ;; too.
+       (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)))
-
-      ;; Step over any type suffix operator.  Do not let the existence
-      ;; of these alter the classification of the found type, since
-      ;; these operators typically are allowed in normal expressions
-      ;; too.
-      (when c-opt-type-suffix-key      ; e.g. "..."
-       (while (looking-at c-opt-type-suffix-key)
-         (goto-char (match-end 1))
+         (setq res t))
+
+       (when c-opt-type-concat-key     ; Only/mainly for pike.
+         ;; Look for a trailing operator that concatenates the type
+         ;; with a following one, and if so step past that one through
+         ;; a recursive call.  Note that we don't record concatenated
+         ;; types in `c-found-types' - it's the component types that
+         ;; are recorded when appropriate.
          (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))
-
-      (when c-opt-type-concat-key      ; Only/mainly for pike.
-       ;; Look for a trailing operator that concatenates the type
-       ;; with a following one, and if so step past that one through
-       ;; a recursive call.  Note that we don't record concatenated
-       ;; types in `c-found-types' - it's the component types that
-       ;; are recorded when appropriate.
-       (setq pos (point))
-       (let* ((c-promote-possible-types (or (memq res '(t known))
-                                            c-promote-possible-types))
-              ;; If we can't promote then set `c-record-found-types' so that
-              ;; we can merge in the types from the second part afterwards if
-              ;; it turns out to be a known type there.
-              (c-record-found-types (and c-record-type-identifiers
-                                         (not c-promote-possible-types)))
-              subres)
-         (if (and (looking-at c-opt-type-concat-key)
+         (let* ((c-promote-possible-types (or (memq res '(t known))
+                                              c-promote-possible-types))
+                ;; If we can't promote then set `c-record-found-types' so that
+                ;; we can merge in the types from the second part afterwards if
+                ;; it turns out to be a known type there.
+                (c-record-found-types (and c-record-type-identifiers
+                                           (not c-promote-possible-types)))
+                subres)
+           (if (and (looking-at c-opt-type-concat-key)
 
-                  (progn
-                    (goto-char (match-end 1))
-                    (c-forward-syntactic-ws)
-                    (setq subres (c-forward-type nil t))
-                    (setq pos (point))))
-
-             (progn
-               ;; If either operand certainly is a type then both are, but we
-               ;; don't let the existence of the operator itself promote two
-               ;; uncertain types to a certain one.
-               (cond ((eq res t))
-                     ((eq subres t)
-                      (unless (eq name-res 'template)
-                        (c-add-type id-start id-end))
-                      (when (and c-record-type-identifiers id-range)
-                        (c-record-type-id id-range))
-                      (setq res t))
-                     ((eq res 'known))
-                     ((eq subres 'known)
-                      (setq res 'known))
-                     ((eq res 'found))
-                     ((eq subres 'found)
-                      (setq res 'found))
-                     (t
-                      (setq res 'maybe)))
-
-               (when (and (eq res t)
-                          (consp c-record-found-types))
-                 ;; Cause the confirmed types to get fontified.
-                 (let ((cur c-record-found-types))
-                   (while (consp (car-safe cur))
-                     (c-fontify-new-found-type
-                      (buffer-substring-no-properties (caar cur) (cdar cur)))
-                     (setq cur (cdr cur))))
-                 ;; Merge in the ranges of any types found by the second
-                 ;; `c-forward-type'.
-                 (setq c-record-type-identifiers
-                       ;; `nconc' doesn't mind that the tail of
-                       ;; `c-record-found-types' is t.
-                       (nconc c-record-found-types
-                              c-record-type-identifiers)))))))
+                    (progn
+                      (goto-char (match-end 1))
+                      (c-forward-syntactic-ws)
+                      (setq subres (c-forward-type nil t))
+                      (setq pos (point))))
 
-      (goto-char pos)
-      (unless stop-at-end
-       (c-forward-syntactic-ws))
+               (progn
+                 ;; If either operand certainly is a type then both are, but we
+                 ;; don't let the existence of the operator itself promote two
+                 ;; uncertain types to a certain one.
+                 (cond ((eq res t))
+                       ((eq subres t)
+                        (unless (eq name-res 'template)
+                          (c-add-type id-start id-end))
+                        (when (and c-record-type-identifiers id-range)
+                          (c-record-type-id id-range))
+                        (setq res t))
+                       ((eq res 'known))
+                       ((eq subres 'known)
+                        (setq res 'known))
+                       ((eq res 'found))
+                       ((eq subres 'found)
+                        (setq res 'found))
+                       (t
+                        (setq res 'maybe)))
+
+                 (when (and (eq res t)
+                            (consp c-record-found-types))
+                   ;; Cause the confirmed types to get fontified.
+                   (let ((cur c-record-found-types))
+                     (while (consp (car-safe cur))
+                       (c-fontify-new-found-type
+                        (buffer-substring-no-properties (caar cur) (cdar cur)))
+                       (setq cur (cdr cur))))
+                   ;; Merge in the ranges of any types found by the second
+                   ;; `c-forward-type'.
+                   (setq c-record-type-identifiers
+                         ;; `nconc' doesn't mind that the tail of
+                         ;; `c-record-found-types' is t.
+                         (nconc c-record-found-types
+                                c-record-type-identifiers)))))))
 
-      (when (and c-record-found-types (memq res '(known found)) id-range)
-       (setq c-record-found-types
-             (cons id-range c-record-found-types))))
+       (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
+               (cons id-range c-record-found-types)))))
     ;;(message "c-forward-type %s -> %s: %s" start (point) res)
 
     res))
@@ -9998,6 +10067,32 @@ point unchanged and return nil."
   (and (zerop (c-forward-token-2))     ; over "requires".
        (c-forward-constraint-clause limit stop-at-end)))
 
+(defun c-in-id-arglist ()
+  ;; If point is inside a paren delimited non-empty arglist, all of whose
+  ;; arguments are identifiers, return a cons of the start and (after) the end
+  ;; of the arglist.  Otherwise return nil.
+  (let* ((paren-state (c-parse-state))
+        (enclosing-paren-pos (c-most-enclosing-brace paren-state)))
+    (save-excursion
+      (and
+       enclosing-paren-pos
+       (eq (char-after enclosing-paren-pos) ?\()
+       (progn
+        (goto-char (1+ enclosing-paren-pos))
+        (c-forward-syntactic-ws)
+        (catch 'in-arglist
+          (while
+              (and
+               (c-on-identifier)
+               (zerop (c-forward-token-2))
+               (progn
+                 (when (eq (char-after) ?\))
+                   (throw 'in-arglist
+                          (cons enclosing-paren-pos (1+ (point)))))
+                 (eq (char-after) ?\,))
+               (zerop (c-forward-token-2))))
+          nil))))))
+
 (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,
@@ -11276,10 +11371,13 @@ This function might do hidden buffer changes."
                      ;; style declarations and parenthesis style initializers
                      ;; aren't allowed then the single identifier must be a
                      ;; type, else we require that it's known or found
-                     ;; (primitive types are handled above).
+                     ;; (primitive types are handled above).  We also allow
+                     ;; 'maybe types when nameless types can be in arglists.
                      (or (and (not c-recognize-knr-p)
                               (not c-recognize-paren-inits))
-                         (memq at-type '(known found))))
+                         (memq at-type '(known found))
+                         (and c-recognize-nameless-type-decls
+                              (eq at-type 'maybe))))
                     ((eq context '<>)
                      ;; Inside a template arglist.  Accept known and found
                      ;; types; other identifiers could just as well be
index ac5a32f704f56f54be318fa461baec302192807a..eca249ee2f6536f85619caf43ba1592b74d65c39 100644 (file)
       (c-put-font-lock-face (car elem) (cdr elem)
                            c-reference-face-name))))
 
+(defun c-font-lock-cpp-messages (limit)
+  ;; Font lock #error and #warning messages between point and LIMIT.
+  ;; Always return nil to prevent a further call to this function.
+  ;; The position of point at the end of this function is random.
+  (while
+      (and (< (point) limit)
+          (re-search-forward c-cpp-messages-re limit t))
+    (let ((beg (match-beginning c-cpp-message-match-no))
+         (end (match-end c-cpp-message-match-no)))
+      (c-put-font-lock-string-face beg end)
+      ;; We replace '(1) (punctuation) syntax-table text properties on ' by
+      ;; '(3) (symbol), so that these characters won't later get the warning
+      ;; face.
+      (goto-char beg)
+      (while (and
+             (< (point) end)
+             (c-search-forward-char-property-with-value-on-char
+              'syntax-table '(1) ?\' end))
+       (c-put-char-property ;; -trim-caches
+                           (1- (point)) 'syntax-table '(3)))
+      (goto-char end)))
+  nil)
+
 (c-lang-defconst c-cpp-matchers
   "Font lock matchers for preprocessor directives and purely lexical
 stuff.  Used on level 1 and higher."
@@ -529,28 +552,20 @@ stuff.  Used on level 1 and higher."
   ;; sets `font-lock-type-face' in languages where
   ;; `c-recognize-<>-arglists' is set.
 
-  t `(,@(when (c-lang-const c-opt-cpp-prefix)
+  t `(;; Fontify "invalid" comment delimiters
+      ,@(when (and (c-lang-const c-block-comment-starter)
+                  (c-lang-const c-line-comment-starter))
+         `(c-maybe-font-lock-wrong-style-comments))
+      ,@(when (c-lang-const c-opt-cpp-prefix)
          (let* ((noncontinued-line-end "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)")
                 (ncle-depth (regexp-opt-depth noncontinued-line-end))
                 (sws-depth (c-lang-const c-syntactic-ws-depth))
                 (nsws-depth (c-lang-const c-nonempty-syntactic-ws-depth)))
 
-           `(;; Fontify "invalid" comment delimiters
-             ,@(when (and (c-lang-const c-block-comment-starter)
-                          (c-lang-const c-line-comment-starter))
-                 `(c-maybe-font-lock-wrong-style-comments))
-
-             ;; The stuff after #error and #warning is a message, so
+           `(;; The stuff after #error and #warning is a message, so
              ;; fontify it as a string.
              ,@(when (c-lang-const c-cpp-message-directives)
-                 (let* ((re (c-make-keywords-re 'appendable ; nil
-                              (c-lang-const c-cpp-message-directives)))
-                        (re-depth (regexp-opt-depth re)))
-                   `((,(concat noncontinued-line-end
-                               (c-lang-const c-opt-cpp-prefix)
-                               re
-                               "\\s +\\(.*\\)$")
-                      ,(+ ncle-depth re-depth 1) font-lock-string-face t))))
+                 '(c-font-lock-cpp-messages))
 
              ;; Fontify filenames in #include <...> as strings.
              ,@(when (c-lang-const c-cpp-include-directives)
@@ -1219,22 +1234,29 @@ casts and declarations are fontified.  Used on level 2 and higher."
   ;; characters it allows within the list.
   (let ((type (and (> match-pos (point-min))
                   (c-get-char-property (1- match-pos) 'c-type)))
-       id-pos)
+       id-pos tok-end-pos)
     (cond
      ;; Are we just after something like "(foo((bar))" ?
      ((and (eq (char-before match-pos) ?\))
           (c-go-list-backward match-pos)
           (progn
             (c-backward-syntactic-ws)
-            (and (setq id-pos (c-on-identifier))
-                 (goto-char id-pos)
-                 (progn
-                   (c-backward-syntactic-ws)
-                   (eq (char-before) ?\()))))
-      (c-get-fontification-context (point) not-front-decl toplev))
+            (setq tok-end-pos (point))
+            (cond
+             ((and (setq id-pos (c-on-identifier))
+                   (goto-char id-pos)
+                   (progn
+                     (c-backward-syntactic-ws)
+                     (eq (char-before) ?\()))
+              (c-get-fontification-context (point) not-front-decl toplev))
+             ((progn
+                (goto-char tok-end-pos)
+                (and (zerop (c-backward-token-2))
+                     (looking-at c-type-internal-paren-key)))
+              (cons 'not-decl nil))))))
      ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{)))
       (cons (and toplev 'top) nil))
-     ;; A control flow expression or a decltype
+     ;; A control flow expression or a decltype, etc.
      ((and (eq (char-before match-pos) ?\()
           (save-excursion
             (goto-char match-pos)
@@ -1246,7 +1268,8 @@ casts and declarations are fontified.  Used on level 2 and higher."
               (cons nil nil))
              ((or (looking-at c-block-stmt-2-key)
                   (looking-at c-block-stmt-1-2-key)
-                  (looking-at c-typeof-key))
+                  (looking-at c-typeof-key)
+                  (looking-at c-type-internal-paren-key))
               (cons nil t))
              (t nil)))))
      ;; Near BOB.
@@ -1531,8 +1554,8 @@ casts and declarations are fontified.  Used on level 2 and higher."
            ;; `parse-sexp-lookup-properties' (when it exists).
            (parse-sexp-lookup-properties
             (cc-eval-when-compile
-              (boundp 'parse-sexp-lookup-properties))
-            ))
+              (boundp 'parse-sexp-lookup-properties)))
+           list-bounds)
 
        ;; Below we fontify a whole declaration even when it crosses the limit,
        ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a
@@ -1622,6 +1645,24 @@ casts and declarations are fontified.  Used on level 2 and higher."
                   nil)
                  ((eq context 'generic)
                   (c-font-lock-c11-generic-clause))
+
+                 ;; K&R parameters.
+                 ((and
+                   c-recognize-knr-p
+                   (or toplev inside-macro)
+                   (eq context 'decl)
+                   (setq list-bounds (c-in-id-arglist))
+                   (save-excursion
+                     (goto-char (car list-bounds))
+                     (and (zerop (c-backward-token-2))
+                          (eq (point) (c-on-identifier))))
+                   (save-excursion
+                     (goto-char (cdr list-bounds))
+                     (c-forward-syntactic-ws)
+                     (not (memq (char-after) '(?\; ?{ ?\? ?: ?\,)))))
+                  ;; Nothing to fontify.
+                  (goto-char (cdr list-bounds)))
+
                  (t
                   (setq decl-or-cast
                         (c-forward-decl-or-cast-1
@@ -2371,7 +2412,10 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
 
       ;; Fontify basic types.
       ,(let ((re (c-make-keywords-re nil
-                  (c-lang-const c-primitive-type-kwds))))
+                  (cl-delete-duplicates
+                   (append (c-lang-const c-primitive-type-kwds)
+                           (c-lang-const c-type-with-paren-kwds))
+                   :test #'equal))))
         (if (c-major-mode-is 'pike-mode)
             ;; No symbol is a keyword after "->" in Pike.
             `(,(concat "\\(\\=.?\\|[^>]\\|[^-]>\\)"
index 17fb51aaeac7f0ac15724b19778b2bc550f299df..772b09e1f979a057d7a0acc15f5cabc7a57b7ad9 100644 (file)
@@ -835,7 +835,7 @@ there be copies of the opener contained in the multi-line string."
 (c-lang-defconst c-has-quoted-numbers
   "Whether the language has numbers quoted like 4'294'967'295."
   t nil
-  c++ t)
+  (c c++) t)
 (c-lang-defvar c-has-quoted-numbers (c-lang-const c-has-quoted-numbers))
 
 (c-lang-defconst c-has-compound-literals
@@ -1172,11 +1172,37 @@ string message."
           '("error"))
   (c c++ objc pike) '("error" "warning"))
 
+(c-lang-defconst c-cpp-message-directives-re
+  ;; Appendable regexp matching any of the tokens in `c-cpp-message-directives'.
+  t (c-make-keywords-re 'appendable (c-lang-const c-cpp-message-directives)))
+
+(c-lang-defconst noncontinued-line-end
+  t "\\(\\=\\|\\(\\=\\|[^\\]\\)[\n\r]\\)")
+(c-lang-defconst ncle-depth
+  t (regexp-opt-depth (c-lang-const noncontinued-line-end)))
+
+(c-lang-defconst c-cpp-messages-re
+  ;; Regexp to match a #error or #warning construct.  See
+  ;; `c-cpp-message-directives'.
+  t (if (c-lang-const c-cpp-message-directives)
+       (concat (c-lang-const noncontinued-line-end)
+               (c-lang-const c-opt-cpp-prefix)
+               (c-lang-const c-cpp-message-directives-re)
+               "\\s +\\(\\(\\\\\\(\\\\?\n\\|.\\)\\|[^\n]\\)*\\)$")))
+(c-lang-defvar c-cpp-messages-re (c-lang-const c-cpp-messages-re))
+
+(c-lang-defconst c-cpp-message-match-no
+    t (if (c-lang-const c-cpp-messages-re)
+         (+ 1 (c-lang-const ncle-depth)
+            (regexp-opt-depth (c-lang-const c-cpp-message-directives-re)))))
+(c-lang-defvar c-cpp-message-match-no (c-lang-const c-cpp-message-match-no))
+
 (c-lang-defconst c-cpp-include-directives
   "List of cpp directives (without the prefix) that are followed by a
 file name in angle brackets or quotes."
   t    (if (c-lang-const c-opt-cpp-prefix)
           '("include"))
+  c '("include" "embed")
   objc '("include" "import"))
 
 (c-lang-defconst c-cpp-include-key
@@ -1235,7 +1261,8 @@ definition, or nil if the language doesn't have any."
   "List of cpp directives (without the prefix) that are followed by an
 expression."
   t (if (c-lang-const c-opt-cpp-prefix)
-       '("if" "elif")))
+       '("if" "elif"
+         "elifdef" "elifndef")))
 
 (c-lang-defconst c-cpp-expr-intro-re
   "Regexp which matches the start of a CPP directive which contains an
@@ -1751,9 +1778,10 @@ This doesn't count the merely contextual bits of the regexp match."
                (c-lang-const c-opt-cpp-symbol) ; usually #
                (substring (c-lang-const c-stmt-delim-chars) 1)) ; ";{}?:"
       (c-lang-const c-stmt-delim-chars))
-  c++ (concat (substring (c-lang-const c-stmt-boundary-skip-chars) 0 1) ; "^"
-             "["
-             (substring (c-lang-const c-stmt-boundary-skip-chars) 1))) ; ";{}?:"
+  (c c++) (concat
+          (substring (c-lang-const c-stmt-boundary-skip-chars) 0 1) ; "^"
+          "["
+          (substring (c-lang-const c-stmt-boundary-skip-chars) 1))) ; ";{}?:"
 (c-lang-defvar c-stmt-boundary-skip-chars
   (c-lang-const c-stmt-boundary-skip-chars))
 
@@ -2250,7 +2278,7 @@ This works in Emacs >= 25.1."
 ;; `c-kwds-lang-consts' list below and used to build `c-keywords' etc.
 
 (c-lang-defconst c-primitive-type-kwds
-  "Primitive type keywords.  As opposed to the other keyword lists, the
+  "Primitive type keywords.  As opposed to most other keyword lists, the
 keywords listed here are fontified with the type face instead of the
 keyword face.
 
@@ -2265,10 +2293,12 @@ the appropriate place for that."
   t    '("char" "double" "float" "int" "long" "short" "signed"
         "unsigned" "void")
   c    (append
-       '("_Bool" "_Complex" "_Imaginary") ; Conditionally defined in C99.
+       '("_Bool" "_Complex" "_Imaginary" ;) Conditionally defined in C99.
+         "_Decimal32" "_Decimal64" "_Decimal128"
+         "bool" "char8_t" "char16_t" "char32_t" "nullptr_t")
        (c-lang-const c-primitive-type-kwds))
   c++  (append
-       '("bool" "wchar_t" "char8_t" "char16_t" "char32_t")
+       '("bool" "wchar_t" "char8_t" "char16_t" "char32_t" "nullptr_t")
        (c-lang-const c-primitive-type-kwds))
   ;; Objective-C extends C, but probably not the new stuff in C99.
   objc (append
@@ -2327,7 +2357,7 @@ of a variable declaration."
   "Keywords followed by a parenthesized expression, which stands for
 the type of that expression."
   t nil
-  c '("typeof")                                ; longstanding GNU C(++) extension.
+  c '("typeof" "typeof_unqual")
   c++ '("decltype" "typeof"))
 
 (c-lang-defconst c-typeof-key
@@ -2357,6 +2387,16 @@ used in declarations without the keyword."
 (c-lang-defvar c-self-contained-typename-key
               (c-lang-const c-self-contained-typename-key))
 
+(c-lang-defconst c-type-with-paren-kwds
+  "Keywords followed by a parenthesis expression, which form types."
+  t nil
+  c '("_BitInt"))
+
+(c-lang-defconst c-type-with-paren-key
+  "Adorned regexp which matches an element of `c-type-with-paren-kwds'."
+  t (c-make-keywords-re t (c-lang-const c-type-with-paren-kwds)))
+(c-lang-defvar c-type-with-paren-key (c-lang-const c-type-with-paren-key))
+
 (c-lang-defconst c-type-prefix-kwds
   "Keywords where the following name - if any - is a type name, and
 where the keyword together with the symbol works as a type in
@@ -2375,6 +2415,31 @@ on one of the `*-decl-kwds' lists."
   t (c-make-keywords-re t (c-lang-const c-type-prefix-kwds)))
 (c-lang-defvar c-type-prefix-key (c-lang-const c-type-prefix-key))
 
+(c-lang-defconst c-type-modifier-with-parens-kwds
+  "Keywords which have parenthesis expressions which modify a type.
+They can appear anywhere in the type.  Not included here are kwds which
+stand in place of a type, namely those in `c-no-type-kwds'."
+  t nil
+  c '("alignof" "alignas" "_Alignas" "_Alignof"))
+
+(c-lang-defconst c-type-modifier-with-parens-key
+  ;; Adorned regexp matching `c-type-modifier-with-parens-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-type-modifier-with-parens-kwds)))
+(c-lang-defvar c-type-modifier-with-parens-key
+  (c-lang-const c-type-modifier-with-parens-key))
+
+(c-lang-defconst c-type-internal-paren-kwds
+  ;; Keywords which can be followed by a parenthesis expression inside a type
+  ;; specification.
+  t (append (c-lang-const c-type-with-paren-kwds)
+           (c-lang-const c-type-modifier-with-parens-kwds)))
+
+(c-lang-defconst c-type-internal-paren-key
+  ;; Adorned regexp matching any member of `c-type-internal-paren-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-type-internal-paren-kwds)))
+(c-lang-defvar c-type-internal-paren-key
+  (c-lang-const c-type-internal-paren-key))
+
 (c-lang-defconst c-type-modifier-prefix-kwds
   "Type modifier keywords which can appear in front of a type.  These can
 also occur almost anywhere in types but they don't build a type of
@@ -2386,6 +2451,7 @@ fontified with the keyword face and not the type face."
   objc '("const" "volatile")
   java '("final")
   t    (append (c-lang-const c-no-type-kwds)
+              (c-lang-const c-type-modifier-with-parens-kwds)
               (c-lang-const c-type-modifier-prefix-kwds)))
 
 (c-lang-defconst c-opt-type-modifier-prefix-key
@@ -2427,7 +2493,8 @@ the type face."
   ;; or a complete type).
   t (c--delete-duplicates (append (c-lang-const c-primitive-type-kwds)
                                  (c-lang-const c-type-prefix-kwds)
-                                 (c-lang-const c-type-modifier-kwds))
+                                 (c-lang-const c-type-modifier-kwds)
+                                 (c-lang-const c-type-with-paren-kwds))
                          :test 'string-equal))
 
 (c-lang-defconst c-type-decl-suffix-ws-ids-kwds
@@ -2539,7 +2606,7 @@ and precede the opening brace."
   "Set to t when we recognize a colon and then a type after an enum,
 e.g., enum foo : int { A, B, C };"
   t nil
-  c++ t)
+  (c c++) t)
 (c-lang-defvar c-recognize-post-brace-list-type-p
               (c-lang-const c-recognize-post-brace-list-type-p))
 
@@ -2644,6 +2711,17 @@ will be handled."
   t (c-make-keywords-re t (c-lang-const c-no-type-kwds)))
 (c-lang-defvar c-no-type-key (c-lang-const c-no-type-key))
 
+(c-lang-defconst c-no-type-with-equals-kwds
+  "Keywords after which no type is needed when there's an = sign."
+  t nil
+  c '("auto"))
+
+(c-lang-defconst c-no-type-with-equals-key
+  ;; Regexp mathing an entry from `c-no-type-with-equals-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-no-type-with-equals-kwds)))
+(c-lang-defvar c-no-type-with-equals-key
+  (c-lang-const c-no-type-with-equals-key))
+
 (c-lang-defconst c-typeless-decl-kwds
   "Keywords introducing declarations where the (first) identifier
 \(declarator) follows directly after the keyword, without any type.
@@ -2750,10 +2828,12 @@ If any of these also are on `c-type-list-kwds', `c-ref-list-kwds',
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
   t    nil
-  (c c++) '("extern" "inline" "register" "static")
-  c    (append '("auto") (c-lang-const c-modifier-kwds))
-  c++  (append '("consteval" "constexpr" "constinit" "explicit"
-                "friend" "mutable" "template" "thread_local" "virtual")
+  (c c++) '("constexpr" "extern" "inline" "register"
+           "static" "thread_local")
+  c    (append '("auto" "_Thread_local")
+              (c-lang-const c-modifier-kwds))
+  c++  (append '("consteval" "constinit" "explicit"
+                "friend" "mutable" "template" "virtual")
               ;; "using" is now handled specially (2020-09-14).
               (c-lang-const c-modifier-kwds))
   objc '("auto" "bycopy" "byref" "extern" "in" "inout" "oneway" "out" "static")
@@ -3061,7 +3141,9 @@ contain type identifiers."
   (c c++) '(;; GCC extension.
            "__attribute__"
            ;; MSVC extension.
-           "__declspec")
+           "__declspec"
+           "static_assert")
+  c (append (c-lang-const c-paren-nontype-kwds) '("_Static_assert"))
   c++ (append (c-lang-const c-paren-nontype-kwds) '("noexcept" "alignas")))
 
 (c-lang-defconst c-paren-nontype-key
@@ -3337,11 +3419,9 @@ not really template operators."
 (c-lang-defconst c-constant-kwds
   "Keywords for constants."
   t       nil
-  c       '("NULL" ;; Not a keyword, but practically works as one.
-           "false" "true")             ; Defined in C99.
-  c++     (append
-           '("nullptr")
-           (c-lang-const c-constant-kwds c))
+  (c c++) '("NULL" ;; Not a keyword, but practically works as one.
+           "false" "true"              ; Defined in C99.
+           "nullptr")
   objc    '("nil" "Nil" "YES" "NO" "IBAction" "IBOutlet"
            "NS_DURING" "NS_HANDLER" "NS_ENDHANDLER")
   idl     '("TRUE" "FALSE")
@@ -3618,7 +3698,8 @@ Note that Java specific rules are currently applied to tell this from
   t (c-make-keywords-re t
       (c--set-difference (c-lang-const c-keywords)
                         (append (c-lang-const c-primitive-type-kwds)
-                                (c-lang-const c-constant-kwds))
+                                (c-lang-const c-constant-kwds)
+                                (c-lang-const c-type-with-paren-kwds))
                         :test 'string-equal)))
 (c-lang-defvar c-regular-keywords-regexp
   (c-lang-const c-regular-keywords-regexp))
@@ -4237,6 +4318,13 @@ This is only used in c++-mode."
 (c-lang-defvar c-pre-brace-non-bracelist-key
   (c-lang-const c-pre-brace-non-bracelist-key))
 
+(c-lang-defconst c-recognize-nameless-type-decls
+  "Non-nil means a type may be used in an arglist without an identifier."
+  t nil
+  c t)
+(c-lang-defvar c-recognize-nameless-type-decls
+  (c-lang-const c-recognize-nameless-type-decls))
+
 (c-lang-defconst c-recognize-typeless-decls
   "Non-nil means function declarations without return type should be
 recognized.  That can introduce an ambiguity with parenthesized macro
index d500fb299594f7e8ce02769c5ab72ba01bbcca31..e559265d2952c2a025ee5e542a1b4e77f4d9ed2e 100644 (file)
        (c-clear-char-properties (point-min) (point-max) 'c-is-sws)
        (c-clear-char-properties (point-min) (point-max) 'c-in-sws)
        (c-clear-char-properties (point-min) (point-max) 'c-type)
+       (if c-has-quoted-numbers
+           (c-clear-char-properties (point-min) (point-max) 'c-digit-separator))
        (if (c-major-mode-is 'awk-mode)
            (c-clear-char-properties (point-min) (point-max) 'c-awk-NL-prop))))
     (setq c-buffer-is-cc-mode nil)))
@@ -2583,7 +2585,7 @@ with // and /*, not more generic line and block comments."
       (goto-char (car ml-delim)))
     (c-backward-syntactic-ws lim)
     (when (setq enclosing-attribute (c-enclosing-c++-attribute))
-      (goto-char (car enclosing-attribute)) ; Only happens in C++ Mode.
+      (goto-char (car enclosing-attribute)) ; Only happens in C or C++ Mode.
       (c-backward-syntactic-ws lim))
     (while (and (> (point) lim)
                (memq (char-before) '(?\[ ?\()))