emacs-diffs
[Top][All Lists]
Advanced

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

master 622724e95d: CC Mode: Fontify cast types without adding them to c-


From: Alan Mackenzie
Subject: master 622724e95d: CC Mode: Fontify cast types without adding them to c-found-types
Date: Fri, 28 Oct 2022 13:53:55 -0400 (EDT)

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

    CC Mode: Fontify cast types without adding them to c-found-types
    
    * lisp/progmodes/cc-engine.el (c-forward-type): Test for the special new
    value `just-one' of c-promote-possible-types, and if found, fontify the 
type,
    but don't add it to c-found-types.
    (c-forward-decl-or-cast-1): Add the new &optional parameter inside-macro.
    Whilst checking for a cast construct, analyze the text following the closing
    paren more rigorously.
    Check for, and allow, the closing paren of a macro arglist before the 
putative
    cast construct.
    
    * lisp/progmodes/cc-fonts.el (c-font-lock-declarations): In the lambda
    function, pass the parameter inside-macro to c-forward-decl-or-cast-1.
    
    * lisp/progmodes/cc-langs.el (c-primary-expr-regexp-details): New
    c-lang-defvar which calculates `c-primary-expr-regexp' and three match
    numbers for various sub-expressions in the regexp.
    (c-primary-expr-regexp): Now extracted from `c-primary-expr-regexp-details'.
    (c-per-++---match, c-per-&*+--match, c-per-\(-match): New
    c-lang-defconsts/vars extracted from `c-primary-expr-regexp-details'.
