File emacs-cc-mode-master.patch of Package emacs
diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el
index 37e40d039cc..fbbb81b6f10 100644
--- a/lisp/progmodes/cc-align.el
+++ b/lisp/progmodes/cc-align.el
@@ -940,6 +940,16 @@ Works with: template-args-cont."
(zerop (c-forward-token-2 1 nil (c-point 'eol))))
(vector (current-column)))))
+(defun c-lineup-template-args-indented-from-margin (_langelem)
+ "Indent a template argument line `c-basic-offset' from the margin
+of the line with the containing <.
+
+Works with: template-args-cont."
+ (save-excursion
+ (goto-char (c-langelem-2nd-pos c-syntactic-element))
+ (back-to-indentation)
+ (vector (+ (current-column) c-basic-offset))))
+
(defun c-lineup-ObjC-method-call (langelem)
"Line up selector args as Emacs Lisp mode does with function args:
Go to the position right after the message receiver, and if you are at
diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el
index 9798f397491..e299f4fa8d2 100644
--- a/lisp/progmodes/cc-awk.el
+++ b/lisp/progmodes/cc-awk.el
@@ -754,14 +754,14 @@
(if (eq (char-after beg) ?_) (setq beg (1+ beg)))
;; First put the properties on the delimiters.
- (cond ((eq end (point-max)) ; string/regexp terminated by EOB
- (c-put-char-property beg 'syntax-table '(15))) ; (15) = "string fence"
- ((/= (char-after beg) (char-after end)) ; missing end delimiter
- (c-put-char-property beg 'syntax-table '(15))
- (c-put-char-property end 'syntax-table '(15)))
- ((eq (char-after beg) ?/) ; Properly bracketed regexp
- (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string"
- (c-put-char-property end 'syntax-table '(7)))
+ (cond ((eq end (point-max)) ; string/regexp terminated by EOB
+ (c-put-string-fence beg))
+ ((/= (char-after beg) (char-after end)) ; missing end delimiter
+ (c-put-string-fence beg)
+ (c-put-string-fence end))
+ ((eq (char-after beg) ?/) ; Properly bracketed regexp
+ (c-put-char-property beg 'syntax-table '(7)) ; (7) = "string"
+ (c-put-char-property end 'syntax-table '(7)))
(t)) ; Properly bracketed string: Nothing to do.
;; Now change the properties of any escaped "s in the string to punctuation.
(save-excursion
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 8dc0714dacf..7cd6cb0dda0 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -4909,7 +4909,8 @@ If a fill prefix is specified, it overrides all the above."
(setq c-lit-limits (c-literal-limits nil nil t)))
(unless c-lit-type
(setq c-lit-type (c-literal-type c-lit-limits)))
- (if (memq (cond ((c-query-and-set-macro-start) 'cpp)
+ (if (memq (cond ((memq c-lit-type '(c c++ string)) c-lit-type)
+ ((c-query-and-set-macro-start) 'cpp)
((null c-lit-type) 'code)
(t c-lit-type))
c-ignore-auto-fill)
@@ -5144,6 +5145,41 @@ details."
(goto-char here)
(delete-char 1))))
+
+
+;; Text conversion support.
+
+(defun c-post-text-conversion ()
+ "Notice that the character `last-command-event' has been inserted.
+If said character is an electric character such as `*' or `{', delete
+it, then call the appropriate CC Mode function to electrically insert
+it again."
+ (cond ((eq last-command-event ?#)
+ (delete-char -1)
+ (c-electric-pound nil) t)
+ ((memq last-command-event '(?{ ?}))
+ (delete-char -1)
+ (c-electric-brace nil) t)
+ ((memq last-command-event '(?\( ?\)))
+ (delete-char -1)
+ (c-electric-paren nil) t)
+ ((eq last-command-event ?*)
+ (delete-char -1)
+ (c-electric-star nil) t)
+ ((eq last-command-event ?/)
+ (delete-char -1)
+ (c-electric-slash nil) t)
+ ((memq last-command-event '(?\; ?,))
+ (delete-char -1)
+ (c-electric-semi&comma nil) t)
+ ((eq last-command-event ?:)
+ (delete-char -1)
+ (c-electric-colon nil) t)
+ ((memq last-command-event '(?> ?<))
+ (delete-char -1)
+ (c-electric-lt-gt nil) t)))
+
+
(cc-provide 'cc-cmds)
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 8fe3d653636..f84d95dbc94 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -425,11 +425,14 @@ to it is returned. This function does not modify the point or the mark."
(defvar lookup-syntax-properties) ;XEmacs.
(defmacro c-is-escaped (pos)
- ;; Are there an odd number of backslashes before POS?
+ ;; Is the character following POS escaped?
(declare (debug t))
`(save-excursion
(goto-char ,pos)
- (not (zerop (logand (skip-chars-backward "\\\\") 1)))))
+ (if (and c-escaped-newline-takes-precedence
+ (memq (char-after) '(?\n ?\r)))
+ (eq (char-before) ?\\)
+ (not (zerop (logand (skip-chars-backward "\\\\") 1))))))
(defmacro c-will-be-escaped (pos beg end)
;; Will the character after POS be escaped after the removal of (BEG END)?
@@ -437,13 +440,23 @@ to it is returned. This function does not modify the point or the mark."
(declare (debug t))
`(save-excursion
(let ((-end- ,end)
+ (-pos- ,pos)
count)
- (goto-char ,pos)
- (setq count (skip-chars-backward "\\\\" -end-))
- (when (eq (point) -end-)
- (goto-char ,beg)
- (setq count (+ count (skip-chars-backward "\\\\"))))
- (not (zerop (logand count 1))))))
+ (if (and c-escaped-newline-takes-precedence
+ (memq (char-after -pos-) '(?\n ?\r)))
+ (eq (char-before (if (eq -pos- -end-)
+ ,beg
+ -pos-))
+ ?\\)
+ (goto-char -pos-)
+ (setq count
+ (if (> -pos- -end-)
+ (skip-chars-backward "\\\\" -end-)
+ 0))
+ (when (eq (point) -end-)
+ (goto-char ,beg)
+ (setq count (+ count (skip-chars-backward "\\\\"))))
+ (not (zerop (logand count 1)))))))
(defmacro c-will-be-unescaped (beg)
;; Would the character after BEG be unescaped?
@@ -720,9 +733,10 @@ various buffer change hooks."
(defmacro c-forward-syntactic-ws (&optional limit)
"Forward skip over syntactic whitespace.
-Syntactic whitespace is defined as whitespace characters, comments,
-and preprocessor directives. However if point starts inside a comment
-or preprocessor directive, the content of it is not treated as
+Syntactic whitespace is defined as whitespace characters with
+whitespace (or comment-end) syntax, comments, and preprocessor
+directives. However if point starts inside a comment or
+preprocessor directive, the content of it is not treated as
whitespace.
LIMIT sets an upper limit of the forward movement, if specified. If
@@ -742,9 +756,10 @@ comment at the start of cc-engine.el for more info."
(defmacro c-backward-syntactic-ws (&optional limit)
"Backward skip over syntactic whitespace.
-Syntactic whitespace is defined as whitespace characters, comments,
-and preprocessor directives. However if point starts inside a comment
-or preprocessor directive, the content of it is not treated as
+Syntactic whitespace is defined as whitespace characters with
+whitespace (or comment-end) syntax, comments, and preprocessor
+directives. However if point starts inside a comment or
+preprocessor directive, the content of it is not treated as
whitespace.
LIMIT sets a lower limit of the backward movement, if specified. If
@@ -912,7 +927,8 @@ be after it."
(when dest (goto-char dest) t)))
(defmacro c-beginning-of-defun-1 ()
- ;; Wrapper around beginning-of-defun.
+ ;; Wrapper around beginning-of-defun. Note that the return value from this
+ ;; macro has no significance.
;;
;; NOTE: This function should contain the only explicit use of
;; beginning-of-defun in CC Mode. Eventually something better than
@@ -925,44 +941,49 @@ be after it."
;; `c-parse-state'.
`(progn
- (if (and ,(fboundp 'buffer-syntactic-context-depth)
- c-enable-xemacs-performance-kludge-p)
- ,(when (fboundp 'buffer-syntactic-context-depth)
- ;; XEmacs only. This can improve the performance of
- ;; c-parse-state to between 3 and 60 times faster when
- ;; braces are hung. It can also degrade performance by
- ;; about as much when braces are not hung.
- '(let (beginning-of-defun-function end-of-defun-function
- pos)
- (while (not pos)
- (save-restriction
- (widen)
- (setq pos (c-safe-scan-lists
- (point) -1 (buffer-syntactic-context-depth))))
- (cond
- ((bobp) (setq pos (point-min)))
- ((not pos)
- (let ((distance (skip-chars-backward "^{")))
- ;; unbalanced parenthesis, while invalid C code,
- ;; shouldn't cause an infloop! See unbal.c
- (when (zerop distance)
- ;; Punt!
- (beginning-of-defun)
- (setq pos (point)))))
- ((= pos 0))
- ((not (eq (char-after pos) ?{))
- (goto-char pos)
- (setq pos nil))
- ))
- (goto-char pos)))
- ;; Emacs, which doesn't have buffer-syntactic-context-depth
- (let (beginning-of-defun-function end-of-defun-function)
- (beginning-of-defun)))
- ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at the
- ;; open brace.
- (and defun-prompt-regexp
- (looking-at defun-prompt-regexp)
- (goto-char (match-end 0)))))
+ (while
+ (progn
+ (if (and ,(fboundp 'buffer-syntactic-context-depth)
+ c-enable-xemacs-performance-kludge-p)
+ ,(when (fboundp 'buffer-syntactic-context-depth)
+ ;; XEmacs only. This can improve the performance of
+ ;; c-parse-state to between 3 and 60 times faster when
+ ;; braces are hung. It can also degrade performance by
+ ;; about as much when braces are not hung.
+ '(let (beginning-of-defun-function end-of-defun-function
+ pos)
+ (while (not pos)
+ (save-restriction
+ (widen)
+ (setq pos (c-safe-scan-lists
+ (point) -1 (buffer-syntactic-context-depth))))
+ (cond
+ ((bobp) (setq pos (point-min)))
+ ((not pos)
+ (let ((distance (skip-chars-backward "^{")))
+ ;; unbalanced parenthesis, while invalid C code,
+ ;; shouldn't cause an infloop! See unbal.c
+ (when (zerop distance)
+ ;; Punt!
+ (beginning-of-defun)
+ (setq pos (point)))))
+ ((= pos 0))
+ ((not (eq (char-after pos) ?{))
+ (goto-char pos)
+ (setq pos nil))
+ ))
+ (goto-char pos)))
+ ;; Emacs, which doesn't have buffer-syntactic-context-depth
+ (let (beginning-of-defun-function end-of-defun-function)
+ (beginning-of-defun)))
+ (and (not (bobp))
+ ;; if defun-prompt-regexp is non-nil, b-o-d won't leave us at
+ ;; the open brace.
+ defun-prompt-regexp
+ (looking-at (concat defun-prompt-regexp "\\s("))
+ (or (not (eq (char-before (match-end 0)) ?{))
+ (progn (goto-char (1- (match-end 0)))
+ nil)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1089,6 +1110,38 @@ continuations."
(eq (char-before) ?\\)))
(backward-char))))
+(defmacro c-skip-ws-chars-forward (string &optional lim)
+ ;; Move point forward, stopping before a char which isn't in STRING, or a
+ ;; char whose syntax isn't whitespace or comment-end, or at pos LIM.
+ ;; Note that \n usually has comment-end syntax.
+ ;;
+ ;; Returns the distance traveled, either zero or positive.
+ (declare (debug t))
+ `(let ((-lim- ,lim)
+ (here (point))
+ count)
+ (setq count (skip-chars-forward ,string -lim-))
+ (when (> count 0)
+ (goto-char here)
+ (setq count (skip-syntax-forward " >" (+ here count))))
+ count))
+
+(defmacro c-skip-ws-chars-backward (string &optional lim)
+ ;; Move point backward, stopping after a char which isn't in STRING, or a
+ ;; char whose syntax isn't whitespace or comment-end, or at pos LIM. Note
+ ;; that \n usually has comment-end syntax.
+ ;;
+ ;; Returns the distance traveled, either zero or negative.
+ (declare (debug t))
+ `(let ((-lim- ,lim)
+ (here (point))
+ count)
+ (setq count (skip-chars-backward ,string -lim-))
+ (when (< count 0)
+ (goto-char here)
+ (setq count (skip-syntax-backward " >" (+ here count))))
+ count))
+
(eval-and-compile
(defvar c-langs-are-parametric nil))
@@ -1195,6 +1248,17 @@ MODE is either a mode symbol or a list of mode symbols."
`((setq c-syntax-table-hwm (min c-syntax-table-hwm -pos-))))
(put-text-property -pos- (1+ -pos-) ',property ,value))))
+(defmacro c-put-string-fence (pos)
+ ;; Put the string-fence syntax-table text property at POS.
+ ;; Since the character there cannot then count as syntactic whitespace,
+ ;; clear the properties `c-is-sws' and `c-in-sws' (see functions
+ ;; `c-forward-sws' and `c-backward-sws' in cc-engine.el for details).
+ (declare (debug t))
+ `(let ((-pos- ,pos))
+ (c-put-char-property -pos- 'syntax-table '(15))
+ (c-clear-char-property -pos- 'c-is-sws)
+ (c-clear-char-property -pos- 'c-in-sws)))
+
(eval-and-compile
;; Constant to decide at compilation time whether to use category
;; properties. Currently (2010-03) they're available only on GNU
@@ -1284,6 +1348,21 @@ MODE is either a mode symbol or a list of mode symbols."
pos)
(most-positive-fixnum))))
+(defmacro c-put-char-properties (from to property value)
+ ;; Put the given PROPERTY with the given VALUE on the characters between
+ ;; FROM and TO. PROPERTY is assumed to be constant. The return value is
+ ;; undefined.
+ ;;
+ ;; This macro does hidden buffer changes.
+ (declare (debug t))
+ (setq property (eval property))
+ `(let ((-from- ,from))
+ (progn
+ ,@(when (and (fboundp 'syntax-ppss)
+ (eq `,property 'syntax-table))
+ `((setq c-syntax-table-hwm (min c-syntax-table-hwm -from-))))
+ (put-text-property -from- ,to ',property ,value))))
+
(defmacro c-clear-char-properties (from to property)
;; Remove all the occurrences of the given property in the given
;; region that has been put with `c-put-char-property'. PROPERTY is
@@ -1379,7 +1458,8 @@ isn't found, return nil; point is then left undefined."
value)
(t (let ((place (c-next-single-property-change
(point) ,property nil -limit-)))
- (when place
+ (when (and place
+ (< place -limit-))
(goto-char (1+ place))
(c-get-char-property place ,property)))))))
@@ -1846,9 +1926,9 @@ with value CHAR in the region [FROM to)."
'(looking-at
"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")
'(or (looking-at
- "\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\)"
+ "\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\)")
(let ((prop (c-get-char-property (point) 'syntax-table)))
- (equal prop '(14))))))) ; '(14) is generic comment delimiter.
+ (equal prop '(14)))))) ; '(14) is generic comment delimiter.
(defsubst c-intersect-lists (list alist)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 8a954c4c14e..ea4ee3d7b7c 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -146,11 +146,6 @@
;; "typedef" keyword. It's value is a list of the identifiers that
;; the "typedef" declares as types.
;;
-;; 'c-<>-c-types-set
-;; This property is set on an opening angle bracket, and indicates that
-;; any "," separators within the template/generic expression have been
-;; marked with a 'c-type property value 'c-<>-arg-sep (see above).
-;;
;; 'c-awk-NL-prop
;; Used in AWK mode to mark the various kinds of newlines. See
;; cc-awk.el.
@@ -981,10 +976,10 @@ comment at the start of cc-engine.el for more info."
(point-min)))
(widen)
- (if (save-excursion
- (and (c-beginning-of-macro)
- (/= (point) start)))
- (setq macro-start (point)))
+ (save-excursion
+ (if (and (c-beginning-of-macro)
+ (/= (point) start))
+ (setq macro-start (point))))
;; Try to skip back over unary operator characters, to register
;; that we've moved.
@@ -1651,7 +1646,7 @@ This function does not do any hidden buffer changes."
;; comment, but XEmacs doesn't. We depend on the Emacs
;; behavior (which also is symmetric).
(if (and (eolp) (elt (parse-partial-sexp start (point)) 7))
- (condition-case nil (forward-char 1)))
+ (forward-char 1))
t))))
@@ -2135,7 +2130,7 @@ comment at the start of cc-engine.el for more info."
;; Skip simple ws and do a quick check on the following character to see
;; if it's anything that can't start syntactic ws, so we can bail out
;; early in the majority of cases when there just are a few ws chars.
- (skip-chars-forward " \t\n\r\f\v")
+ (c-skip-ws-chars-forward " \t\n\r\f\v")
(when (or (looking-at c-syntactic-ws-start)
(and c-opt-cpp-prefix
(looking-at c-noise-macro-name-re))
@@ -2185,7 +2180,7 @@ comment at the start of cc-engine.el for more info."
rung-pos (point) (point-max))
(setq rung-pos (point))
- (and (> (skip-chars-forward " \t\n\r\f\v") 0)
+ (and (> (c-skip-ws-chars-forward " \t\n\r\f\v") 0)
(not (eobp))))
;; We'll loop here if there is simple ws after the last rung.
@@ -2251,7 +2246,7 @@ comment at the start of cc-engine.el for more info."
(and c-opt-cpp-prefix
(looking-at c-opt-cpp-start)
(setq macro-start (point))
- (progn (skip-chars-backward " \t")
+ (progn (c-skip-ws-chars-backward " \t")
(bolp))
(or (bobp)
(progn (backward-char)
@@ -2291,7 +2286,7 @@ comment at the start of cc-engine.el for more info."
;; We've searched over a piece of non-white syntactic ws. See if this
;; can be cached.
(setq next-rung-pos (point))
- (skip-chars-forward " \t\n\r\f\v")
+ (c-skip-ws-chars-forward " \t\n\r\f\v")
(setq rung-end-pos (min (1+ (point)) (point-max)))
(if (or
@@ -2388,7 +2383,7 @@ comment at the start of cc-engine.el for more info."
;; bail out early in the majority of cases when there just are a few ws
;; chars. Newlines are complicated in the backward direction, so we can't
;; skip over them.
- (skip-chars-backward " \t\f")
+ (c-skip-ws-chars-backward " \t\f")
(when (and (not (bobp))
(save-excursion
(or (and
@@ -2416,7 +2411,7 @@ comment at the start of cc-engine.el for more info."
(setq simple-ws-beg (or attr-end ; After attribute.
(match-end 1) ; Noise macro, etc.
(match-end 0))) ; c-syntactic-ws-end
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(if (setq rung-is-marked (text-property-any
(point) (min (1+ rung-pos) (point-max))
'c-is-sws t))
@@ -2453,10 +2448,10 @@ comment at the start of cc-engine.el for more info."
(point) rung-pos (point-min))
(setq rung-pos (point))
- (if (and (< (min (skip-chars-backward " \t\f\v")
+ (if (and (< (min (c-skip-ws-chars-backward " \t\f\v")
(progn
(setq simple-ws-beg (point))
- (skip-chars-backward " \t\n\r\f\v")))
+ (c-skip-ws-chars-backward " \t\n\r\f\v")))
0)
(setq rung-is-marked
(text-property-any (point) rung-pos
@@ -2536,7 +2531,7 @@ comment at the start of cc-engine.el for more info."
;; the macro, and then `simple-ws-beg' must be kept on the
;; same side of those comments.
(goto-char simple-ws-beg)
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(if (eq (char-before) ?\\)
(forward-char))
(forward-line 1)
@@ -2549,7 +2544,7 @@ comment at the start of cc-engine.el for more info."
t)))
((/= (save-excursion
- (skip-chars-forward " \t\n\r\f\v" simple-ws-beg)
+ (c-skip-ws-chars-forward " \t\n\r\f\v" simple-ws-beg)
(setq next-rung-pos (point)))
simple-ws-beg)
;; Skipped over comments. Must put point at the end of
@@ -2586,7 +2581,7 @@ comment at the start of cc-engine.el for more info."
;; We've searched over a piece of non-white syntactic ws. See if this
;; can be cached.
(setq next-rung-pos (point))
- (skip-chars-backward " \t\f\v")
+ (c-skip-ws-chars-backward " \t\f\v")
(if (or
;; Cache if we started either from a marked rung or from a
@@ -2596,7 +2591,7 @@ comment at the start of cc-engine.el for more info."
;; Cache if there's a marked rung in the encountered simple ws.
(save-excursion
- (skip-chars-backward " \t\n\r\f\v")
+ (c-skip-ws-chars-backward " \t\n\r\f\v")
(text-property-any (point) (min (1+ next-rung-pos) (point-max))
'c-is-sws t)))
@@ -2677,6 +2672,7 @@ comment at the start of cc-engine.el for more info."
(progn (goto-char beg)
(c-skip-ws-forward end+1)
(eq (point) end+1))))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; We maintain a sopisticated cache of positions which are in a literal,
@@ -5915,19 +5911,21 @@ comment at the start of cc-engine.el for more info."
(cond
((> pos start) ; Nothing but literals
base)
- ((> base (point-min))
+ ((and
+ (> base (point-min))
+ (> (- base try-size) (point-min))) ; prevent infinite recursion.
(c-determine-limit how-far-back base (* 2 try-size) org-start))
(t base)))
((>= count how-far-back)
(c-determine-limit-no-macro
- (+ (car elt) (- count how-far-back))
- org-start))
+ (+ (car elt) (- count how-far-back))
+ org-start))
((eq base (point-min))
(point-min))
((> base (- start try-size)) ; Can only happen if we hit point-min.
(c-determine-limit-no-macro
- (car elt)
- org-start))
+ (car elt)
+ org-start))
(t
(c-determine-limit (- how-far-back count) base (* 2 try-size)
org-start))))))
@@ -6170,12 +6168,18 @@ comment at the start of cc-engine.el for more info."
(cons (point)
(cons bound-<> s)))))
+(defvar c-record-type-identifiers) ; Specially for `c-brace-stack-at'.
+
(defun c-brace-stack-at (here)
;; Given a buffer position HERE, Return the value of the brace stack there.
(save-excursion
(save-restriction
(widen)
- (let ((c c-bs-cache)
+ (let (c-record-type-identifiers ; In case `c-forward-<>-arglist' would
+ ; otherwise record identifiers outside
+ ; of the restriction in force before
+ ; this function.
+ (c c-bs-cache)
(can-use-prev (<= c-bs-prev-pos c-bs-cache-limit))
elt stack pos npos high-elt)
;; Trim the cache to take account of buffer changes.
@@ -6241,6 +6245,9 @@ comment at the start of cc-engine.el for more info."
;; prefix". The declaration prefix is the earlier of `cfd-prop-match' and
;; `cfd-re-match'. `cfd-match-pos' is set to the decl prefix.
;;
+ ;; The variables which this macro should set for `c-find-decl-spots' are
+ ;; `cfd-match-pos' and `cfd-continue-pos'.
+ ;;
;; This macro might do hidden buffer changes.
'(progn
@@ -6583,11 +6590,17 @@ comment at the start of cc-engine.el for more info."
;; and so we can continue the search from this point. If we
;; didn't hit `c-find-decl-syntactic-pos' then we're now in
;; the right spot to begin searching anyway.
- (if (and (eq (point) c-find-decl-syntactic-pos)
- c-find-decl-match-pos)
- (setq cfd-match-pos c-find-decl-match-pos
- cfd-continue-pos syntactic-pos)
-
+ (cond
+ ((and (eq (point) c-find-decl-syntactic-pos)
+ c-find-decl-match-pos)
+ (setq cfd-match-pos c-find-decl-match-pos
+ cfd-continue-pos syntactic-pos))
+ ((save-excursion (c-beginning-of-macro))
+ ;; The `c-backward-syntactic-ws' ~40 lines up failed to find non
+ ;; syntactic-ws and hit its limit, leaving us in a macro.
+ (setq cfd-match-pos cfd-start-pos
+ cfd-continue-pos cfd-start-pos))
+ (t
(setq c-find-decl-syntactic-pos syntactic-pos)
(when (if (bobp)
@@ -6605,7 +6618,7 @@ comment at the start of cc-engine.el for more info."
(c-find-decl-prefix-search)) ; sets cfd-continue-pos
(setq c-find-decl-match-pos (and (< cfd-match-pos cfd-start-pos)
- cfd-match-pos))))) ; end of `cond'
+ cfd-match-pos)))))) ; end of `cond'
;; Advance `cfd-continue-pos' if it's before the start position.
;; The closest continue position that might have effect at or
@@ -7027,8 +7040,8 @@ comment at the start of cc-engine.el for more info."
;; POS (default point) is at a < character. If it is both marked
;; with open/close paren syntax-table property, and has a matching >
;; (also marked) which is after LIM, remove the property both from
- ;; the current > and its partner. Return t when this happens, nil
- ;; when it doesn't.
+ ;; the current > and its partner. Return the position after the >
+ ;; when this happens, nil when it doesn't.
(save-excursion
(if pos
(goto-char pos)
@@ -7042,15 +7055,15 @@ comment at the start of cc-engine.el for more info."
c->-as-paren-syntax)) ; should always be true.
(c-unmark-<->-as-paren (1- (point)))
(c-unmark-<->-as-paren pos)
- (c-truncate-lit-pos-cache pos))
- t)))
+ (c-truncate-lit-pos-cache pos)
+ (point)))))
(defun c-clear->-pair-props-if-match-before (lim &optional pos)
;; POS (default point) is at a > character. If it is both marked
;; with open/close paren syntax-table property, and has a matching <
;; (also marked) which is before LIM, remove the property both from
- ;; the current < and its partner. Return t when this happens, nil
- ;; when it doesn't.
+ ;; the current < and its partner. Return the position of the < when
+ ;; this happens, nil when it doesn't.
(save-excursion
(if pos
(goto-char pos)
@@ -7064,8 +7077,8 @@ comment at the start of cc-engine.el for more info."
c-<-as-paren-syntax)) ; should always be true.
(c-unmark-<->-as-paren (point))
(c-truncate-lit-pos-cache (point))
- (c-unmark-<->-as-paren pos))
- t)))
+ (c-unmark-<->-as-paren pos)
+ (point)))))
;; Set by c-common-init in cc-mode.el.
(defvar c-new-BEG)
@@ -7073,7 +7086,48 @@ comment at the start of cc-engine.el for more info."
;; Set by c-before-change-check-raw-strings.
(defvar c-old-END-literality)
-(defun c-before-change-check-<>-operators (beg end)
+(defun c-end-of-literal (pt-s pt-search)
+ ;; If a literal is open in the `c-semi-pp-to-literal' state PT-S, return the
+ ;; end point of this literal (or point-max) assuming PT-S is valid at
+ ;; PT-SEARCH. Otherwise, return nil.
+ (when (car (cddr pt-s)) ; Literal start
+ (let ((lit-type (cadr pt-s))
+ (lit-beg (car (cddr pt-s)))
+ ml-end-re
+ )
+ (save-excursion
+ (cond
+ ((eq lit-type 'string)
+ (if (and c-ml-string-opener-re
+ (c-ml-string-opener-at-or-around-point lit-beg))
+ (progn
+ (setq ml-end-re
+ (funcall c-make-ml-string-closer-re-function
+ (match-string 1)))
+ (goto-char (max (- pt-search (1- (length ml-end-re)))
+ (point-min)))
+ (re-search-forward ml-end-re nil 'stay))
+ ;; For an ordinary string, we can't use `parse-partial-sexp' since
+ ;; not all syntax-table properties have yet been set.
+ (goto-char pt-search)
+ (re-search-forward
+ "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\"\n\\]\\)*[\"\n]" nil 'stay)))
+ ((memq lit-type '(c c++))
+ ;; To work around a bug in parse-partial-sexp, where effect is given
+ ;; to the syntax of a backslash, even the the scan starts with point
+ ;; just after it.
+ (if (and (eq (char-before pt-search) ?\\)
+ (eq (char-after pt-search) ?\n))
+ (progn
+ (c-put-char-property (1- pt-search) 'syntax-table '(1))
+ (parse-partial-sexp pt-search (point-max) nil nil (car pt-s)
+ 'syntax-table)
+ (c-clear-char-property (1- pt-search) 'syntax-table))
+ (parse-partial-sexp pt-search (point-max) nil nil (car pt-s)
+ 'syntax-table))))
+ (point)))))
+
+(defun c-unmark-<>-around-region (beg end &optional old-len)
;; Unmark certain pairs of "< .... >" which are currently marked as
;; template/generic delimiters. (This marking is via syntax-table text
;; properties), and expand the (c-new-BEG c-new-END) region to include all
@@ -7087,66 +7141,196 @@ comment at the start of cc-engine.el for more info."
;; enclose a brace or semicolon, so we use these as bounds on the
;; region we must work on.
;;
+ ;; The buffer is widened, and point is undefined, both at entry and exit.
+ ;;
+ ;; FIXME!!! This routine ignores the possibility of macros entirely.
+ ;; 2010-01-29.
+
+ (when (> end beg)
+ ;; Extend the region (BEG END) to deal with any complicating literals.
+ (let* ((lit-search-beg (if (memq (char-before beg) '(?/ ?*))
+ (1- beg) beg))
+ (lit-search-end (if (memq (char-after end) '(?/ ?*))
+ (1+ end) end))
+ ;; Note we can't use c-full-pp-to-literal here, since we haven't
+ ;; yet applied syntax-table properties to ends of lines, etc.
+ (lit-search-beg-s (c-semi-pp-to-literal lit-search-beg))
+ (beg-literal-beg (car (cddr lit-search-beg-s)))
+ (lit-search-end-s (c-semi-pp-to-literal lit-search-end))
+ (end-literal-beg (car (cddr lit-search-end-s)))
+ (beg-literal-end (c-end-of-literal lit-search-beg-s lit-search-beg))
+ (end-literal-end (c-end-of-literal lit-search-end-s lit-search-end))
+ new-beg new-end search-region)
+
+ ;; Determine any new end of literal resulting from the insertion/deletion.
+ (setq search-region
+ (if (and (eq beg-literal-beg end-literal-beg)
+ (eq beg-literal-end end-literal-end))
+ (if beg-literal-beg
+ nil
+ (cons beg
+ (max end
+ (or beg-literal-end (point-min))
+ (or end-literal-end (point-min)))))
+ (cons (or beg-literal-beg beg)
+ (max end
+ (or beg-literal-end (point-min))
+ (or end-literal-end (point-min))))))
+
+ (when search-region
+ ;; If we've just inserted text, mask its syntaxes temporarily so that
+ ;; they won't interfere with the undoing of the properties on the <s
+ ;; and >s.
+ (c-save-buffer-state (syn-tab-settings syn-tab-value
+ swap-open-string-ends)
+ (unwind-protect
+ (progn
+ (when old-len
+ ;; Special case: If a \ has just been inserted into a
+ ;; string, escaping or unescaping a LF, temporarily swap
+ ;; the LF's syntax-table text property with that of the
+ ;; former end of the open string.
+ (goto-char end)
+ (when (and (eq (cadr lit-search-beg-s) 'string)
+ (not (eq beg-literal-end end-literal-end))
+ (skip-chars-forward "\\\\")
+ (eq (char-after) ?\n)
+ (not (zerop (skip-chars-backward "\\\\"))))
+ (setq swap-open-string-ends t)
+ (if (c-get-char-property (1- beg-literal-end)
+ 'syntax-table)
+ (progn
+ (c-clear-char-property (1- beg-literal-end)
+ 'syntax-table)
+ (c-put-string-fence (1- end-literal-end)))
+ (c-put-string-fence (1- beg-literal-end))
+ (c-clear-char-property (1- end-literal-end)
+ 'syntax-table)))
+
+ ;; Save current settings of the 'syntax-table property in
+ ;; (BEG END), then splat these with the punctuation value.
+ (goto-char beg)
+ (while (setq syn-tab-value
+ (c-search-forward-non-nil-char-property
+ 'syntax-table end))
+ (when (not (c-get-char-property (1- (point)) 'category))
+ (push (cons (1- (point)) syn-tab-value)
+ syn-tab-settings)))
+
+ (c-put-char-properties beg end 'syntax-table '(1))
+ ;; If an open string's opener has just been neutralized,
+ ;; do the same to the terminating LF.
+ (when (and end-literal-end
+ (eq (char-before end-literal-end) ?\n)
+ (equal (c-get-char-property
+ (1- end-literal-end) 'syntax-table)
+ '(15)))
+ (push (cons (1- end-literal-end) '(15)) syn-tab-settings)
+ (c-put-char-property (1- end-literal-end) 'syntax-table
+ '(1))))
+
+ (let
+ ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
+ beg-limit end-limit <>-pos)
+ ;; Locate the earliest < after the barrier before the
+ ;; changed region, which isn't already marked as a paren.
+ (goto-char (or beg-lit-start beg))
+ (setq beg-limit (c-determine-limit 5000))
+
+ ;; Remove the syntax-table/category properties from each pertinent <...>
+ ;; pair. Firstly, the ones with the < before beg and > after beg....
+ (goto-char (cdr search-region))
+ (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
+ (eq (char-before) ?<))
+ (c-backward-token-2)
+ (when (eq (char-after) ?<)
+ (when (setq <>-pos (c-clear-<-pair-props-if-match-after
+ (car search-region)))
+ (setq new-end <>-pos))
+ (setq new-beg (point))))
+
+ ;; ...Then the ones with < before end and > after end.
+ (goto-char (car search-region))
+ (setq end-limit (c-determine-+ve-limit 5000))
+ (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 'end)
+ (eq (char-before) ?>))
+ (when (eq (char-before) ?>)
+ (if (and (looking-at c->-op-cont-regexp)
+ (not (eq (char-after) ?>)))
+ (goto-char (match-end 0))
+ (when
+ (and (setq <>-pos
+ (c-clear->-pair-props-if-match-before
+ (cdr search-region)
+ (1- (point))))
+ (or (not new-beg)
+ (< <>-pos new-beg)))
+ (setq new-beg <>-pos))
+ (when (or (not new-end) (> (point) new-end))
+ (setq new-end (point))))))))
+
+ (when old-len
+ (c-clear-char-properties beg end 'syntax-table)
+ (dolist (elt syn-tab-settings)
+ (if (cdr elt)
+ (c-put-char-property (car elt) 'syntax-table (cdr elt)))))
+ ;; Swap the '(15) syntax-table property on open string LFs back
+ ;; again.
+ (when swap-open-string-ends
+ (if (c-get-char-property (1- beg-literal-end)
+ 'syntax-table)
+ (progn
+ (c-clear-char-property (1- beg-literal-end)
+ 'syntax-table)
+ (c-put-string-fence (1- end-literal-end)))
+ (c-put-string-fence (1- beg-literal-end))
+ (c-clear-char-property (1- end-literal-end)
+ 'syntax-table)))))
+ ;; Extend the fontification region, if needed.
+ (and new-beg
+ (< new-beg c-new-BEG)
+ (setq c-new-BEG new-beg))
+ (and new-end
+ (> new-end c-new-END)
+ (setq c-new-END new-end))))))
+
+(defun c-before-change-check-<>-operators (beg end)
+ ;; When we're deleting text, unmark certain pairs of "< .... >" which are
+ ;; currently marked as template/generic delimiters. (This marking is via
+ ;; syntax-table text properties), and expand the (c-new-BEG c-new-END)
+ ;; region to include all unmarked < and > operators within the certain
+ ;; bounds (see below).
+ ;;
+ ;; These pairs are those which are in the current "statement" (i.e.,
+ ;; the region between the {, }, or ; before BEG and the one after
+ ;; END), and which enclose any part of the interval (BEG END).
+ ;; Also unmark a < or > which is about to become part of a multi-character
+ ;; operator, e.g. <=.
+ ;;
+ ;; Note that in C++ (?and Java), template/generic parens cannot
+ ;; enclose a brace or semicolon, so we use these as bounds on the
+ ;; region we must work on.
+ ;;
;; This function is called from before-change-functions (via
;; c-get-state-before-change-functions). Thus the buffer is widened,
;; and point is undefined, both at entry and exit.
;;
;; FIXME!!! This routine ignores the possibility of macros entirely.
;; 2010-01-29.
- (when (and (or (> end beg)
- (and (> c-<-pseudo-digraph-cont-len 0)
- (goto-char beg)
- (progn
- (skip-chars-backward
- "^<" (max (- (point) c-<-pseudo-digraph-cont-len)
- (point-min)))
- (eq (char-before) ?<))
- (looking-at c-<-pseudo-digraph-cont-regexp)))
- (or
- (progn
- (goto-char beg)
- (search-backward "<" (max (- (point) 1024) (point-min)) t))
- (progn
- (goto-char end)
- (search-forward ">" (min (+ (point) 1024) (point-max)) t))))
- (save-excursion
- (c-save-buffer-state
- ((beg-lit-start (progn (goto-char beg) (c-literal-start)))
- (end-lit-limits (progn (goto-char end) (c-literal-limits)))
- new-beg new-end beg-limit end-limit)
- ;; Locate the earliest < after the barrier before the changed region,
- ;; which isn't already marked as a paren.
- (goto-char (or beg-lit-start beg))
- (setq beg-limit (c-determine-limit 512))
-
- ;; Remove the syntax-table/category properties from each pertinent <...>
- ;; pair. Firstly, the ones with the < before beg and > after beg....
- (while (progn (c-syntactic-skip-backward "^;{}<" beg-limit)
- (eq (char-before) ?<))
- (c-backward-token-2)
- (when (eq (char-after) ?<)
- (c-clear-<-pair-props-if-match-after beg)
- (setq new-beg (point))))
- (c-forward-syntactic-ws)
-
- ;; ...Then the ones with < before end and > after end.
- (goto-char (if end-lit-limits (cdr end-lit-limits) end))
- (setq end-limit (c-determine-+ve-limit 512))
- (while (and (c-syntactic-re-search-forward "[;{}>]" end-limit 'end)
- (eq (char-before) ?>))
- (c-end-of-current-token)
- (when (eq (char-before) ?>)
- (c-clear->-pair-props-if-match-before end (1- (point)))
- (setq new-end (point))))
- (c-backward-syntactic-ws)
-
- ;; Extend the fontification region, if needed.
- (and new-beg
- (< new-beg c-new-BEG)
- (setq c-new-BEG new-beg))
- (and new-end
- (> new-end c-new-END)
- (setq c-new-END new-end))))))
+ (when (> end beg)
+ ;; Cope with removing (beg end) coalescing a < or > with, say, an = sign.
+ (goto-char beg)
+ (let ((ch (char-before)))
+ (if (and (memq ch '(?< ?>))
+ (c-get-char-property (1- (point)) 'syntax-table)
+ (progn
+ (goto-char end)
+ (looking-at (if (eq ch ?<)
+ c-<-op-cont-regexp
+ c->-op-cont-regexp)))
+ (or (eq ch ?<)
+ (not (eq (char-after) ?>))))
+ (c-unmark-<>-around-region (1- beg) beg)))))
(defun c-after-change-check-<>-operators (beg end)
;; This is called from `after-change-functions' when
@@ -7186,29 +7370,38 @@ comment at the start of cc-engine.el for more info."
(c-clear-<>-pair-props)
(forward-char)))))))
+(defun c-<>-get-restricted ()
+ ;; With point at the < at the start of the purported <>-arglist, determine
+ ;; the value of `c-restricted-<>-arglists' to use for the call of
+ ;; `c-forward-<>-arglist' starting there.
+ (save-excursion
+ (c-backward-token-2)
+ (and (not (looking-at c-opt-<>-sexp-key))
+ (progn (c-backward-syntactic-ws) ; to ( or ,
+ (and (memq (char-before) '(?\( ?,)) ; what about <?
+ (not (eq (c-get-char-property (point) 'c-type)
+ 'c-decl-arg-start)))))))
+
(defun c-restore-<>-properties (_beg _end _old-len)
;; This function is called as an after-change function. It restores the
;; category/syntax-table properties on template/generic <..> pairs between
;; c-new-BEG and c-new-END. It may do hidden buffer changes.
- (c-save-buffer-state ((c-parse-and-markup-<>-arglists t)
- c-restricted-<>-arglists lit-limits)
+ (c-save-buffer-state ((c-parse-and-markup-<>-arglists t) lit-limits)
(goto-char c-new-BEG)
(if (setq lit-limits (c-literal-limits))
(goto-char (cdr lit-limits)))
(while (and (< (point) c-new-END)
- (c-syntactic-re-search-forward "<" c-new-END 'bound))
- (backward-char)
- (save-excursion
- (c-backward-token-2)
- (setq c-restricted-<>-arglists
- (and (not (looking-at c-opt-<>-sexp-key))
- (progn (c-backward-syntactic-ws) ; to ( or ,
- (and (memq (char-before) '(?\( ?,)) ; what about <?
- (not (eq (c-get-char-property (point) 'c-type)
- 'c-decl-arg-start)))))))
- (or (c-forward-<>-arglist nil)
- (c-forward-over-token-and-ws)
- (goto-char c-new-END)))))
+ (c-syntactic-re-search-forward "[<>]" c-new-END 'bound))
+ (if (eq (char-before) ?<)
+ (progn
+ (backward-char)
+ (let ((c-restricted-<>-arglists (c-<>-get-restricted)))
+ (or (c-forward-<>-arglist nil)
+ (c-forward-over-token-and-ws)
+ (goto-char c-new-END))))
+ (save-excursion
+ (when (c-backward-<>-arglist nil nil #'c-<>-get-restricted)
+ (setq c-new-BEG (min c-new-BEG (point)))))))))
;; Handling of CC Mode multi-line strings.
@@ -7360,13 +7553,13 @@ multi-line strings (but not C++, for example)."
(defun c-ml-string-opener-intersects-region (&optional start finish)
;; If any part of the region [START FINISH] is inside an ml-string opener,
- ;; return a dotted list of the start, end and double-quote position of that
- ;; opener. That list will not include any "context characters" before or
- ;; after the opener. If an opener is found, the match-data will indicate
- ;; it, with (match-string 1) being the entire delimiter, and (match-string
- ;; 2) the "main" double-quote. Otherwise, the match-data is undefined.
- ;; Both START and FINISH default to point. FINISH may not be at an earlier
- ;; buffer position than START.
+ ;; return a dotted list of the start, end and double-quote position of the
+ ;; first such opener. That list will not include any "context characters"
+ ;; before or after the opener. If an opener is found, the match-data will
+ ;; indicate it, with (match-string 1) being the entire delimiter, and
+ ;; (match-string 2) the "main" double-quote. Otherwise, the match-data is
+ ;; undefined. Both START and FINISH default to point. FINISH may not be at
+ ;; an earlier buffer position than START.
(let ((here (point)) found)
(or finish (setq finish (point)))
(or start (setq start (point)))
@@ -7390,7 +7583,10 @@ multi-line strings (but not C++, for example)."
;; If POSITION (default point) is at or inside an ml string opener, return a
;; dotted list of the start and end of that opener, and the position of the
;; double-quote in it. That list will not include any "context characters"
- ;; before or after the opener.
+ ;; before or after the opener. If an opener is found, the match-data will
+ ;; indicate it, with (match-string 1) being the entire delimiter, and
+ ;; (match-string 2) the "main" double-quote. Otherwise, the match-data is
+ ;; undefined.
(let ((here (point))
found)
(or position (setq position (point)))
@@ -7402,7 +7598,7 @@ multi-line strings (but not C++, for example)."
c-ml-string-opener-re
(min (+ position c-ml-string-max-opener-len) (point-max))
'bound))
- (<= (match-end 1) position)))
+ (< (match-end 1) position)))
(prog1
(and found
(<= (match-beginning 1) position)
@@ -7746,7 +7942,7 @@ multi-line strings (but not C++, for example)."
(insert (nth 3 (car state))))
((eq (nth 3 (car state)) t)
(insert ?\")
- (c-put-char-property end 'syntax-table '(15))))
+ (c-put-string-fence end)))
(c-truncate-lit-pos-cache end)
;; ....ensure c-new-END extends right to the end of the about
;; to be un-stringed raw string....
@@ -7991,7 +8187,7 @@ multi-line strings (but not C++, for example)."
(goto-char (cadr end-delim))
t)
(c-put-char-property (cddr delim) 'syntax-table '(1))
- (c-put-char-property (1- (cadr delim)) 'syntax-table '(15))
+ (c-put-string-fence (1- (cadr delim)))
(c-truncate-lit-pos-cache (1- (cddr delim)))
(when bound
;; In a CPP construct, we try to apply a generic-string
@@ -8021,10 +8217,10 @@ multi-line strings (but not C++, for example)."
(cadr delim) t))
(if (match-beginning 10)
(progn
- (c-put-char-property (match-beginning 10) 'syntax-table '(15))
+ (c-put-string-fence (match-beginning 10))
(c-truncate-lit-pos-cache (match-beginning 10)))
(c-put-char-property (match-beginning 5) 'syntax-table '(1))
- (c-put-char-property (1+ (match-beginning 5)) 'syntax-table '(15))
+ (c-put-string-fence (1+ (match-beginning 5)))
(c-truncate-lit-pos-cache (match-beginning 5))))
(goto-char bound))
nil))
@@ -8288,10 +8484,17 @@ multi-line strings (but not C++, for example)."
(setq c-record-ref-identifiers
(cons range c-record-ref-identifiers))))))
-(defmacro c-forward-keyword-prefixed-id (type)
+(defmacro c-forward-keyword-prefixed-id (type &optional stop-at-end)
;; Used internally in `c-forward-keyword-clause' to move forward
;; over a type (if TYPE is 'type) or a name (otherwise) which
;; possibly is prefixed by keywords and their associated clauses.
+ ;; Point should be at the type/name or a preceding keyword at the start of
+ ;; the macro, and it is left at the first token following the type/name,
+ ;; or (when STOP-AT-END is non-nil) immediately after that type/name.
+ ;;
+ ;; Note that both parameters are evaluated at compile time, not run time,
+ ;; so they must be constants.
+ ;;
;; Try with a type/name first to not trip up on those that begin
;; with a keyword. Return t if a known or found type is moved
;; over. The point is clobbered if nil is returned. If range
@@ -8300,51 +8503,84 @@ multi-line strings (but not C++, for example)."
;;
;; This macro might do hidden buffer changes.
(declare (debug t))
- `(let (res)
+ `(let (res pos)
(setq c-last-identifier-range nil)
(while (if (setq res ,(if (eq type 'type)
- '(c-forward-type)
- '(c-forward-name)))
- nil
- (cond ((looking-at c-keywords-regexp)
- (c-forward-keyword-clause 1))
- ((and c-opt-cpp-prefix
- (looking-at c-noise-macro-with-parens-name-re))
- (c-forward-noise-clause)))))
+ `(c-forward-type nil ,stop-at-end)
+ `(c-forward-name ,stop-at-end)))
+ (progn
+ (setq pos (point))
+ nil)
+ (and
+ (cond ((looking-at c-keywords-regexp)
+ (c-forward-keyword-clause 1 t))
+ ((and c-opt-cpp-prefix
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause t)))
+ (progn
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ t))))
(when (memq res '(t known found prefix maybe))
(when c-record-type-identifiers
- ,(if (eq type 'type)
- '(c-record-type-id c-last-identifier-range)
- '(c-record-ref-id c-last-identifier-range)))
+ ,(if (eq type 'type)
+ '(c-record-type-id c-last-identifier-range)
+ '(c-record-ref-id c-last-identifier-range)))
+ (when pos
+ (goto-char pos)
+ ,(unless stop-at-end
+ `(c-forward-syntactic-ws)))
t)))
-(defmacro c-forward-id-comma-list (type update-safe-pos)
+(defmacro c-forward-id-comma-list (type update-safe-pos &optional stop-at-end)
;; Used internally in `c-forward-keyword-clause' to move forward
;; over a comma separated list of types or names using
- ;; `c-forward-keyword-prefixed-id'.
+ ;; `c-forward-keyword-prefixed-id'. Point should start at the first token
+ ;; after the already scanned type/name, or (if STOP-AT-END is non-nil)
+ ;; immediately after that type/name. Point is left either before or
+ ;; after the whitespace following the last type/name in the list, depending
+ ;; on whether STOP-AT-END is non-nil or nil. The return value is without
+ ;; significance.
+ ;;
+ ;; Note that all three parameters are evaluated at compile time, not run
+ ;; time, so they must be constants.
;;
;; This macro might do hidden buffer changes.
(declare (debug t))
- `(while (and (progn
- ,(when update-safe-pos
- '(setq safe-pos (point)))
- (eq (char-after) ?,))
- (progn
- (forward-char)
- (c-forward-syntactic-ws)
- (c-forward-keyword-prefixed-id ,type)))))
+ `(let ((pos (point)))
+ (while (and (progn
+ ,(when update-safe-pos
+ `(setq safe-pos (point)))
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (eq (char-after) ?,))
+ (progn
+ (forward-char)
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-keyword-prefixed-id ,type t))))
+ (goto-char pos)
+ ,(unless stop-at-end
+ `(c-forward-syntactic-ws))))
-(defun c-forward-noise-clause ()
+(defun c-forward-noise-clause (&optional stop-at-end)
;; Point is at a c-noise-macro-with-parens-names macro identifier. Go
;; forward over this name, any parenthesis expression which follows it, and
- ;; any syntactic WS, ending up at the next token or EOB. If there is an
+ ;; any syntactic WS, ending up either at the next token or EOB or (when
+ ;; STOP-AT-END is non-nil) directly after the clause. If there is an
;; unbalanced paren expression, leave point at it. Always Return t.
- (or (zerop (c-forward-token-2))
- (goto-char (point-max)))
- (if (and (eq (char-after) ?\()
- (c-go-list-forward))
+ (let (pos)
+ (or (c-forward-over-token)
+ (goto-char (point-max)))
+ (setq pos (point))
+ (c-forward-syntactic-ws)
+ (when (and (eq (char-after) ?\()
+ (c-go-list-forward))
+ (setq pos (point)))
+ (goto-char pos)
+ (unless stop-at-end
(c-forward-syntactic-ws))
- t)
+ t))
(defun c-forward-noise-clause-not-macro-decl (maybe-parens)
;; Point is at a noise macro identifier, which, when MAYBE-PARENS is
@@ -8378,11 +8614,12 @@ multi-line strings (but not C++, for example)."
(goto-char here)
nil)))
-(defun c-forward-keyword-clause (match)
+(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 at the start of
- ;; the next token. t is returned in that case, otherwise the point
+ ;; 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',
@@ -8412,19 +8649,23 @@ multi-line strings (but not C++, for example)."
(when kwd-sym
(goto-char (match-end match))
- (c-forward-syntactic-ws)
(setq safe-pos (point))
+ (c-forward-syntactic-ws)
(cond
((and (c-keyword-member kwd-sym 'c-type-list-kwds)
- (c-forward-keyword-prefixed-id type))
+ (c-forward-keyword-prefixed-id type t))
;; There's a type directly after a keyword in `c-type-list-kwds'.
- (c-forward-id-comma-list type t))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list type t t))
((and (c-keyword-member kwd-sym 'c-ref-list-kwds)
- (c-forward-keyword-prefixed-id ref))
+ (c-forward-keyword-prefixed-id ref t))
;; There's a name directly after a keyword in `c-ref-list-kwds'.
- (c-forward-id-comma-list ref t))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list ref t t))
((and (c-keyword-member kwd-sym 'c-paren-any-kwds)
(eq (char-after) ?\())
@@ -8444,20 +8685,20 @@ multi-line strings (but not C++, for example)."
(goto-char (match-end 0)))))
(goto-char pos)
- (c-forward-syntactic-ws)
- (setq safe-pos (point))))
+ (setq safe-pos (point)))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-<>-sexp-kwds)
(eq (char-after) ?<)
(c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)))
- (c-forward-syntactic-ws)
- (setq safe-pos (point)))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds)
(not (looking-at c-symbol-start))
(c-safe (c-forward-sexp) t))
- (c-forward-syntactic-ws)
- (setq safe-pos (point)))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws))
((and (c-keyword-member kwd-sym 'c-protection-kwds)
(or (null c-post-protection-token)
@@ -8467,8 +8708,8 @@ multi-line strings (but not C++, for example)."
(not (c-end-of-current-token))))))
(if c-post-protection-token
(goto-char (match-end 0)))
- (c-forward-syntactic-ws)
- (setq safe-pos (point))))
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)))
(when (c-keyword-member kwd-sym 'c-colon-type-list-kwds)
(if (eq (char-after) ?:)
@@ -8477,8 +8718,10 @@ multi-line strings (but not C++, for example)."
(progn
(forward-char)
(c-forward-syntactic-ws)
- (when (c-forward-keyword-prefixed-id type)
- (c-forward-id-comma-list type t)))
+ (when (c-forward-keyword-prefixed-id type t)
+ (setq safe-pos (point))
+ (c-forward-syntactic-ws)
+ (c-forward-id-comma-list type t t)))
;; Not at the colon, so stop here. But the identifier
;; ranges in the type list later on should still be
;; recorded.
@@ -8488,15 +8731,18 @@ multi-line strings (but not C++, for example)."
;; this one, we move forward to the colon following the
;; clause matched above.
(goto-char safe-pos)
+ (c-forward-syntactic-ws)
(c-forward-over-colon-type-list))
(progn
(c-forward-syntactic-ws)
- (c-forward-keyword-prefixed-id type))
+ (c-forward-keyword-prefixed-id type t))
;; There's a type after the `c-colon-type-list-re' match
;; after a keyword in `c-colon-type-list-kwds'.
(c-forward-id-comma-list type nil))))
(goto-char safe-pos)
+ (unless stop-at-end
+ (c-forward-syntactic-ws))
t)))
;; cc-mode requires cc-fonts.
@@ -8578,11 +8824,9 @@ multi-line strings (but not C++, for example)."
;; List that collects the positions after the argument
;; separating ',' in the arglist.
arg-start-pos)
- ;; If the '<' has paren open syntax then we've marked it as an angle
- ;; bracket arglist before, so skip to the end.
- (if (and syntax-table-prop-on-<
- (or (not c-parse-and-markup-<>-arglists)
- (c-get-char-property (point) 'c-<>-c-types-set)))
+ (if (and (not c-parse-and-markup-<>-arglists)
+ syntax-table-prop-on-<)
+
(progn
(forward-char)
(if (and (c-go-up-list-forward)
@@ -8679,7 +8923,6 @@ multi-line strings (but not C++, for example)."
(c-unmark-<->-as-paren (point)))))
(c-mark-<-as-paren start)
(c-mark->-as-paren (1- (point)))
- (c-put-char-property start 'c-<>-c-types-set t)
(c-truncate-lit-pos-cache start))
(setq res t)
nil)) ; Exit the loop.
@@ -8762,7 +9005,7 @@ multi-line strings (but not C++, for example)."
(if res
(or c-record-found-types t)))))
-(defun c-backward-<>-arglist (all-types &optional limit)
+(defun c-backward-<>-arglist (all-types &optional limit restricted-function)
;; The point is assumed to be directly after a ">". Try to treat it
;; as the close paren of an angle bracket arglist and move back to
;; the corresponding "<". If successful, the point is left at
@@ -8771,7 +9014,12 @@ multi-line strings (but not C++, for example)."
;; `c-forward-<>-arglist'.
;;
;; If the optional LIMIT is given, it bounds the backward search.
- ;; It's then assumed to be at a syntactically relevant position.
+ ;; It's then assumed to be at a syntactically relevant position. If
+ ;; RESTRICTED-FUNCTION is non-nil, it should be a function taking no
+ ;; arguments, called with point at a < at the start of a purported
+ ;; <>-arglist, which will return the value of
+ ;; `c-restricted-<>-arglists' to be used in the `c-forward-<>-arglist'
+ ;; call starting at that <.
;;
;; This is a wrapper around `c-forward-<>-arglist'. See that
;; function for more details.
@@ -8807,7 +9055,11 @@ multi-line strings (but not C++, for example)."
t
(backward-char)
- (let ((beg-pos (point)))
+ (let ((beg-pos (point))
+ (c-restricted-<>-arglists
+ (if restricted-function
+ (funcall restricted-function)
+ c-restricted-<>-arglists)))
(if (c-forward-<>-arglist all-types)
(cond ((= (point) start)
;; Matched the arglist. Break the while.
@@ -8827,11 +9079,12 @@ multi-line strings (but not C++, for example)."
(/= (point) start))))
-(defun c-forward-name ()
- ;; Move forward over a complete name if at the beginning of one,
- ;; stopping at the next following token. A keyword, as such,
- ;; doesn't count as a name. If the point is not at something that
- ;; is recognized as a name then it stays put.
+(defun c-forward-name (&optional stop-at-end)
+ ;; Move forward over a complete name if at the beginning of one, stopping
+ ;; either at the next following token or (when STOP-AT-END is non-nil) at
+ ;; the end of the name. A keyword, as such, doesn't count as a name. If
+ ;; the point is not at something that is recognized as a name then it stays
+ ;; put.
;;
;; A name could be something as simple as "foo" in C or something as
;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> ::
@@ -8853,7 +9106,7 @@ multi-line strings (but not C++, for example)."
;;
;; This function might do hidden buffer changes.
- (let ((pos (point)) (start (point)) res id-start id-end
+ (let ((pos (point)) pos2 pos3 (start (point)) res id-start id-end
;; Turn off `c-promote-possible-types' here since we might
;; call `c-forward-<>-arglist' and we don't want it to promote
;; every suspect thing in the arglist to a type. We're
@@ -8895,7 +9148,7 @@ multi-line strings (but not C++, for example)."
(c-forward-syntactic-ws lim+)
(cond ((eq (char-before id-end) ?e)
;; Got "... ::template".
- (let ((subres (c-forward-name)))
+ (let ((subres (c-forward-name t)))
(when subres
(setq pos (point)
res subres))))
@@ -8907,7 +9160,7 @@ multi-line strings (but not C++, for example)."
(and (eq (c-forward-token-2) 0)
(not (eq (char-after) ?\())))))
;; Got a cast operator.
- (when (c-forward-type)
+ (when (c-forward-type nil t)
(setq pos (point)
res 'operator)
;; Now we should match a sequence of either
@@ -8931,8 +9184,8 @@ multi-line strings (but not C++, for example)."
(forward-char)
t)))))
(while (progn
- (c-forward-syntactic-ws lim+)
(setq pos (point))
+ (c-forward-syntactic-ws lim+)
(and
(<= (point) lim+)
(looking-at c-opt-type-modifier-key)))
@@ -8947,30 +9200,34 @@ multi-line strings (but not C++, for example)."
;; operator"" has an (?)optional tag after it.
(progn
(goto-char (match-end 0))
+ (setq pos2 (point))
(c-forward-syntactic-ws lim+)
(when (c-on-identifier)
- (c-forward-token-2 1 nil lim+)))
- (goto-char (match-end 0))
- (c-forward-syntactic-ws lim+))
- (setq pos (point)
+ (c-forward-over-token nil lim+)))
+ (goto-char (match-end 0))
+ (setq pos2 (point))
+ (c-forward-syntactic-ws lim+))
+ (setq pos pos2
res 'operator)))
nil)
;; `id-start' is equal to `id-end' if we've jumped over
;; an identifier that doesn't end with a symbol token.
- ;; That can occur e.g. for Java import directives on the
+ ;; That can occur e.g. for Java import directives of the
;; form "foo.bar.*".
(when (and id-start (/= id-start id-end))
(setq c-last-identifier-range
(cons id-start id-end)))
(goto-char id-end)
+ (setq pos (point))
(c-forward-syntactic-ws lim+)
- (setq pos (point)
- res t)))
+ (setq res t)))
(progn
(goto-char pos)
+ (c-forward-syntactic-ws lim+)
+ (setq pos3 (point))
(when (or c-opt-identifier-concat-key
c-recognize-<>-arglists)
@@ -8981,7 +9238,6 @@ multi-line strings (but not C++, for example)."
;; cases with tricky syntactic whitespace that aren't
;; covered in `c-identifier-key'.
(goto-char (match-end 0))
- (c-forward-syntactic-ws lim+)
t)
((and c-recognize-<>-arglists
@@ -8993,11 +9249,12 @@ multi-line strings (but not C++, for example)."
;; `lim+'.
(setq lim+ (c-determine-+ve-limit 500))
+ (setq pos2 (point))
(c-forward-syntactic-ws lim+)
(unless (eq (char-after) ?\()
(setq c-last-identifier-range nil)
- (c-add-type start (1+ pos)))
- (setq pos (point))
+ (c-add-type start (1+ pos3)))
+ (setq pos pos2)
(if (and c-opt-identifier-concat-key
(looking-at c-opt-identifier-concat-key))
@@ -9007,7 +9264,7 @@ multi-line strings (but not C++, for example)."
(progn
(when (and c-record-type-identifiers id-start)
(c-record-ref-id (cons id-start id-end)))
- (forward-char 2)
+ (goto-char (match-end 0))
(c-forward-syntactic-ws lim+)
t)
@@ -9019,11 +9276,14 @@ multi-line strings (but not C++, for example)."
)))))
(goto-char pos)
+ (unless stop-at-end
+ (c-forward-syntactic-ws lim+))
res))
-(defun c-forward-type (&optional brace-block-too)
+(defun c-forward-type (&optional brace-block-too stop-at-end)
;; Move forward over a type spec if at the beginning of one,
- ;; stopping at the next following token. The keyword "typedef"
+ ;; stopping at the next following token (if STOP-AT-END is nil) or
+ ;; at the end of the type spec (otherwise). The keyword "typedef"
;; isn't part of a type spec here.
;;
;; BRACE-BLOCK-TOO, when non-nil, means move over the brace block in
@@ -9062,7 +9322,7 @@ 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)
+ post-prefix-pos prefix-end-pos)
;; Skip leading type modifiers. If any are found we know it's a
;; prefix of a type.
@@ -9072,6 +9332,8 @@ multi-line strings (but not C++, for example)."
(when (looking-at c-no-type-key)
(setq res 'no-id)))
(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))))
@@ -9080,32 +9342,41 @@ multi-line strings (but not C++, for example)."
(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
- (c-forward-syntactic-ws)
+ (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)
(while (cond
((looking-at c-decl-hangon-key)
- (c-forward-keyword-clause 1))
+ (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))))
+ (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 name-res (c-forward-name))
(setq res (not (null name-res)))
(when (eq name-res t)
;; With some keywords the name can be used without the prefix, so we
@@ -9113,21 +9384,21 @@ multi-line strings (but not C++, for example)."
(when (save-excursion
(goto-char post-prefix-pos)
(looking-at c-self-contained-typename-key))
- (c-add-type pos (save-excursion
- (c-backward-syntactic-ws)
- (point))))
+ (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)
- (c-forward-syntactic-ws)
(setq pos (point))))))
(goto-char pos)
+ (c-forward-syntactic-ws)
(setq res t))
(unless res (goto-char start))) ; invalid syntax
@@ -9141,7 +9412,7 @@ multi-line strings (but not C++, for example)."
(if (looking-at c-identifier-start)
(save-excursion
(setq id-start (point)
- name-res (c-forward-name))
+ name-res (c-forward-name t))
(when name-res
(setq id-end (point)
id-range c-last-identifier-range))))
@@ -9154,8 +9425,9 @@ multi-line strings (but not C++, for example)."
(>= (save-excursion
(save-match-data
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
- (setq pos (point))))
+ pos))
id-end)
(setq res nil)))))
;; Looking at a primitive or known type identifier. We've
@@ -9168,62 +9440,86 @@ multi-line strings (but not C++, for example)."
(or c-promote-possible-types (eq res t)))
(c-record-type-id (cons (match-beginning 1) (match-end 1))))
- (if (and c-opt-type-component-key
+ (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)
- (while (progn
- (setq safe-pos (point))
- (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))
- (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)
- (setq res t))
- (goto-char safe-pos)
- (setq res 'prefix)))
- (unless (save-match-data (c-forward-keyword-clause 1))
- (if pos
- (goto-char pos)
- (goto-char (match-end 1))
- (c-forward-syntactic-ws)))))
+ (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))))
+ (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))
- (not (looking-at c-type-decl-prefix-key)))))
+ (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 id-start)
+ (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 (save-excursion
- (goto-char id-end)
- (c-backward-syntactic-ws)
- (point))))
+ (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)))
+ (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.
@@ -9233,6 +9529,7 @@ multi-line strings (but not C++, for example)."
((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) ?\()
@@ -9258,6 +9555,7 @@ multi-line strings (but not C++, for example)."
(when c-opt-type-modifier-key
(while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
(goto-char (match-end 1))
+ (setq pos (point))
(c-forward-syntactic-ws)
(setq res t)))
@@ -9268,11 +9566,13 @@ multi-line strings (but not C++, for example)."
(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))
@@ -9296,7 +9596,8 @@ multi-line strings (but not C++, for example)."
(progn
(goto-char (match-end 1))
(c-forward-syntactic-ws)
- (setq subres (c-forward-type))))
+ (setq subres (c-forward-type nil t))
+ (setq pos (point))))
(progn
;; If either operand certainly is a type then both are, but we
@@ -9332,9 +9633,11 @@ multi-line strings (but not C++, for example)."
;; `nconc' doesn't mind that the tail of
;; `c-record-found-types' is t.
(nconc c-record-found-types
- c-record-type-identifiers))))
+ c-record-type-identifiers)))))))
- (goto-char pos))))
+ (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
@@ -9373,19 +9676,24 @@ multi-line strings (but not C++, for example)."
(setq ,ps (cdr ,ps)))))
(defun c-forward-over-compound-identifier ()
- ;; Go over a possibly compound identifier, such as C++'s Foo::Bar::Baz,
- ;; returning that identifier (with any syntactic WS removed). Return nil if
- ;; we're not at an identifier.
- (when (c-on-identifier)
+ ;; Go over a possibly compound identifier (but not any following
+ ;; whitespace), such as C++'s Foo::Bar::Baz, returning that identifier (with
+ ;; any syntactic WS removed). Return nil if we're not at an identifier, in
+ ;; which case point is not moved.
+ (when
+ (eq (c-on-identifier)
+ (point))
(let ((consolidated "") (consolidated-:: "")
- start end)
+ (here (point))
+ start end end-token)
(while
(progn
(setq start (point))
(c-forward-over-token)
(setq consolidated
(concat consolidated-::
- (buffer-substring-no-properties start (point))))
+ (buffer-substring-no-properties start (point)))
+ end-token (point))
(c-forward-syntactic-ws)
(and c-opt-identifier-concat-key
(looking-at c-opt-identifier-concat-key)
@@ -9400,7 +9708,9 @@ multi-line strings (but not C++, for example)."
(concat consolidated
(buffer-substring-no-properties start end))))))))
(if (equal consolidated "")
- nil
+ (progn (goto-char here)
+ nil)
+ (goto-char end-token)
consolidated))))
(defun c-back-over-compound-identifier ()
@@ -9573,13 +9883,16 @@ point unchanged and return nil."
;; Handling of large scale constructs like statements and declarations.
-(defun c-forward-primary-expression (&optional limit)
- ;; Go over the primary expression (if any) at point, moving to the next
- ;; token and return non-nil. If we're not at a primary expression leave
- ;; point unchanged and return nil.
+(defun c-forward-primary-expression (&optional limit stop-at-end)
+ ;; Go over the primary expression (if any) at point, and unless STOP-AT-END
+ ;; is non-nil, move to the next token then return non-nil. If we're not at
+ ;; a primary expression leave point unchanged and return nil.
;;
;; Note that this function is incomplete, handling only those cases expected
;; to be common in a C++20 requires clause.
+ ;;
+ ;; Note also that (...) is not recognized as a primary expression if the
+ ;; next token is an open brace.
(let ((here (point))
(c-restricted-<>-arglists t)
(c-parse-and-markup-<>-arglists nil)
@@ -9587,28 +9900,38 @@ point unchanged and return nil."
(if (cond
((looking-at c-constant-key)
(goto-char (match-end 1))
- (c-forward-syntactic-ws limit)
+ (unless stop-at-end (c-forward-syntactic-ws limit))
t)
((eq (char-after) ?\()
(and (c-go-list-forward (point) limit)
(eq (char-before) ?\))
- (progn (c-forward-syntactic-ws limit)
- t)))
+ (let ((after-paren (point)))
+ (c-forward-syntactic-ws limit)
+ (prog1
+ (not (eq (char-after) ?{))
+ (when stop-at-end
+ (goto-char after-paren))))))
((c-forward-over-compound-identifier)
- (c-forward-syntactic-ws limit)
- (while (cond
- ((looking-at "<")
- (prog1
- (c-forward-<>-arglist nil)
- (c-forward-syntactic-ws limit)))
- ((looking-at c-opt-identifier-concat-key)
- (and
- (zerop (c-forward-token-2 1 nil limit))
- (prog1
- (c-forward-over-compound-identifier)
- (c-forward-syntactic-ws limit))))))
- t)
- ((looking-at c-fun-name-substitute-key) ; "requires"
+ (let ((after-id (point)))
+ (c-forward-syntactic-ws limit)
+ (while (cond
+ ((and
+ (looking-at "<")
+ (prog1
+ (and
+ (c-forward-<>-arglist nil)
+ (setq after-id (point)))))
+ (c-forward-syntactic-ws limit))
+ ((looking-at c-opt-identifier-concat-key)
+ (and
+ (zerop (c-forward-token-2 1 nil limit))
+ (prog1
+ (c-forward-over-compound-identifier)
+ (c-forward-syntactic-ws limit))))))
+ (goto-char after-id)))
+ ((and
+ (looking-at c-fun-name-substitute-key) ; "requires"
+ (not (eq (char-after (match-end 0)) ?_)))
(goto-char (match-end 1))
(c-forward-syntactic-ws limit)
(and
@@ -9621,36 +9944,47 @@ point unchanged and return nil."
(and (c-go-list-forward (point) limit)
(eq (char-before) ?}))
(progn
- (c-forward-syntactic-ws limit)
+ (unless stop-at-end (c-forward-syntactic-ws limit))
t))))
t
(goto-char here)
nil)))
-(defun c-forward-c++-requires-clause (&optional limit)
- ;; Point is at the keyword "requires". Move forward over the requires
- ;; clause to the next token after it and return non-nil. If there is no
- ;; valid requires clause at point, leave point unmoved and return nil.
+(defun c-forward-constraint-clause (&optional limit stop-at-end)
+ ;; Point is at the putative start of a constraint clause. Move to its end
+ ;; (when STOP-AT-END is non-zero) or the token after that (otherwise) and
+ ;; return non-nil. Return nil without moving if we fail to find a
+ ;; constraint.
(let ((here (point))
final-point)
(or limit (setq limit (point-max)))
- (if (and
- (zerop (c-forward-token-2 1 nil limit)) ; over "requires".
- (prog1
- (c-forward-primary-expression limit)
- (setq final-point (point))
- (while
- (and (looking-at "\\(?:&&\\|||\\)")
- (progn (goto-char (match-end 0))
- (c-forward-syntactic-ws limit)
- (and (< (point) limit)
- (c-forward-primary-expression limit))))
- (setq final-point (point)))))
- (progn (goto-char final-point)
- t)
+ (if (c-forward-primary-expression limit t)
+ (progn
+ (setq final-point (point))
+ (c-forward-syntactic-ws limit)
+ (while
+ (and (looking-at "\\(?:&&\\|||\\)")
+ (<= (match-end 0) limit)
+ (progn (goto-char (match-end 0))
+ (c-forward-syntactic-ws limit)
+ (and (<= (point) limit)))
+ (c-forward-primary-expression limit t)
+ (setq final-point (point))))
+ (goto-char final-point)
+ (or stop-at-end (c-forward-syntactic-ws limit))
+ t)
(goto-char here)
nil)))
+(defun c-forward-c++-requires-clause (&optional limit stop-at-end)
+ ;; Point is at the keyword "requires". Move forward over the requires
+ ;; clause to its end (if STOP-AT-END is non-nil) or the next token after it
+ ;; (otherwise) and return non-nil. If there is no valid requires clause at
+ ;; point, leave point unmoved and return nil.
+ (or limit (setq limit (point-max)))
+ (and (zerop (c-forward-token-2)) ; over "requires".
+ (c-forward-constraint-clause limit stop-at-end)))
+
(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,
@@ -9737,7 +10071,7 @@ point unchanged and return nil."
;; (e.g. "," or ";" or "}").
(let ((here (point))
id-start id-end brackets-after-id paren-depth decorated
- got-init arglist double-double-quote)
+ got-init arglist double-double-quote pos)
(or limit (setq limit (point-max)))
(if (and
(< (point) limit)
@@ -9771,6 +10105,7 @@ point unchanged and return nil."
(eq (char-after (1+ (point))) ?\"))
(setq double-double-quote t))
(goto-char (match-end 0))
+ (setq pos (point))
(c-forward-syntactic-ws limit)
(setq got-identifier t)
nil)
@@ -9783,7 +10118,10 @@ point unchanged and return nil."
;; prefix only if it specifies a member pointer.
(progn
(setq id-start (point))
- (when (c-forward-name)
+ (when (c-forward-name t)
+ (setq pos (point))
+ (c-forward-syntactic-ws limit)
+
(if (save-match-data
(looking-at "\\(::\\)"))
;; We only check for a trailing "::" and
@@ -9812,10 +10150,12 @@ point unchanged and return nil."
(setq id-start (point)))
(cond
((or got-identifier
- (c-forward-name))
- (save-excursion
- (c-backward-syntactic-ws)
- (setq id-end (point))))
+ (c-forward-name t))
+ (setq id-end
+ (or pos
+ (point)))
+ (c-forward-syntactic-ws limit)
+ t)
(accept-anon
(setq id-start nil id-end nil)
t)
@@ -9846,7 +10186,9 @@ point unchanged and return nil."
((looking-at c-type-decl-suffix-key)
(cond
((save-match-data
- (looking-at c-fun-name-substitute-key))
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
(c-forward-c++-requires-clause))
((eq (char-after) ?\()
(if (c-forward-decl-arglist not-top decorated limit)
@@ -9883,7 +10225,11 @@ point unchanged and return nil."
(prog1
(setq found
(c-syntactic-re-search-forward
- "[;:,]\\|\\(=\\|\\s(\\)"
+ ;; Consider making the next regexp a
+ ;; c-lang-defvar (2023-07-04).
+ (if (c-major-mode-is 'objc-mode)
+ "\\(?:@end\\)\\|[;:,]\\|\\(=\\|[[(]\\)"
+ "[;:,]\\|\\(=\\|\\s(\\)")
limit 'limit t))
(setq got-init
(and found (match-beginning 1))))
@@ -10060,6 +10406,24 @@ This function might do hidden buffer changes."
;; This identifier is bound only in the inner let.
'(setq start id-start))))
+(defmacro c-fdoc-assymetric-space-about-asterisk ()
+ ;; We've got a "*" at `id-start' between two identifiers, the first at
+ ;; `type-start'. Return non-nil when there is either whitespace between the
+ ;; first id and the "*" or between the "*" and the second id, but not both.
+ `(let ((space-before-id
+ (save-excursion
+ (goto-char id-start) ; Position of "*".
+ (and (> (skip-chars-forward "* \t\n\r") 0)
+ (memq (char-before) '(?\ ?\t ?\n ?\r)))))
+ (space-after-type
+ (save-excursion
+ (goto-char type-start)
+ (and (c-forward-type nil t)
+ (or (eolp)
+ (memq (char-after) '(?\ ?\t)))))))
+ (not (eq (not space-before-id)
+ (not space-after-type)))))
+
(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.
@@ -10282,7 +10646,9 @@ This function might do hidden buffer changes."
(when (and (c-major-mode-is 'c++-mode)
(c-keyword-member kwd-sym 'c-<>-sexp-kwds)
(save-match-data
- (looking-at c-fun-name-substitute-key)))
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))))
(c-forward-c++-requires-clause))
(setq kwd-clause-end (point))))
((and c-opt-cpp-prefix
@@ -10477,6 +10843,10 @@ This function might do hidden buffer changes."
got-parens
;; True if there is a terminated argument list.
got-arglist
+ ;; True when `got-arglist' and the token after the end of the
+ ;; arglist is an opening brace. Used only when we have a
+ ;; suspected typeless function name.
+ got-stmt-block
;; True if there is an identifier in the declarator.
got-identifier
;; True if we find a number where an identifier was expected.
@@ -10569,11 +10939,11 @@ This function might do hidden buffer changes."
(or got-identifier
(and (looking-at c-identifier-start)
(setq pos (point))
- (setq got-identifier (c-forward-name))
+ (setq got-identifier (c-forward-name t))
(save-excursion
- (c-backward-syntactic-ws)
(c-simple-skip-symbol-backward)
(setq identifier-start (point)))
+ (progn (c-forward-syntactic-ws) t)
(setq name-start pos))
(when (looking-at "[0-9]")
(setq got-number t)) ; We probably have an arithmetic expression.
@@ -10629,10 +10999,16 @@ This function might do hidden buffer changes."
(setq got-arglist t))
t)
(when (cond
+ ((and (eq (char-after) ?\()
+ (c-safe (c-forward-sexp 1) t))
+ (when (eq (char-before) ?\))
+ (setq got-arglist t)))
((save-match-data (looking-at "\\s("))
(c-safe (c-forward-sexp 1) t))
((save-match-data
- (looking-at c-fun-name-substitute-key)) ; C++ requires
+ (and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))) ; C++ requires
(c-forward-c++-requires-clause))
(t (goto-char (match-end 1))
t))
@@ -10641,6 +11017,11 @@ This function might do hidden buffer changes."
(setq got-suffix-after-parens (match-beginning 0)))
(setq got-suffix t))))
+ ((and got-arglist
+ (eq (char-after) ?{))
+ (setq got-stmt-block t)
+ nil)
+
(t
;; No suffix matched. We might have matched the
;; identifier as a type and the open paren of a
@@ -10709,9 +11090,17 @@ This function might do hidden buffer changes."
(not (memq context '(arglist decl))))
(or (and new-style-auto
(looking-at c-auto-ops-re))
- (and (or maybe-typeless backup-maybe-typeless)
- (not got-prefix)
- at-type)))
+ (and (not got-prefix)
+ at-type
+ (or maybe-typeless backup-maybe-typeless
+ ;; Do we have a (typeless) constructor?
+ (and got-stmt-block
+ (save-excursion
+ (goto-char type-start)
+ (and
+ (looking-at c-identifier-key)
+ (c-directly-in-class-called-p
+ (match-string 0)))))))))
;; Have found no identifier but `c-typeless-decl-kwds' has
;; matched so we know we're inside a declaration. The
;; preceding type must be the identifier instead.
@@ -10796,8 +11185,7 @@ This function might do hidden buffer changes."
type-start
(progn
(goto-char type-start)
- (c-forward-type)
- (c-backward-syntactic-ws)
+ (c-forward-type nil t)
(point)))))))))
;; Got a declaration of the form "foo bar (gnu);" or "bar
;; (gnu);" where we've recognized "bar" as the type and "gnu"
@@ -11081,19 +11469,25 @@ This function might do hidden buffer changes."
;; CASE 16
(when (and got-prefix-before-parens
at-type
- (or at-decl-end (looking-at "=[^=]"))
(memq context '(nil top))
(or (not got-suffix)
at-decl-start))
;; Got something like "foo * bar;". Since we're not inside
;; an arglist it would be a meaningless expression because
;; the result isn't used. We therefore choose to recognize
- ;; it as a declaration. We only allow a suffix (which makes
- ;; the construct look like a function call) when
- ;; `at-decl-start' provides additional evidence that we do
- ;; have a declaration.
+ ;; it as a declaration when there's "symmetrical WS" around
+ ;; the "*" or the flag `c-asymmetry-fontification-flag' is
+ ;; not set. We only allow a suffix (which makes the
+ ;; construct look like a function call) when `at-decl-start'
+ ;; provides additional evidence that we do have a
+ ;; declaration.
(setq maybe-expression t)
- (throw 'at-decl-or-cast t))
+ (when (or (not c-asymmetry-fontification-flag)
+ (looking-at "=\\([^=]\\|$\\)\\|;")
+ (c-fdoc-assymetric-space-about-asterisk))
+ (when (eq at-type 'maybe)
+ (setq unsafe-maybe t))
+ (throw 'at-decl-or-cast t)))
;; CASE 17
(when (and (or got-suffix-after-parens
@@ -11112,25 +11506,12 @@ This function might do hidden buffer changes."
got-prefix-before-parens
at-type
(or (not got-suffix)
- at-decl-start))
- (let ((space-before-id
- (save-excursion
- (goto-char id-start) ; Position of "*".
- (and (> (skip-chars-forward "* \t\n\r") 0)
- (memq (char-before) '(?\ ?\t ?\n ?\r)))))
- (space-after-type
- (save-excursion
- (goto-char type-start)
- (and (c-forward-type)
- (progn (c-backward-syntactic-ws) t)
- (or (eolp)
- (memq (char-after) '(?\ ?\t)))))))
- (when (not (eq (not space-before-id)
- (not space-after-type)))
- (when (eq at-type 'maybe)
- (setq unsafe-maybe t))
- (setq maybe-expression t)
- (throw 'at-decl-or-cast t)))))
+ at-decl-start)
+ (c-fdoc-assymetric-space-about-asterisk))
+ (when (eq at-type 'maybe)
+ (setq unsafe-maybe t))
+ (setq maybe-expression t)
+ (throw 'at-decl-or-cast t)))
;; CASE 18
(when (and at-decl-end
@@ -11895,11 +12276,14 @@ comment at the start of cc-engine.el for more info."
;; Each time around the following checks one
;; declaration (which may contain several identifiers).
(while (and
- (consp (setq decl-or-cast
- (c-forward-decl-or-cast-1
- after-prec-token
- nil ; Or 'arglist ???
- nil)))
+ (not (eq (char-after) ?{))
+ (or
+ (consp (setq decl-or-cast
+ (c-forward-decl-or-cast-1
+ after-prec-token
+ nil ; Or 'arglist ???
+ nil)))
+ (throw 'knr nil))
(memq (char-after) '(?\; ?\,))
(goto-char (car decl-or-cast))
(save-excursion
@@ -12243,31 +12627,27 @@ comment at the start of cc-engine.el for more info."
(let ((open-brace (point)) kwd-start first-specifier-pos)
(c-syntactic-skip-backward c-block-prefix-charset limit t)
- (when (and c-recognize-<>-arglists
- (eq (char-before) ?>))
- ;; Could be at the end of a template arglist.
- (let ((c-parse-and-markup-<>-arglists t))
- (while (and
- (c-backward-<>-arglist nil limit)
- (progn
- (c-syntactic-skip-backward c-block-prefix-charset limit t)
- (eq (char-before) ?>))))))
-
- ;; Skip back over noise clauses.
- (while (and
- c-opt-cpp-prefix
- (eq (char-before) ?\))
- (let ((after-paren (point)))
- (if (and (c-go-list-backward)
- (progn (c-backward-syntactic-ws)
- (c-simple-skip-symbol-backward))
- (or (looking-at c-paren-nontype-key)
- (looking-at c-noise-macro-with-parens-name-re)))
- (progn
- (c-syntactic-skip-backward c-block-prefix-charset limit t)
- t)
- (goto-char after-paren)
- nil))))
+ (while
+ (or
+ ;; Could be after a template arglist....
+ (and c-recognize-<>-arglists
+ (eq (char-before) ?>)
+ (let ((c-parse-and-markup-<>-arglists t))
+ (c-backward-<>-arglist nil limit)))
+ ;; .... or after a noise clause with parens.
+ (and c-opt-cpp-prefix
+ (let ((after-paren (point)))
+ (if (eq (char-before) ?\))
+ (and
+ (c-go-list-backward)
+ (eq (char-after) ?\()
+ (progn (c-backward-syntactic-ws)
+ (c-simple-skip-symbol-backward))
+ (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
+ (looking-at c-noise-macro-with-parens-name-re)))
+ (goto-char after-paren)
+ nil))))
+ (c-syntactic-skip-backward c-block-prefix-charset limit t))
;; Note: Can't get bogus hits inside template arglists below since they
;; have gotten paren syntax above.
@@ -12277,10 +12657,18 @@ comment at the start of cc-engine.el for more info."
;; The `c-decl-block-key' search continues from there since
;; we know it can't match earlier.
(if goto-start
- (when (c-syntactic-re-search-forward c-symbol-start
- open-brace t t)
- (goto-char (setq first-specifier-pos (match-beginning 0)))
- t)
+ (progn
+ (while
+ (and
+ (c-syntactic-re-search-forward c-symbol-start
+ open-brace t t)
+ (goto-char (match-beginning 0))
+ (if (or (looking-at c-noise-macro-name-re)
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause)
+ (setq first-specifier-pos (match-beginning 0))
+ nil)))
+ first-specifier-pos)
t)
(cond
@@ -12349,34 +12737,39 @@ comment at the start of cc-engine.el for more info."
(goto-char first-specifier-pos)
(while (< (point) kwd-start)
- (if (looking-at c-symbol-key)
- ;; Accept any plain symbol token on the ground that
- ;; it's a specifier masked through a macro (just
- ;; like `c-forward-decl-or-cast-1' skip forward over
- ;; such tokens).
- ;;
- ;; Could be more restrictive wrt invalid keywords,
- ;; but that'd only occur in invalid code so there's
- ;; no use spending effort on it.
- (let ((end (match-end 0))
- (kwd-sym (c-keyword-sym (match-string 0))))
- (unless
- (and kwd-sym
- ;; Moving over a protection kwd and the following
- ;; ":" (in C++ Mode) to the next token could take
- ;; us all the way up to `kwd-start', leaving us
- ;; no chance to update `first-specifier-pos'.
- (not (c-keyword-member kwd-sym 'c-protection-kwds))
- (c-forward-keyword-clause 0))
- (goto-char end)
- (c-forward-syntactic-ws)))
-
+ (cond
+ ((or (looking-at c-noise-macro-name-re)
+ (looking-at c-noise-macro-with-parens-name-re))
+ (c-forward-noise-clause))
+ ((looking-at c-symbol-key)
+ ;; Accept any plain symbol token on the ground that
+ ;; it's a specifier masked through a macro (just
+ ;; like `c-forward-decl-or-cast-1' skips forward over
+ ;; such tokens).
+ ;;
+ ;; Could be more restrictive wrt invalid keywords,
+ ;; but that'd only occur in invalid code so there's
+ ;; no use spending effort on it.
+ (let ((end (match-end 0))
+ (kwd-sym (c-keyword-sym (match-string 0))))
+ (unless
+ (and kwd-sym
+ ;; Moving over a protection kwd and the following
+ ;; ":" (in C++ Mode) to the next token could take
+ ;; us all the way up to `kwd-start', leaving us
+ ;; no chance to update `first-specifier-pos'.
+ (not (c-keyword-member kwd-sym 'c-protection-kwds))
+ (c-forward-keyword-clause 0))
+ (goto-char end)
+ (c-forward-syntactic-ws))))
+
+ ((c-syntactic-re-search-forward c-symbol-start
+ kwd-start 'move t)
;; Can't parse a declaration preamble and is still
;; before `kwd-start'. That means `first-specifier-pos'
;; was in some earlier construct. Search again.
- (if (c-syntactic-re-search-forward c-symbol-start
- kwd-start 'move t)
- (goto-char (setq first-specifier-pos (match-beginning 0)))
+ (goto-char (setq first-specifier-pos (match-beginning 0))))
+ (t
;; Got no preamble before the block declaration keyword.
(setq first-specifier-pos kwd-start))))
@@ -12401,7 +12794,8 @@ comment at the start of cc-engine.el for more info."
(looking-at c-class-key))
(goto-char (match-end 1))
(c-forward-syntactic-ws)
- (looking-at name))))))
+ (and (looking-at c-identifier-key)
+ (string= (match-string 0) name)))))))
(defun c-search-uplist-for-classkey (paren-state)
;; Check if the closest containing paren sexp is a declaration
@@ -12625,11 +13019,19 @@ comment at the start of cc-engine.el for more info."
(defvar c-laomib-cache nil)
(make-variable-buffer-local 'c-laomib-cache)
-(defun c-laomib-get-cache (containing-sexp)
- ;; Get an element from `c-laomib-cache' matching CONTAINING-SEXP.
+(defun c-laomib-get-cache (containing-sexp start)
+ ;; Get an element from `c-laomib-cache' matching CONTAINING-SEXP, and which
+ ;; is suitable for start position START.
;; Return that element or nil if one wasn't found.
- (let ((elt (assq containing-sexp c-laomib-cache)))
- (when elt
+ (let ((ptr c-laomib-cache)
+ elt)
+ (while
+ (and ptr
+ (setq elt (car ptr))
+ (or (not (eq (car elt) containing-sexp))
+ (< start (car (cddr elt)))))
+ (setq ptr (cdr ptr)))
+ (when ptr
;; Move the fetched `elt' to the front of the cache.
(setq c-laomib-cache (delq elt c-laomib-cache))
(push elt c-laomib-cache)
@@ -12641,18 +13043,26 @@ comment at the start of cc-engine.el for more info."
;; the components of the new element (see comment for `c-laomib-cache').
;; The return value is of no significance.
(when lim
- (let ((old-elt (assq lim c-laomib-cache))
- ;; (elt (cons containing-sexp (cons start nil)))
+ (let (old-elt
(new-elt (list lim start end result))
big-ptr
(cur-ptr c-laomib-cache)
- togo (size 0) cur-size
- )
- (if old-elt (setq c-laomib-cache (delq old-elt c-laomib-cache)))
+ togo (size 0) cur-size)
+
+ ;; If there is an elt which overlaps with the new element, remove it.
+ (while
+ (and cur-ptr
+ (setq old-elt (car cur-ptr))
+ (or (not (eq (car old-elt) lim))
+ (not (and (> start (car (cddr old-elt)))
+ (<= start (cadr old-elt))))))
+ (setq cur-ptr (cdr cur-ptr)))
+ (when (and cur-ptr old-elt)
+ (setq c-laomib-cache (delq old-elt c-laomib-cache)))
(while (>= (length c-laomib-cache) 4)
;; We delete the least recently used elt which doesn't enclose START,
- ;; or..
+ ;; or ...
(dolist (elt c-laomib-cache)
(if (or (<= start (cadr elt))
(> start (car (cddr elt))))
@@ -12660,8 +13070,10 @@ comment at the start of cc-engine.el for more info."
;; ... delete the least recently used elt which isn't the biggest.
(when (not togo)
+ (setq cur-ptr c-laomib-cache)
(while (cdr cur-ptr)
- (setq cur-size (- (nth 2 (cadr cur-ptr)) (car (cadr cur-ptr))))
+ (setq cur-size (- (cadr (cadr cur-ptr))
+ (car (cddr (cadr cur-ptr)))))
(when (> cur-size size)
(setq size cur-size
big-ptr cur-ptr))
@@ -12763,7 +13175,9 @@ comment at the start of cc-engine.el for more info."
in-paren 'in-paren))
((looking-at c-pre-brace-non-bracelist-key)
(setq braceassignp nil))
- ((looking-at c-fun-name-substitute-key)
+ ((and
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_)))
(setq braceassignp nil))
((looking-at c-return-key))
((and (looking-at c-symbol-start)
@@ -12778,7 +13192,8 @@ comment at the start of cc-engine.el for more info."
;; Have we a requires with a parenthesis list?
(when (save-excursion
(and (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-fun-name-substitute-key)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
(setq braceassignp nil))
nil)
(t nil))
@@ -12850,7 +13265,7 @@ comment at the start of cc-engine.el for more info."
(goto-char pos)
(when (eq braceassignp 'dontknow)
(let* ((cache-entry (and containing-sexp
- (c-laomib-get-cache containing-sexp)))
+ (c-laomib-get-cache containing-sexp pos)))
(lim2 (or (cadr cache-entry) lim))
sub-bassign-p)
(if cache-entry
@@ -12872,6 +13287,8 @@ comment at the start of cc-engine.el for more info."
)
(setq braceassignp (nth 3 cache-entry))
(goto-char (nth 2 cache-entry)))
+ (c-laomib-put-cache containing-sexp
+ start (point) sub-bassign-p)
(setq braceassignp sub-bassign-p)))
(t))
@@ -13109,6 +13526,120 @@ comment at the start of cc-engine.el for more info."
(t nil)))
(goto-char here))))
+(defun c-forward-concept-fragment (&optional limit stop-at-end)
+ ;; Are we currently at the "concept" keyword in a concept construct? If so
+ ;; we return the position of the first constraint expression following the
+ ;; "=" sign and move forward over the constraint. Otherwise we return nil.
+ ;; LIMIT is a forward search limit.
+ (let ((here (point)))
+ (if
+ (and
+ (looking-at c-equals-nontype-decl-key) ; "concept"
+ (goto-char (match-end 0))
+ (progn (c-forward-syntactic-ws limit)
+ (not (looking-at c-keywords-regexp)))
+ (looking-at c-identifier-key)
+ (goto-char (match-end 0))
+ (progn (c-forward-syntactic-ws limit)
+ (looking-at c-operator-re))
+ (equal (match-string 0) "=")
+ (goto-char (match-end 0)))
+ (prog1
+ (progn (c-forward-syntactic-ws limit)
+ (point))
+ (c-forward-constraint-clause limit stop-at-end))
+ (goto-char here)
+ nil)))
+
+(defun c-looking-at-concept (&optional limit)
+ ;; Are we currently at the start of a concept construct? I.e. at the
+ ;; "template" keyword followed by the construct? If so, we return a cons of
+ ;; the position of "concept" and the position of the first constraint
+ ;; expression following the "=" sign, otherwise we return nil. LIMIT is a
+ ;; forward search limit.
+ (save-excursion
+ (let (conpos)
+ (and (looking-at c-pre-concept-<>-key)
+ (goto-char (match-end 1))
+ (< (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (eq (char-after) ?<))
+ (let ((c-parse-and-markup-<>-arglists t)
+ c-restricted-<>-arglists)
+ (c-forward-<>-arglist nil))
+ (< (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (looking-at c-equals-nontype-decl-key)) ; "concept"
+ (setq conpos (match-beginning 0))
+ (goto-char (match-end 0))
+ (< (point) limit)
+ (c-syntactic-re-search-forward
+ "=" limit t t)
+ (goto-char (match-end 0))
+ (<= (point) limit)
+ (progn (c-forward-syntactic-ws limit)
+ (cons conpos (point)))))))
+
+(defun c-in-requires-or-at-end-of-clause (&optional pos)
+ ;; Is POS (default POINT) in a C++ "requires" expression or "requires"
+ ;; clause or at the end of a "requires" clause? If so return a cons
+ ;; (POSITION . END) where POSITION is that of the "requires" keyword, and
+ ;; END is `expression' if POS is in an expression, nil if it's in a clause
+ ;; or t if it's at the end of a clause. "End of a clause" means just after
+ ;; the non syntactic WS on the line where the clause ends.
+ ;;
+ ;; Note we can't use `c-beginning-of-statement-1' in this function because
+ ;; of this function's use in `c-at-vsemi-p' for C++ Mode.
+ (save-excursion
+ (if pos (goto-char pos) (setq pos (point)))
+ (let ((limit (max (- (point) 2000) (point-min)))
+ found-req req-pos found-clause res pe-start pe-end
+ )
+ (while ; Loop around syntactically significant "requires" keywords.
+ (progn
+ (while
+ (and
+ (setq found-req (re-search-backward
+ c-fun-name-substitute-key
+ limit t)) ; Fast!
+ (or (not (setq found-req
+ (not (eq (char-after (match-end 0)) ?_))))
+ (not (setq found-req (not (c-in-literal))))))) ; Slow!
+ (setq req-pos (point))
+ (cond
+ ((not found-req) ; No "requires" found
+ nil)
+ ((save-excursion ; A primary expression `pos' is in
+ (setq pe-end nil)
+ (while (and (setq pe-start (point))
+ (< (point) pos)
+ (c-forward-primary-expression nil t)
+ (setq pe-end (point))
+ (progn (c-forward-syntactic-ws)
+ (looking-at "&&\\|||"))
+ (c-forward-over-token-and-ws)))
+ pe-end)
+ (if (<= pe-end pos)
+ t ; POS is not in a primary expression.
+ (setq res (cons pe-start 'expression))
+ nil))
+ ((progn
+ (goto-char req-pos)
+ (if (looking-at c-fun-name-substitute-key)
+ (setq found-clause (c-forward-c++-requires-clause nil t))
+ (and (c-forward-concept-fragment)
+ (setq found-clause (point))))
+ nil))
+ ((and found-clause (>= (point) pos))
+ (setq res (cons req-pos (eq (point) pos)))
+ nil)
+ (found-clause ; We found a constraint clause, but it did not
+ ; extend far enough forward to reach POS.
+ (c-go-up-list-backward req-pos limit))
+ (t (goto-char req-pos)
+ t))))
+ res)))
+
(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
;; Return non-nil if we're looking at the beginning of a block
;; inside an expression. The value returned is actually a cons of
@@ -13305,6 +13836,19 @@ comment at the start of cc-engine.el for more info."
(looking-at c-pre-lambda-tokens-re)))
(not (c-in-literal))))
+(defun c-c++-vsemi-p (&optional pos)
+ ;; C++ Only - Is there a "virtual semicolon" at POS or point?
+ ;; (See cc-defs.el for full details of "virtual semicolons".)
+ ;;
+ ;; This is true when point is at the last non syntactic WS position on the
+ ;; line, and either there is a "macro with semicolon" just before it (see
+ ;; `c-at-macro-vsemi-p') or there is a "requires" clause which ends there.
+ (let (res)
+ (cond
+ ((setq res (c-in-requires-or-at-end-of-clause pos))
+ (and res (eq (cdr res) t)))
+ ((c-at-macro-vsemi-p)))))
+
(defun c-at-macro-vsemi-p (&optional pos)
;; Is there a "virtual semicolon" at POS or point?
;; (See cc-defs.el for full details of "virtual semicolons".)
@@ -13640,7 +14184,8 @@ comment at the start of cc-engine.el for more info."
(defun c-add-class-syntax (symbol
containing-decl-open
containing-decl-start
- containing-decl-kwd)
+ containing-decl-kwd
+ &rest args)
;; The inclass and class-close syntactic symbols are added in
;; several places and some work is needed to fix everything.
;; Therefore it's collected here.
@@ -13655,7 +14200,7 @@ comment at the start of cc-engine.el for more info."
;; Ought to use `c-add-stmt-syntax' instead of backing up to boi
;; here, but we have to do like this for compatibility.
(back-to-indentation)
- (c-add-syntax symbol (point))
+ (apply #'c-add-syntax symbol (point) args)
(if (and (c-keyword-member containing-decl-kwd
'c-inexpr-class-kwds)
(/= containing-decl-start (c-point 'boi containing-decl-start)))
@@ -13689,9 +14234,10 @@ comment at the start of cc-engine.el for more info."
;; CASE B.1: class-open
((save-excursion
(and (eq (char-after) ?{)
- (c-looking-at-decl-block t)
+ (setq placeholder (c-looking-at-decl-block t))
(setq beg-of-same-or-containing-stmt (point))))
- (c-add-syntax 'class-open beg-of-same-or-containing-stmt))
+ (c-add-syntax 'class-open beg-of-same-or-containing-stmt
+ (c-point 'boi placeholder)))
;; CASE B.2: brace-list-open
((or (consp special-brace-list)
@@ -13856,7 +14402,7 @@ comment at the start of cc-engine.el for more info."
literal char-before-ip before-ws-ip char-after-ip macro-start
in-macro-expr c-syntactic-context placeholder
step-type tmpsymbol keyword injava-inher special-brace-list tmp-pos
- tmp-pos2 containing-<
+ tmp-pos2 containing-< tmp constraint-detail
;; The following record some positions for the containing
;; declaration block if we're directly within one:
;; `containing-decl-open' is the position of the open
@@ -14186,7 +14732,10 @@ comment at the start of cc-engine.el for more info."
'lambda-intro-cont)))
(goto-char (cdr placeholder))
(back-to-indentation)
- (c-add-stmt-syntax tmpsymbol nil t
+ (c-add-stmt-syntax tmpsymbol
+ (and (eq tmpsymbol 'class-open)
+ (list (point)))
+ t
(c-most-enclosing-brace state-cache (point))
paren-state)
(unless (eq (point) (cdr placeholder))
@@ -14229,9 +14778,10 @@ comment at the start of cc-engine.el for more info."
(goto-char indent-point)
(skip-chars-forward " \t")
(and (eq (char-after) ?{)
- (c-looking-at-decl-block t)
+ (setq tmp-pos (c-looking-at-decl-block t))
(setq placeholder (point))))
- (c-add-syntax 'class-open placeholder))
+ (c-add-syntax 'class-open placeholder
+ (c-point 'boi tmp-pos)))
;; CASE 5A.3: brace list open
((save-excursion
@@ -14271,6 +14821,33 @@ comment at the start of cc-engine.el for more info."
containing-decl-start
containing-decl-kwd))
+ ;; CASE 5A.7: "defun" open in a requires expression.
+ ((save-excursion
+ (goto-char indent-point)
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))
+ (setq placeholder (point))))
+ (goto-char placeholder)
+ (back-to-indentation)
+ (c-add-syntax 'defun-open (point)))
+
+ ;; CASE 5A.6: "defun" open in concept.
+ ;; ((save-excursion
+ ;; (goto-char indent-point)
+ ;; (skip-chars-forward " \t")
+ ;; (and (eq (char-after) ?{)
+ ;; (eq (c-beginning-of-statement-1 lim) 'same)
+ ;; (setq placeholder
+ ;; (cdr (c-looking-at-concept indent-point)))))
+ ;; (goto-char placeholder)
+ ;; (back-to-indentation)
+ ;; (c-add-syntax 'defun-open (point)))
+
;; CASE 5A.5: ordinary defun open
(t
(save-excursion
@@ -14441,10 +15018,35 @@ comment at the start of cc-engine.el for more info."
nil nil
containing-sexp paren-state))
+ ;; CASE 5F: Close of a non-class declaration level block.
+ ((and (eq char-after-ip ?})
+ (c-keyword-member containing-decl-kwd
+ 'c-other-block-decl-kwds))
+ ;; This is inconsistent: Should use `containing-decl-open'
+ ;; here if it's at boi, like in case 5J.
+ (goto-char containing-decl-start)
+ (c-add-stmt-syntax
+ (if (string-equal (symbol-name containing-decl-kwd) "extern")
+ ;; Special case for compatibility with the
+ ;; extern-lang syntactic symbols.
+ 'extern-lang-close
+ (intern (concat (symbol-name containing-decl-kwd)
+ "-close")))
+ nil t
+ (c-most-enclosing-brace paren-state (point))
+ paren-state))
+
+ ;; CASE 5T: Continuation of a concept clause.
+ ((save-excursion
+ (and (eq (c-beginning-of-statement-1 nil t) 'same)
+ (setq tmp (c-looking-at-concept indent-point))))
+ (c-add-syntax 'constraint-cont (car tmp)))
+
;; CASE 5D: this could be a top-level initialization, a
;; member init list continuation, or a template argument
;; list continuation.
((save-excursion
+ (setq constraint-detail (c-in-requires-or-at-end-of-clause))
;; Note: We use the fact that lim is always after any
;; preceding brace sexp.
(if c-recognize-<>-arglists
@@ -14474,8 +15076,9 @@ comment at the start of cc-engine.el for more info."
;; clause - we assume only C++ needs it.
(c-syntactic-skip-backward "^;,=" lim t))
(setq placeholder (point))
- (and (memq (char-before) '(?, ?= ?<))
- (not (c-crosses-statement-barrier-p (point) indent-point))))
+ (or constraint-detail
+ (and (memq (char-before) '(?, ?= ?<))
+ (not (c-crosses-statement-barrier-p (point) indent-point)))))
(cond
;; CASE 5D.6: Something like C++11's "using foo = <type-exp>"
@@ -14493,8 +15096,7 @@ comment at the start of cc-engine.el for more info."
(c-on-identifier))
(setq placeholder preserve-point)))))
(c-add-syntax
- 'statement-cont placeholder)
- )
+ 'statement-cont placeholder))
;; CASE 5D.3: perhaps a template list continuation?
((and (c-major-mode-is 'c++-mode)
@@ -14544,21 +15146,10 @@ comment at the start of cc-engine.el for more info."
;; CASE 5D.7: Continuation of a "concept foo =" line in C++20 (or
;; similar).
- ((and c-equals-nontype-decl-key
- (save-excursion
- (prog1
- (and (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-operator-re)
- (equal (match-string 0) "=")
- (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-symbol-start)
- (not (looking-at c-keywords-regexp))
- (zerop (c-backward-token-2 1 nil lim))
- (looking-at c-equals-nontype-decl-key)
- (eq (c-beginning-of-statement-1 lim) 'same))
- (setq placeholder (point)))))
- (goto-char placeholder)
- (c-add-stmt-syntax 'topmost-intro-cont nil nil containing-sexp
+ ((and constraint-detail
+ (not (eq (cdr constraint-detail) 'expression)))
+ (goto-char (car constraint-detail))
+ (c-add-stmt-syntax 'constraint-cont nil nil containing-sexp
paren-state))
;; CASE 5D.5: Continuation of the "expression part" of a
@@ -14583,33 +15174,19 @@ comment at the start of cc-engine.el for more info."
nil nil containing-sexp paren-state))
))
- ;; CASE 5F: Close of a non-class declaration level block.
- ((and (eq char-after-ip ?})
- (c-keyword-member containing-decl-kwd
- 'c-other-block-decl-kwds))
- ;; This is inconsistent: Should use `containing-decl-open'
- ;; here if it's at boi, like in case 5J.
- (goto-char containing-decl-start)
- (c-add-stmt-syntax
- (if (string-equal (symbol-name containing-decl-kwd) "extern")
- ;; Special case for compatibility with the
- ;; extern-lang syntactic symbols.
- 'extern-lang-close
- (intern (concat (symbol-name containing-decl-kwd)
- "-close")))
- nil t
- (c-most-enclosing-brace paren-state (point))
- paren-state))
-
;; CASE 5G: we are looking at the brace which closes the
;; enclosing nested class decl
((and containing-sexp
(eq char-after-ip ?})
(eq containing-decl-open containing-sexp))
+ (save-excursion
+ (goto-char containing-decl-open)
+ (setq tmp-pos (c-looking-at-decl-block t)))
(c-add-class-syntax 'class-close
containing-decl-open
containing-decl-start
- containing-decl-kwd))
+ containing-decl-kwd
+ (c-point 'boi tmp-pos)))
;; CASE 5H: we could be looking at subsequent knr-argdecls
((and c-recognize-knr-p
@@ -14813,7 +15390,59 @@ 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.)
+ ;; CASE 20: A C++ requires sub-clause.
+ ((and (setq tmp (c-in-requires-or-at-end-of-clause indent-point))
+ (not (eq (cdr tmp) 'expression))
+ (setq placeholder (car tmp)))
+ (c-add-syntax
+ (if (eq char-after-ip ?{)
+ 'substatement-open
+ 'substatement)
+ (c-point 'boi placeholder)))
+
+ ;; ((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
@@ -15154,6 +15783,20 @@ comment at the start of cc-engine.el for more info."
(c-add-syntax 'defun-close (point))
(c-add-syntax 'inline-close (point))))
+ ;; CASE 16G: Do we have the closing brace of a "requires" clause
+ ;; of a C++20 "concept"?
+ ((save-excursion
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
+ (goto-char containing-sexp)
+ (back-to-indentation)
+ (c-add-stmt-syntax 'defun-close nil t lim paren-state))
+
;; CASE 16F: Can be a defun-close of a function declared
;; in a statement block, e.g. in Pike or when using gcc
;; extensions, but watch out for macros followed by
@@ -15304,6 +15947,21 @@ comment at the start of cc-engine.el for more info."
(if (eq char-after-ip ?{)
(c-add-syntax 'block-open)))
+ ;; CASE 17J: first "statement" inside a C++20 requires
+ ;; "function".
+ ((save-excursion
+ (goto-char containing-sexp)
+ (c-backward-syntactic-ws lim)
+ (and (or (not (eq (char-before) ?\)))
+ (c-go-list-backward nil lim))
+ (progn (c-backward-syntactic-ws lim)
+ (zerop (c-backward-token-2 nil nil lim)))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))
+ (goto-char containing-sexp)
+ (back-to-indentation)
+ (c-add-syntax 'defun-block-intro (point)))
+
;; CASE 17F: first statement in an inline, or first
;; statement in a top-level defun. we can tell this is it
;; if there are no enclosing braces that haven't been
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index d4079bdd6dd..6419d6cf05a 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))))
@@ -387,7 +387,7 @@
(parse-sexp-lookup-properties
(cc-eval-when-compile
(boundp 'parse-sexp-lookup-properties))))
- ,(c-make-font-lock-search-form regexp highlights))
+ ,(c-make-font-lock-search-form regexp highlights t))
nil)))
(defun c-make-font-lock-BO-decl-search-function (regexp &rest highlights)
@@ -1112,7 +1112,7 @@ casts and declarations are fontified. Used on level 2 and higher."
;; 'c-decl-type-start (according to TYPES). Stop at LIMIT.
;;
;; If TYPES is t, fontify all identifiers as types; if it is a number, a
- ;; buffer position, additionally set the `c-deftype' text property on the
+ ;; buffer position, additionally set the `c-typedef' text property on the
;; keyword at that position; if it is nil fontify as either variables or
;; functions, otherwise TYPES is a face to use. If NOT-TOP is non-nil, we
;; are not at the top-level ("top-level" includes being directly inside a
@@ -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)
@@ -1378,7 +1388,8 @@ casts and declarations are fontified. Used on level 2 and higher."
(memq type '(c-decl-arg-start
c-decl-type-start))))))))
((and (zerop (c-backward-token-2))
- (looking-at c-fun-name-substitute-key)))))))))
+ (looking-at c-fun-name-substitute-key)
+ (not (eq (char-after (match-end 0)) ?_))))))))))
;; Cache the result of this test for next time around.
(c-put-char-property (1- match-pos) 'c-type 'c-decl-arg-start)
(cons 'decl nil))
@@ -1616,13 +1627,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 +1697,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 +1727,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.
;;
@@ -1854,6 +1890,38 @@ casts and declarations are fontified. Used on level 2 and higher."
(c-font-lock-declarators limit t in-typedef
(not (c-bs-at-toplevel-p (point)))))))))))
+(defun c-font-lock-ids-with-dollar (limit)
+ ;; Maybe fontify identifiers with a dollar using `font-lock-warning-face'.
+ ;; This is done only for languages which tolerate a $ in ids, and only when
+ ;; the flag variable `c-warn-ids-with-dollar' is set to non-nil. This
+ ;; function only works after functions such as `c-font-lock-declarations'
+ ;; have already been run.
+ ;;
+ ;; This function will be called from font-lock for a region bounded by POINT
+ ;; and LIMIT, as though it were to identify a keyword for
+ ;; font-lock-keyword-face. It always returns NIL to inhibit this and
+ ;; prevent a repeat invocation. See elisp/lispref page "Search-based
+ ;; Fontification".
+ (when c-warn-ids-with-dollar
+ (let (id-start)
+ (while (and (< (point) limit)
+ (skip-chars-forward "^$" limit)
+ (< (point) limit)
+ (eq (char-after) ?$))
+ (if (and (memq (c-get-char-property (point) 'face)
+ '(font-lock-variable-name-face
+ font-lock-function-name-face
+ font-lock-type-face))
+ (setq id-start (c-on-identifier)))
+ (progn
+ (goto-char id-start)
+ (looking-at c-identifier-key)
+ (c-put-font-lock-face (match-beginning 0) (match-end 0)
+ 'font-lock-warning-face)
+ (goto-char (match-end 0)))
+ (forward-char)))
+ nil)))
+
(defun c-font-lock-ml-strings (limit)
;; Fontify multi-line strings.
;;
@@ -2254,7 +2322,12 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
;; Fontify generic colon labels in languages that support them.
,@(when (c-lang-const c-recognize-colon-labels)
- '(c-font-lock-labels))))
+ '(c-font-lock-labels))
+
+ ;; Maybe fontify identifiers containing a dollar sign with
+ ;; `font-lock-warning-face'.
+ ,@(when (c-lang-const c-dollar-in-ids)
+ `(c-font-lock-ids-with-dollar))))
(c-lang-defconst c-complex-decl-matchers
"Complex font lock matchers for types and declarations. Used on level
@@ -2330,7 +2403,11 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
;; (see Elisp page "Search-based Fontification").
'(("\\<new\\>"
(c-font-lock-c++-new))))
- ))
+
+ ;; Maybe fontify identifiers containing a dollar sign with
+ ;; `font-lock-warning-face'.
+ ,@(when (c-lang-const c-dollar-in-ids)
+ `(c-font-lock-ids-with-dollar))))
(defun c-font-lock-labels (limit)
;; Fontify all statement labels from the point to LIMIT. Assumes
@@ -2623,7 +2700,9 @@ need for `c-font-lock-extra-types'.")
;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; fontification".
(let (pos)
- (while (c-syntactic-re-search-forward c-using-key limit 'end)
+ (while
+ (and (< (point) limit)
+ (c-syntactic-re-search-forward c-using-key limit 'end))
(while ; Do one declarator of a comma separated list, each time around.
(progn
(c-forward-syntactic-ws)
@@ -2643,9 +2722,7 @@ need for `c-font-lock-extra-types'.")
'same)
(looking-at c-colon-type-list-re)))
;; Inherited protected member: leave unfontified
- )
- (t (goto-char pos)
- (c-font-lock-declarators limit nil c-label-face-name nil)))
+ ))
(eq (char-after) ?,)))
(forward-char))) ; over the comma.
nil))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 9bbcd065b7f..ba0d1d0fc49 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -455,19 +455,29 @@ so that all identifiers are recognized as words.")
c++ '(c-extend-region-for-CPP
c-depropertize-CPP
c-before-change-check-ml-strings
+ c-unmark-<>-around-region
c-before-change-check-<>-operators
c-before-after-change-check-c++-modules
c-truncate-bs-cache
c-before-change-check-unbalanced-strings
c-parse-quotes-before-change
c-before-change-fix-comment-escapes)
- (c objc) '(c-extend-region-for-CPP
- c-depropertize-CPP
- c-truncate-bs-cache
- c-before-change-check-unbalanced-strings
- c-parse-quotes-before-change
- c-before-change-fix-comment-escapes)
+ c '(c-extend-region-for-CPP
+ c-depropertize-CPP
+ c-truncate-bs-cache
+ c-before-change-check-unbalanced-strings
+ c-parse-quotes-before-change
+ c-before-change-fix-comment-escapes)
+ objc '(c-extend-region-for-CPP
+ c-depropertize-CPP
+ c-truncate-bs-cache
+ c-before-change-check-unbalanced-strings
+ c-unmark-<>-around-region
+ c-before-change-check-<>-operators
+ c-parse-quotes-before-change
+ c-before-change-fix-comment-escapes)
java '(c-parse-quotes-before-change
+ c-unmark-<>-around-region
c-before-change-check-unbalanced-strings
c-before-change-check-<>-operators)
pike '(c-before-change-check-ml-strings
@@ -502,20 +512,31 @@ parameters \(point-min) and \(point-max).")
c-after-change-escape-NL-in-string
c-after-change-mark-abnormal-strings
c-change-expand-fl-region)
- (c objc) '(c-depropertize-new-text
- c-after-change-fix-comment-escapes
- c-after-change-escape-NL-in-string
- c-parse-quotes-after-change
- c-after-change-mark-abnormal-strings
- c-extend-font-lock-region-for-macros
- c-neutralize-syntax-in-CPP
- c-change-expand-fl-region)
+ c '(c-depropertize-new-text
+ c-after-change-fix-comment-escapes
+ c-after-change-escape-NL-in-string
+ c-parse-quotes-after-change
+ c-after-change-mark-abnormal-strings
+ c-extend-font-lock-region-for-macros
+ c-neutralize-syntax-in-CPP
+ c-change-expand-fl-region)
+ objc '(c-depropertize-new-text
+ c-after-change-fix-comment-escapes
+ c-after-change-escape-NL-in-string
+ c-parse-quotes-after-change
+ c-after-change-mark-abnormal-strings
+ c-unmark-<>-around-region
+ c-extend-font-lock-region-for-macros
+ c-neutralize-syntax-in-CPP
+ c-restore-<>-properties
+ c-change-expand-fl-region)
c++ '(c-depropertize-new-text
c-after-change-fix-comment-escapes
c-after-change-escape-NL-in-string
c-after-change-unmark-ml-strings
c-parse-quotes-after-change
c-after-change-mark-abnormal-strings
+ c-unmark-<>-around-region
c-extend-font-lock-region-for-macros
c-before-after-change-check-c++-modules
c-neutralize-syntax-in-CPP
@@ -524,6 +545,7 @@ parameters \(point-min) and \(point-max).")
java '(c-depropertize-new-text
c-after-change-escape-NL-in-string
c-parse-quotes-after-change
+ c-unmark-<>-around-region
c-after-change-mark-abnormal-strings
c-restore-<>-properties
c-change-expand-fl-region)
@@ -586,7 +608,8 @@ Such a function takes one optional parameter, a buffer position (defaults to
point), and returns nil or t. This variable contains nil for languages which
don't have EOL terminated statements. "
t nil
- (c c++ objc) 'c-at-macro-vsemi-p
+ (c objc) 'c-at-macro-vsemi-p
+ c++ 'c-c++-vsemi-p
awk 'c-awk-at-vsemi-p)
(c-lang-defvar c-at-vsemi-p-fn (c-lang-const c-at-vsemi-p-fn))
@@ -738,11 +761,11 @@ When non-nil, this variable should end in \"\\\\\\==\". Note that
such a backward search will match a minimal string, so a
\"context character\" is probably needed at the start of the
regexp. The value for csharp-mode would be something like
-\"\\\\(:?\\\\`\\\\|[^\\\"]\\\\)\\\"*\\\\\\==\"."
+\"\\\\(?:\\\\`\\\\|[^\\\"]\\\\)\\\"*\\\\\\==\"."
t nil
- pike "\\(:?\\`\\|[^\\\"]\\)\\(:?\\\\.\\)*\\="
+ pike "\\(?:\\`\\|[^\\\"]\\)\\(?:\\\\.\\)*\\="
;;pike ;; 2
- ;; "\\(:?\\`\\|[^\"]\\)\"*\\="
+ ;; "\\(?:\\`\\|[^\"]\\)\"*\\="
)
(c-lang-defvar c-ml-string-back-closer-re
(c-lang-const c-ml-string-back-closer-re))
@@ -794,7 +817,7 @@ there be copies of the opener contained in the multi-line string."
(c-lang-defconst c-cpp-or-ml-match-offset
;; The offset to be added onto match numbers for a multi-line string in
- ;; matches for `c-cpp-or-ml-string-opener-re'.
+ ;; matches for `c-ml-string-cpp-or-opener-re'.
t (if (c-lang-const c-anchored-cpp-prefix)
(+ 2 (regexp-opt-depth (c-lang-const c-anchored-cpp-prefix)))
2))
@@ -829,8 +852,9 @@ which `c-backward-sexp' needs to be called twice to move backwards over."
keyword. It's unspecified how far it matches. Does not contain a \\|
operator at the top level."
t (concat "[" c-alpha "_]")
+ (c c++) (concat "[" c-alpha "_$]")
java (concat "[" c-alpha "_@]")
- objc (concat "[" c-alpha "_@]")
+ objc (concat "[" c-alpha "_@$]")
pike (concat "[" c-alpha "_`]"))
(c-lang-defvar c-symbol-start (c-lang-const c-symbol-start))
@@ -843,6 +867,10 @@ This is of the form that fits inside [ ] in a regexp."
objc (concat c-alnum "_$@"))
(c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars))
+(c-lang-defconst c-dollar-in-ids
+ "Non-nil when a dollar (can be) a non-standard constituent of an identifier."
+ t (string-match (c-lang-const c-symbol-start) "$"))
+
(c-lang-defconst c-symbol-char-key
"Regexp matching a sequence of at least one identifier character."
t (concat "[" (c-lang-const c-symbol-chars) "]+"))
@@ -854,9 +882,9 @@ to match if `c-symbol-start' matches on the same position."
t (concat (c-lang-const c-symbol-start)
"[" (c-lang-const c-symbol-chars) "]\\{,1000\\}")
pike (concat
- ;; Use the value from C here since the operator backquote is
+ ;; Use the value from AWK here since the operator backquote is
;; covered by the other alternative.
- (c-lang-const c-symbol-key c)
+ (c-lang-const c-symbol-key awk)
"\\|"
(c-make-keywords-re nil
(c-lang-const c-overloadable-operators))))
@@ -1043,14 +1071,6 @@ Currently (2022-09) just C++ Mode uses this."
;; matched.
t nil)
-(c-lang-defconst c-string-escaped-newlines
- "Set if the language support backslash escaped newlines inside string
-literals."
- t nil
- (c c++ objc pike) t)
-(c-lang-defvar c-string-escaped-newlines
- (c-lang-const c-string-escaped-newlines))
-
(c-lang-defconst c-multiline-string-start-char
"Set if the language supports multiline string literals without escaped
newlines. If t, all string literals are multiline. If a character,
@@ -1067,6 +1087,18 @@ further directions."
(c-lang-defvar c-multiline-string-start-char
(c-lang-const c-multiline-string-start-char))
+(c-lang-defconst c-escaped-newline-takes-precedence
+ "Set if the language resolves escaped newlines first.
+This makes a difference in a string like \"...\\\\\n\". When
+this variable is nil, the first backslash escapes the second,
+leaving an unterminated string. When it's non-nil, the string is
+continued onto the next line, and the first backslash escapes
+whatever begins that next line."
+ t nil
+ (c c++ objc pike) t)
+(c-lang-defvar c-escaped-newline-takes-precedence
+ (c-lang-const c-escaped-newline-takes-precedence))
+
(c-lang-defconst c-string-innards-re-alist
;; An alist of regexps matching the innards of a string, the key being the
;; string's delimiter.
@@ -1077,9 +1109,12 @@ further directions."
t (mapcar (lambda (delim)
(cons
delim
- (concat "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r"
- (string delim)
- "]\\)*")))
+ (concat
+ (if (c-lang-const c-escaped-newline-takes-precedence)
+ "\\(\\\\\\(\\\\?\n\\|.\\)\\|[^\\\n\r"
+ "\\(\\\\\\(\n\\|.\\)\\|[^\\\n\r")
+ (string delim)
+ "]\\)*")))
(and
(or (null (c-lang-const c-multiline-string-start-char))
(c-characterp (c-lang-const c-multiline-string-start-char)))
@@ -2635,9 +2670,12 @@ clause. An arglist may or may not follow such a keyword."
c++ '("requires"))
(c-lang-defconst c-fun-name-substitute-key
- ;; An adorned regular expression which matches any member of
+ ;; An unadorned regular expression which matches any member of
;; `c-fun-name-substitute-kwds'.
- t (c-make-keywords-re t (c-lang-const c-fun-name-substitute-kwds)))
+ t (c-make-keywords-re 'appendable (c-lang-const c-fun-name-substitute-kwds)))
+;; We use 'appendable, so that we get "\\>" on the regexp, but without a further
+;; character, which would mess up backward regexp search from just after the
+;; keyword. If only XEmacs had \\_>. ;-(
(c-lang-defvar c-fun-name-substitute-key
(c-lang-const c-fun-name-substitute-key))
@@ -3086,6 +3124,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)
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 5c1cc761ad6..64a679eacc7 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -255,6 +255,13 @@ control). See \"cc-mode.el\" for more info."
;; Will try initialization hooks again if they failed.
(put 'c-initialize-cc-mode initprop c-initialization-ok))))
+ ;; Set up text conversion, for Emacs >= 30.0
+ ;; This is needed here because CC-mode's implementation of
+ ;; electricity does not rely on `post-self-insert-hook' (which is
+ ;; already handled adequately by `analyze-text-conversion').
+ (when (boundp 'post-text-conversion-hook)
+ (add-hook 'post-text-conversion-hook #'c-post-text-conversion nil t))
+
(unless new-style-init
(c-init-language-vars-for 'c-mode)))
@@ -1275,7 +1282,9 @@ Note that the style variables are always made local to the buffer."
;; VALUE (which should not be nil).
;; `(let ((-pos- ,pos)
;; (-value- ,value))
- (c-put-char-property pos 'syntax-table value)
+ (if (equal value '(15))
+ (c-put-string-fence pos)
+ (c-put-char-property pos 'syntax-table value))
(c-put-char-property pos 'c-fl-syn-tab value)
(cond
((null c-min-syn-tab-mkr)
@@ -1367,7 +1376,15 @@ Note that the style variables are always made local to the buffer."
(and ;(< (point) end)
(not (nth 3 s))
(c-get-char-property (1- (point)) 'c-fl-syn-tab))
- (c-put-char-property pos 'syntax-table '(1)))
+ (c-put-char-property pos 'syntax-table '(1))
+ ;; Remove syntax-table text properties from template
+ ;; delimiters.
+ (c-clear-char-property-with-value
+ (1+ pos) (c-point 'eol pos)
+ 'syntax-table c-<-as-paren-syntax)
+ (c-clear-char-property-with-value
+ (1+ pos) (c-point 'eol pos)
+ 'syntax-table c->-as-paren-syntax))
(setq pos (point)))
(setq pos (1+ pos)))))))))
@@ -1384,6 +1401,9 @@ Note that the style variables are always made local to the buffer."
(setq pos
(c-min-property-position pos c-max-syn-tab-mkr 'c-fl-syn-tab))
(< pos c-max-syn-tab-mkr))
+ (when (and (equal (c-get-char-property pos 'syntax-table) '(1))
+ (equal (c-get-char-property pos 'c-fl-syn-tab) '(15)))
+ (c-clear-char-properties (1+ pos) (c-point 'eol pos) 'syntax-table))
(c-put-char-property pos 'syntax-table
(c-get-char-property pos 'c-fl-syn-tab))
(setq pos (1+ pos))))))
@@ -2444,8 +2464,6 @@ with // and /*, not more generic line and block comments."
(setq pseudo (c-cheap-inside-bracelist-p (c-parse-state)))))))
(goto-char pseudo))
t)
- (or (> (point) bod-lim)
- (eq bod-lim (point-min)))
;; Move forward to the start of the next declaration.
(progn (c-forward-syntactic-ws)
;; Have we got stuck in a comment at EOB?
@@ -2720,18 +2738,18 @@ This function is called from `c-common-init', once per mode initialization."
;; Emacs < 22 and XEmacs
(defmacro c-advise-fl-for-region (function)
(declare (debug t))
- `(defadvice ,function (before get-awk-region activate)
- ;; Make sure that any string/regexp is completely font-locked.
- (when c-buffer-is-cc-mode
- (save-excursion
- (ad-set-arg 1 c-new-END) ; end
- (ad-set-arg 0 c-new-BEG))))) ; beg
-
-(unless (boundp 'font-lock-extend-after-change-region-function)
- (c-advise-fl-for-region font-lock-after-change-function)
- (c-advise-fl-for-region jit-lock-after-change)
- (c-advise-fl-for-region lazy-lock-defer-rest-after-change)
- (c-advise-fl-for-region lazy-lock-defer-line-after-change))
+ (unless (boundp 'font-lock-extend-after-change-region-function)
+ `(defadvice ,function (before get-awk-region activate)
+ ;; Make sure that any string/regexp is completely font-locked.
+ (when c-buffer-is-cc-mode
+ (save-excursion
+ (ad-set-arg 1 c-new-END) ; end
+ (ad-set-arg 0 c-new-BEG)))))) ; beg
+
+(c-advise-fl-for-region font-lock-after-change-function)
+(c-advise-fl-for-region jit-lock-after-change)
+(c-advise-fl-for-region lazy-lock-defer-rest-after-change)
+(c-advise-fl-for-region lazy-lock-defer-line-after-change)
;; Connect up to `electric-indent-mode' (Emacs 24.4 and later).
(defun c-electric-indent-mode-hook ()
@@ -2861,7 +2879,7 @@ Key bindings:
"\\|" id "::"
"\\|" id ws-maybe "=\\)"
"\\|" "\\(?:inline" ws "\\)?namespace"
- "\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{"
+ "\\(?:" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{"
"\\|" "class" ws id
"\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]"
"\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]"
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index b79853252ac..ff6371d9368 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -658,8 +658,9 @@ any reason to call this function directly."
(let ((func (if this-buf-only-p
'make-local-variable
'make-variable-buffer-local))
- (varsyms (cons 'c-indentation-style (copy-alist c-style-variables))))
- (delq 'c-special-indent-hook varsyms)
+ (varsyms (cons 'c-indentation-style
+ (delq 'c-special-indent-hook
+ (copy-alist c-style-variables)))))
(mapc func varsyms)
;; Hooks must be handled specially
(if this-buf-only-p
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 88c389b4e5d..3845c2d55f0 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -280,6 +280,14 @@ anchoring position to indent the line in that case."
:type 'boolean
:group 'c)
+(defcustom c-warn-ids-with-dollar nil
+ "Fontify identifiers with a dollar character in font-lock-warn-face.
+This has effect only for languages in which `c-dollar-in-ids' is
+non-nil, e.g. C, C++, Objective C. It covers languages where
+\"$\" is permitted in ids \"informally\", but only by some compilers."
+ :type 'boolean
+ :group 'c)
+
(defcustom-c-stylevar c-basic-offset 4
"Amount of basic offset used by + and - symbols in `c-offsets-alist'.
Also used as the indentation step when `c-syntactic-indentation' is
@@ -1094,6 +1102,8 @@ can always override the use of `c-default-style' by making calls to
;; Anchor pos: Bol at the last line of previous construct.
(topmost-intro-cont . c-lineup-topmost-intro-cont)
;;Anchor pos: Bol at the topmost annotation line
+ (constraint-cont . +)
+ ;; Anchor pos: Boi of the starting requires/concept line
(annotation-top-cont . 0)
;;Anchor pos: Bol at the topmost annotation line
(annotation-var-cont . +)
@@ -1217,7 +1227,8 @@ can always override the use of `c-default-style' by making calls to
(incomposition . +)
;; Anchor pos: At the extern/namespace/etc block open brace if
;; it's at boi, otherwise boi at the keyword.
- (template-args-cont . (c-lineup-template-args +))
+ (template-args-cont . (c-lineup-template-args
+ c-lineup-template-args-indented-from-margin))
;; Anchor pos: Boi at the decl start. This might be changed;
;; the logical position is clearly the opening '<'.
(inlambda . 0)
@@ -1326,6 +1337,9 @@ Here is the current list of valid syntactic element symbols:
knr-argdecl -- Subsequent lines in a K&R C argument declaration.
topmost-intro -- The first line in a topmost construct definition.
topmost-intro-cont -- Topmost definition continuation lines.
+ constraint-cont -- Continuation line of a C++ requires clause (not
+ to be confused with a \"requires expression\") or
+ concept.
annotation-top-cont -- Topmost definition continuation line where only
annotations are on previous lines.
annotation-var-cont -- A continuation of a C (or like) statement where