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
openSUSE Build Service is sponsored by