;; 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
(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
;; 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
;; 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.
;; 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)))))
;; 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)))
(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))
+
\f
;;; Additional constants for parser-level constructs.