---
 lisp/progmodes/cc-engine.el |  62 +++++++++----
 lisp/progmodes/cc-fonts.el  |   2 +-
 lisp/progmodes/cc-langs.el  | 207 +++++++++++++++++++++++++++++++++-----------
 3 files changed, 201 insertions(+), 70 deletions(-)

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index ed06807a87..d730fddeb0 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -8194,7 +8194,8 @@ multi-line strings (but not C++, for example)."
 ;; treat possible types (i.e. those that it normally returns 'maybe or
 ;; 'found for) as actual types (and always return 'found for them).
 ;; This means that it records them in `c-record-type-identifiers' if
-;; that is set, and that it adds them to `c-found-types'.
+;; that is set, and that if its value is t (not 'just-one), it adds
+;; them to `c-found-types'.
 (defvar c-promote-possible-types nil)
 
 ;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
@@ -9191,10 +9192,11 @@ multi-line strings (but not C++, for example)."
             (goto-char id-end)
             (if (or res c-promote-possible-types)
                 (progn
-                  (c-add-type id-start (save-excursion
-                                         (goto-char id-end)
-                                         (c-backward-syntactic-ws)
-                                         (point)))
+                  (when (not (eq c-promote-possible-types 'just-one))
+                    (c-add-type id-start (save-excursion
+                                           (goto-char id-end)
+                                           (c-backward-syntactic-ws)
+                                           (point))))
                   (when (and c-record-type-identifiers id-range)
                     (c-record-type-id id-range))
                   (unless res
@@ -10029,7 +10031,8 @@ This function might do hidden buffer changes."
        ;; This identifier is bound only in the inner let.
        '(setq start id-start))))
 
-(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end)
+(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end
+                                                    &optional inside-macro)
   ;; Move forward over a declaration or a cast if at the start of one.
   ;; The point is assumed to be at the start of some token.  Nil is
   ;; returned if no declaration or cast is recognized, and the point
@@ -10118,6 +10121,10 @@ This function might do hidden buffer changes."
   ;; matched.  In that case it's used to discover chains of casts like
   ;; "(a) (b) c".
   ;;
+  ;; INSIDE-MACRO is t when we definitely know we're inside a macro, nil
+  ;; otherwise.  We use it to disambiguate things like "(a) (b);", which is
+  ;; likely a function call in a macro, but a cast outside of one.
+  ;;
   ;; This function records identifier ranges on
   ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
   ;; `c-record-type-identifiers' is non-nil.
@@ -11102,11 +11109,17 @@ This function might do hidden buffer changes."
                   ;; Check if the expression begins with a prefix keyword.
                   (match-beginning 2)
                   (if (match-beginning 1)
-                      ;; Expression begins with an ambiguous operator.  Treat
-                      ;; it as a cast if it's a type decl or if we've
-                      ;; recognized the type somewhere else.
-                      (or at-decl-or-cast
-                          (memq at-type '(t known found)))
+                      ;; Expression begins with an ambiguous operator.
+                      (cond
+                       ((match-beginning c-per-&*+--match)
+                        (memq at-type '(t known found)))
+                       ((match-beginning c-per-++---match)
+                        t)
+                       ((match-beginning c-per-\(-match)
+                        (or
+                         (memq at-type '(t known found))
+                         (not inside-macro)))
+                       (t nil))
                     ;; Unless it's a keyword, it's the beginning of a primary
                     ;; expression.
                     (not (looking-at c-keywords-regexp)))))
@@ -11132,18 +11145,33 @@ This function might do hidden buffer changes."
                     ;; surrounding parens).
                     (looking-at c-simple-stmt-key)
                   (and
-                   ;; Check that it isn't a close paren (block close is ok,
-                   ;; though).
-                   (not (memq (char-before) '(?\) ?\])))
+                   ;; Check that it isn't a close paren (block close , or a
+                   ;; macro arglist is ok, though).
+                   (or
+                    (not (memq (char-before) '(?\) ?\])))
+                    ;; Have we moved back to a macro arglist?
+                    (and c-opt-cpp-prefix
+                         (eq (char-before) ?\))
+                         (save-excursion
+                           (and
+                            (c-go-list-backward)
+                            (let (pos)
+                              (c-backward-syntactic-ws)
+                              (and (setq pos (c-on-identifier))
+                                   (goto-char pos)))
+                            (zerop (c-backward-token-2 2))
+                            (looking-at c-opt-cpp-macro-define-start)))))
+
                    ;; Check that it isn't a nonsymbol identifier.
                    (not (c-on-identifier)))))))))
 
       ;; Handle the cast.
       (when (and c-record-type-identifiers
                 at-type
-                (not (memq at-type '(t maybe)))) ; 'maybe isn't strong enough
-                                       ; evidence to promote the type.
-       (let ((c-promote-possible-types t))
+                (not (eq at-type t)))
+       (let ((c-promote-possible-types (if (eq at-type 'maybe)
+                                           'just-one
+                                         t)))
          (goto-char type-start)
          (c-forward-type)))
 
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 5bb3e2e0b4..608919d0c9 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1585,7 +1585,7 @@ casts and declarations are fontified.  Used on level 2 
and higher."
                       nil)
                   (setq decl-or-cast
                         (c-forward-decl-or-cast-1
-                         match-pos context last-cast-end))
+                         match-pos context last-cast-end inside-macro))
 
                   ;; Ensure that c-<>-arg-sep c-type properties are in place 
on the
                   ;; commas separating the arguments inside template/generic 
<..>s.
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index fc3977967b..291af038b7 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -3489,76 +3489,179 @@ Note that Java specific rules are currently applied to 
tell this from
 (c-lang-defvar c-regular-keywords-regexp
   (c-lang-const c-regular-keywords-regexp))
 
-(c-lang-defconst c-primary-expr-regexp
-  ;; Regexp matching the start of any primary expression, i.e. any
-  ;; literal, symbol, prefix operator, and '('.  It doesn't need to
-  ;; exclude keywords; they are excluded afterwards unless the second
-  ;; submatch matches. If the first but not the second submatch
-  ;; matches then it is an ambiguous primary expression; it could also
-  ;; be a match of e.g. an infix operator. (The case with ambiguous
-  ;; keyword operators isn't handled.)
-
+(c-lang-defconst c-primary-expr-regexp-details
+  ;; A list of c-primary-expr-regexp and three numbers identifying particular
+  ;; matches in it.
   t (let* ((prefix-ops
+           ;All prefix ops
            (c-filter-ops (c-lang-const c-operators)
                          '(prefix)
                          (lambda (op)
                            ;; Filter out the special case prefix
                            ;; operators that are close parens.
                            (not (string-match "\\s)" op)))))
-
-          (nonkeyword-prefix-ops
-           (c-filter-ops prefix-ops
-                         t
-                         "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'"))
+          (postfix-ops
+           ;; All postfix ops.
+           (c-filter-ops (c-lang-const c-operators)
+                         '(postfix)
+                         (lambda (op) (not (string-match "\\s)" op)))))
 
           (in-or-postfix-ops
+           ;; All ops which are postfix, etc.
            (c-filter-ops (c-lang-const c-operators)
                          '(postfix
                            postfix-if-paren
                            left-assoc
                            right-assoc
                            right-assoc-sequence)
-                         t)))
+                         t))
 
-      (concat
-       "\\("
-       ;; Take out all symbol class operators from `prefix-ops' and make the
-       ;; first submatch from them together with `c-primary-expr-kwds'.
-       (c-make-keywords-re t
-        (append (c-lang-const c-primary-expr-kwds)
-                (c--set-difference prefix-ops nonkeyword-prefix-ops
-                                   :test 'string-equal)))
-
-       "\\|"
-       ;; Match all ambiguous operators.
-       (c-make-keywords-re nil
-        (c--intersection nonkeyword-prefix-ops in-or-postfix-ops
-                         :test 'string-equal))
-       "\\)"
-
-       "\\|"
-       ;; Now match all other symbols.
-       (c-lang-const c-symbol-start)
-
-       "\\|"
-       ;; The chars that can start integer and floating point
-       ;; constants.
-       "\\.?[0-9]"
-
-       "\\|"
-       ;; The unambiguous operators from `prefix-ops'.
-       (c-make-keywords-re nil
-        (c--set-difference nonkeyword-prefix-ops in-or-postfix-ops
-                           :test 'string-equal))
-
-       "\\|"
-       ;; Match string and character literals.
-       "\\s\""
-       (if (memq 'gen-string-delim c-emacs-features)
-          "\\|\\s|"
-        ""))))
+          (nonkeyword-prefix-ops
+           ;; All prefix ops apart from those which are keywords.
+           (c-filter-ops prefix-ops
+                         t
+                         "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'"))
+          (nonkeyword-postfix-ops
+           ;; All postfix ops apart from those which are keywords.
+           (c-filter-ops postfix-ops
+                         t
+                         "\\`\\(\\s.\\|\\s(\\|\\s)\\)+\\'"))
+
+          (cast-ops
+           ;; All prefix ops which have syntax open-paren.
+           (c-filter-ops prefix-ops
+                         t
+                         "\\`\\s(\\'"))
+
+          (ambiguous-pre/postfix-ops
+           ;; All non-keyword ops which are both prefix and postfix, apart
+           ;; from (.
+           (c--set-difference (c--intersection nonkeyword-prefix-ops
+                                               nonkeyword-postfix-ops
+                                               :test 'string-equal)
+                              cast-ops :test 'string-equal))
+          (unambiguous-prefix-ops
+           ;; All non-keyword ops which are prefix ops and not any other type
+           ;; of op.
+           (c--set-difference nonkeyword-prefix-ops
+                              in-or-postfix-ops
+                              :test 'string-equal))
+          (ambiguous-prefix-ops
+           ;; All non-keyword ops which are prefix ops and also some other
+           ;; type of op.
+           (c--intersection nonkeyword-prefix-ops
+                            in-or-postfix-ops
+                            :test 'string-equal)) ; This has everything we
+                                                  ; need, plus (, ++, --.
+
+          (ambiguous-prefix-non-postfix-ops
+           ;; All non-keyword prefix ops which are also other types of ops
+           ;; apart from postfix ops.
+           (c--set-difference (c--set-difference ambiguous-prefix-ops
+                                                 ambiguous-pre/postfix-ops
+                                                 :test 'string-equal)
+                              cast-ops :test 'string-equal))
+
+          (primary-expression-keywords-string
+           ;; Take out all symbol class operators from `prefix-ops' and make
+           ;; the first submatch from them together with
+           ;; `c-primary-expr-kwds'.
+           (c-make-keywords-re t
+             (append (c-lang-const c-primary-expr-kwds)
+                     (c--set-difference prefix-ops nonkeyword-prefix-ops
+                                        :test 'string-equal))))
+          (primary-expression-keywords-string-depth
+           (regexp-opt-depth primary-expression-keywords-string))
+
+          (ambiguous-pre/postfix-string
+           (c-make-keywords-re nil ambiguous-pre/postfix-ops))
+          (ambiguous-pre/postfix-string-depth
+           (regexp-opt-depth ambiguous-pre/postfix-string))
+
+          (ambiguous-prefix-non-postfix-string
+           (c-make-keywords-re nil ambiguous-prefix-non-postfix-ops))
+          (ambiguous-prefix-non-postfix-string-depth
+           (regexp-opt-depth ambiguous-prefix-non-postfix-string))
+
+          (per-++---match (+ 2 primary-expression-keywords-string-depth))
+          (per-&*+--match (+ 1 per-++---match
+                             ambiguous-pre/postfix-string-depth))
+          (per-\(-match (+ 1 per-&*+--match
+                           ambiguous-prefix-non-postfix-string-depth)))
+
+      (list
+       (concat
+       "\\("                           ; 1
+       primary-expression-keywords-string
+       "\\|"
+       ;; Match all ambiguous operators.
+       "\\("                   ; 2 + primary-expression-keywords-string-depth
+       ambiguous-pre/postfix-string
+       "\\)\\|\\("             ; 3 + primary-expression-keywords-string-depth
+                               ;   + ambiguous-pre/postfix-string-depth
+       ambiguous-prefix-non-postfix-string
+       "\\)\\|"
+       "\\((\\)"              ; 4 + primary-expression-keywords-string-depth
+                              ;   + ambiguous-pre/postfix-string-depth
+                              ;   + ambiguous-prefix-non-postfix-string-depth
+       "\\)"
+
+       "\\|"
+       ;; Now match all other symbols.
+       (c-lang-const c-symbol-start)
+
+       "\\|"
+       ;; The chars that can start integer and floating point
+       ;; constants.
+       "\\.?[0-9]"
+
+       "\\|"
+       ;; The unambiguous operators from `prefix-ops'.
+       (c-make-keywords-re nil
+         ;; (c--set-difference nonkeyword-prefix-ops in-or-postfix-ops
+         ;;                :test 'string-equal)
+         unambiguous-prefix-ops
+         )
+
+       "\\|"
+       ;; Match string and character literals.
+       "\\s\""
+       (if (memq 'gen-string-delim c-emacs-features)
+           "\\|\\s|"
+         ""))
+       per-++---match
+       per-&*+--match
+       per-\(-match)))
+
+(c-lang-defconst c-primary-expr-regexp
+  ;; Regexp matching the start of any primary expression, i.e. any
+  ;; literal, symbol, prefix operator, and '('.  It doesn't need to
+  ;; exclude keywords; they are excluded afterwards unless the second
+  ;; submatch matches. If the first but not the second submatch
+  ;; matches then it is an ambiguous primary expression; it could also
+  ;; be a match of e.g. an infix operator. (The case with ambiguous
+  ;; keyword operators isn't handled.)
+  t (car (c-lang-const c-primary-expr-regexp-details)))
 (c-lang-defvar c-primary-expr-regexp (c-lang-const c-primary-expr-regexp))
 
+(c-lang-defconst c-per-++---match
+  ;; Match number for group in `c-primary-expr-regexp' which matches (in C)
+  ;; the ++ and -- operators, and any similar ones in other languages.
+  t (cadr (c-lang-const c-primary-expr-regexp-details)))
+(c-lang-defvar c-per-++---match (c-lang-const c-per-++---match))
+
+(c-lang-defconst c-per-&*+--match
+  ;; Match number for group in `c-primary-expr-regexp' which matches (in C)
+  ;; the &, *, +, and - operators, and any similar ones in other languages.
+  t (car (cddr (c-lang-const c-primary-expr-regexp-details))))
+(c-lang-defvar c-per-&*+--match (c-lang-const c-per-&*+--match))
+
+(c-lang-defconst c-per-\(-match
+  ;; Match number for group in `c-primary-expr-regexp' which matches (in C)
+  ;; the ( operator, and any similar ones in other languages.
+  t (cadr (cddr (c-lang-const c-primary-expr-regexp-details))))
+(c-lang-defvar c-per-\(-match (c-lang-const c-per-\(-match))
+
 
 ;;; Additional constants for parser-level constructs.
 



reply via email to

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