changeset 110888:fb9b207b7488

Enhance fontification of declarators to take account of the presence/absence of "typedef". cc-engine.el (c-forward-type): New &optional param "brace-block-too". (c-forward-decl-or-cast-1): cdr of return value now indicates the presence of either or both of a "struct"-like keyword and "typedef". cc-fonts.el (c-complex-decl-matchers): Remove the heuristic fontification of declarators which follow a "}". (c-font-lock-declarations): Fontify declarators according to the presence/absence of "typedef". cc-langs.el (c-typedef-kwds c-typedef-key): New lang variable for "typedef". (c-typedef-decl-key): New lang variable built from c-typedef-decl-kwds.
author Alan Mackenzie <acm@muc.de>
date Sat, 09 Oct 2010 19:58:28 +0000
parents 951b5214e939
children 50d2da482ed7
files lisp/ChangeLog lisp/progmodes/cc-engine.el lisp/progmodes/cc-fonts.el lisp/progmodes/cc-langs.el
diffstat 4 files changed, 311 insertions(+), 148 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sat Oct 09 12:39:42 2010 -0700
+++ b/lisp/ChangeLog	Sat Oct 09 19:58:28 2010 +0000
@@ -1,3 +1,24 @@
+2010-10-09  Alan Mackenzie  <acm@muc.de>
+
+	Enhance fontification of declarators to take account of the
+	presence/absence of "typedef".
+
+	* cc-engine.el (c-forward-type): New &optional param
+	"brace-block-too".
+	(c-forward-decl-or-cast-1): cdr of return value now indicates the
+	presence of either or both of a "struct"-like keyword and
+	"typedef".
+
+	* cc-fonts.el (c-complex-decl-matchers): Remove the heuristic
+	fontification of declarators which follow a "}".
+	(c-font-lock-declarations): Fontify declarators according to the
+	presence/absence of "typedef".
+
+	* cc-langs.el (c-typedef-kwds c-typedef-key): New lang variable
+	for "typedef".
+	(c-typedef-decl-key): New lang variable built from
+	c-typedef-decl-kwds.
+
 2010-10-09  Lars Magne Ingebrigtsen  <larsi@gnus.org>
 
 	* ibuffer.el (ibuffer-mode-map): Don't redefine the cursor keys,
--- a/lisp/progmodes/cc-engine.el	Sat Oct 09 12:39:42 2010 -0700
+++ b/lisp/progmodes/cc-engine.el	Sat Oct 09 19:58:28 2010 +0000
@@ -5646,17 +5646,23 @@
 
 (defun c-forward-name ()
   ;; Move forward over a complete name if at the beginning of one,
-  ;; stopping at the next following token.  If the point is not at
-  ;; something that are recognized as name then it stays put.  A name
-  ;; could be something as simple as "foo" in C or something as
+  ;; 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.
+  ;;
+  ;; 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<> ::
   ;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short
   ;; int>::*volatile const" in C++ (this function is actually little
   ;; more than a `looking-at' call in all modes except those that,
-  ;; like C++, have `c-recognize-<>-arglists' set).  Return nil if no
-  ;; name is found, 'template if it's an identifier ending with an
-  ;; angle bracket arglist, 'operator of it's an operator identifier,
-  ;; or t if it's some other kind of name.
+  ;; like C++, have `c-recognize-<>-arglists' set).
+  ;;
+  ;; Return
+  ;; o - nil if no name is found;
+  ;; o - 'template if it's an identifier ending with an angle bracket
+  ;;   arglist;
+  ;; o - 'operator of it's an operator identifier;
+  ;; o - t if it's some other kind of name.
   ;;
   ;; This function records identifier ranges on
   ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
@@ -5808,16 +5814,28 @@
     (goto-char pos)
     res))
 
-(defun c-forward-type ()
+(defun c-forward-type (&optional brace-block-too)
   ;; Move forward over a type spec if at the beginning of one,
-  ;; stopping at the next following token.  Return t if it's a known
-  ;; type that can't be a name or other expression, 'known if it's an
-  ;; otherwise known type (according to `*-font-lock-extra-types'),
-  ;; 'prefix if it's a known prefix of a type, 'found if it's a type
-  ;; that matches one in `c-found-types', 'maybe if it's an identfier
-  ;; that might be a type, or nil if it can't be a type (the point
-  ;; isn't moved then).  The point is assumed to be at the beginning
-  ;; of a token.
+  ;; stopping at the next following token.  The keyword "typedef"
+  ;; isn't part of a type spec here.
+  ;;
+  ;; BRACE-BLOCK-TOO, when non-nil, means move over the brace block in
+  ;; constructs like "struct foo {...} bar ;" or "struct {...} bar;".
+  ;; The current (2009-03-10) intention is to convert all uses of
+  ;; `c-forward-type' to call with this parameter set, then to
+  ;; eliminate it.
+  ;;
+  ;; Return
+  ;;   o - t if it's a known type that can't be a name or other
+  ;;     expression;
+  ;;   o - 'known if it's an otherwise known type (according to
+  ;;     `*-font-lock-extra-types');
+  ;;   o - 'prefix if it's a known prefix of a type;
+  ;;   o - 'found if it's a type that matches one in `c-found-types';
+  ;;   o - 'maybe if it's an identfier that might be a type; or
+  ;;   o -  nil if it can't be a type (the point isn't moved then).
+  ;;
+  ;; The point is assumed to be at the beginning of a token.
   ;;
   ;; Note that this function doesn't skip past the brace definition
   ;; that might be considered part of the type, e.g.
@@ -5836,32 +5854,39 @@
 
     ;; Skip leading type modifiers.  If any are found we know it's a
     ;; prefix of a type.
-    (when c-opt-type-modifier-key
+    (when c-opt-type-modifier-key ; e.g. "const" "volatile", but NOT "typedef"
       (while (looking-at c-opt-type-modifier-key)
 	(goto-char (match-end 1))
 	(c-forward-syntactic-ws)
 	(setq res 'prefix)))
 
     (cond
-     ((looking-at c-type-prefix-key)
-      ;; Looking at a keyword that prefixes a type identifier,
-      ;; e.g. "class".
+     ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT
+				     ; "typedef".
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
       (setq pos (point))
-      (if (memq (setq name-res (c-forward-name)) '(t template))
-	  (progn
-	    (when (eq name-res t)
-	      ;; In many languages the name can be used without the
-	      ;; prefix, so we add it to `c-found-types'.
-	      (c-add-type pos (point))
-	      (when (and c-record-type-identifiers
-			 c-last-identifier-range)
-		(c-record-type-id c-last-identifier-range)))
-	    (setq res t))
-	;; Invalid syntax.
-	(goto-char start)
-	(setq res nil)))
+
+      (setq name-res (c-forward-name))
+      (setq res (not (null name-res)))
+      (when (eq name-res t)
+	;; In many languages the name can be used without the
+	;; prefix, so we add it to `c-found-types'.
+	(c-add-type pos (point))
+	(when (and c-record-type-identifiers
+		   c-last-identifier-range)
+	  (c-record-type-id c-last-identifier-range)))
+      (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)
+	(setq res t))
+      (unless res (goto-char start)))	; invalid syntax
 
      ((progn
 	(setq pos nil)
@@ -5951,14 +5976,13 @@
 	     (setq res nil)))))
 
     (when res
-      ;; Skip trailing type modifiers.  If any are found we know it's
+      ;; Skip trailing type modifiers.	If any are found we know it's
       ;; a type.
       (when c-opt-type-modifier-key
-	(while (looking-at c-opt-type-modifier-key)
+	(while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
 	  (goto-char (match-end 1))
 	  (c-forward-syntactic-ws)
 	  (setq res t)))
-
       ;; Step over any type suffix operator.  Do not let the existence
       ;; of these alter the classification of the found type, since
       ;; these operators typically are allowed in normal expressions
@@ -5968,7 +5992,7 @@
 	  (goto-char (match-end 1))
 	  (c-forward-syntactic-ws)))
 
-      (when c-opt-type-concat-key
+      (when c-opt-type-concat-key	; Only/mainly for pike.
 	;; Look for a trailing operator that concatenates the type
 	;; with a following one, and if so step past that one through
 	;; a recursive call.  Note that we don't record concatenated
@@ -6119,11 +6143,15 @@
   ;;      car ^                                     ^ point
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
-  ;;
-  ;;   The cdr of the return value is non-nil iff a `c-typedef-decl-kwds'
-  ;;   specifier (e.g. class, struct, enum, typedef) is found in the
-  ;;   declaration, i.e. the declared identifier(s) are types.
-  ;;
+  ;; 
+  ;;   The cdr of the return value is non-nil when a
+  ;;   `c-typedef-decl-kwds' specifier is found in the declaration.
+  ;;   Specifically it is a dotted pair (A . B) where B is t when a
+  ;;   `c-typedef-kwds' ("typedef") is present, and A is t when some
+  ;;   other `c-typedef-decl-kwds' (e.g. class, struct, enum)
+  ;;   specifier is present.  I.e., (some of) the declared
+  ;;   identifier(s) are types.
+  ;; 
   ;; If a cast is parsed:
   ;;
   ;;   The point is left at the first token after the closing paren of
@@ -6181,9 +6209,11 @@
 	;; If `backup-at-type' is nil then the other variables have
 	;; undefined values.
 	backup-at-type backup-type-start backup-id-start
-	;; Set if we've found a specifier that makes the defined
-	;; identifier(s) types.
+	;; Set if we've found a specifier (apart from "typedef") that makes
+	;; the defined identifier(s) types.
 	at-type-decl
+	;; Set if we've a "typedef" keyword.
+	at-typedef
 	;; Set if we've found a specifier that can start a declaration
 	;; where there's no type.
 	maybe-typeless
@@ -6223,12 +6253,14 @@
 
 	  ;; Look for a specifier keyword clause.
 	  (when (looking-at c-prefix-spec-kwds-re)
+	    (if (looking-at c-typedef-key)
+		(setq at-typedef t))
 	    (setq kwd-sym (c-keyword-sym (match-string 1)))
 	    (save-excursion
 	      (c-forward-keyword-clause 1)
 	      (setq kwd-clause-end (point))))
 
-	  (when (setq found-type (c-forward-type))
+	  (when (setq found-type (c-forward-type t)) ; brace-block-too
 	    ;; Found a known or possible type or a prefix of a known type.
 
 	    (when at-type
@@ -6293,6 +6325,8 @@
 			  (setq backup-maybe-typeless t)))
 
 		    (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
+		      ;; This test only happens after we've scanned a type.
+		      ;; So, with valid syntax, kwd-sym can't be 'typedef.
 		      (setq at-type-decl t))
 		    (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
 		      (setq maybe-typeless t))
@@ -6892,7 +6926,9 @@
 	    (goto-char type-start)
 	    (c-forward-type))))
 
-      (cons id-start at-type-decl))
+      (cons id-start
+	    (and (or at-type-decl at-typedef)
+		 (cons at-type-decl at-typedef))))
 
      (t
       ;; False alarm.  Restore the recorded ranges.
--- a/lisp/progmodes/cc-fonts.el	Sat Oct 09 12:39:42 2010 -0700
+++ b/lisp/progmodes/cc-fonts.el	Sat Oct 09 19:58:28 2010 +0000
@@ -289,7 +289,7 @@
     ;; bit of the overhead compared to a real matcher.  The main reason
     ;; is however to pass the real search limit to the anchored
     ;; matcher(s), since most (if not all) font-lock implementations
-    ;; arbitrarily limits anchored matchers to the same line, and also
+    ;; arbitrarily limit anchored matchers to the same line, and also
     ;; to insulate against various other irritating differences between
     ;; the different (X)Emacs font-lock packages.
     ;;
@@ -310,7 +310,7 @@
     ;; covered by the font-lock context.)
 
     ;; Note: Replace `byte-compile' with `eval' to debug the generated
-    ;; lambda easier.
+    ;; lambda more easily.
     (byte-compile
      `(lambda (limit)
 	(let (;; The font-lock package in Emacs is known to clobber
@@ -721,16 +721,26 @@
 
   ;; Clear the list of found types if we start from the start of the
   ;; buffer, to make it easier to get rid of misspelled types and
-  ;; variables that has gotten recognized as types in malformed code.
+  ;; variables that have gotten recognized as types in malformed code.
   (when (bobp)
     (c-clear-found-types))
 
-  ;; Clear the c-type char properties in the region to recalculate
-  ;; them properly. This is necessary e.g. to handle constructs that
-  ;; might been required as declarations temporarily during editing.
-  ;; The interesting properties are anyway those put on the closest
-  ;; token before the region.
-  (c-clear-char-properties (point) limit 'c-type)
+  ;; Clear the c-type char properties which mark the region, to recalculate
+  ;; them properly.  The most interesting properties are those put on the
+  ;; closest token before the region.
+  (save-excursion
+    (let ((pos (point)))
+      (c-backward-syntactic-ws)
+      (c-clear-char-properties
+       (if (and (not (bobp))
+		(memq (c-get-char-property (1- (point)) 'c-type)
+		      '(c-decl-arg-start
+			c-decl-end
+			c-decl-id-start
+			c-decl-type-start)))
+	   (1- (point))
+	 pos)
+       limit 'c-type)))
 
   ;; Update `c-state-cache' to the beginning of the region.  This will
   ;; make `c-beginning-of-syntax' go faster when it's used later on,
@@ -739,6 +749,8 @@
 
   ;; Check if the fontified region starts inside a declarator list so
   ;; that `c-font-lock-declarators' should be called at the start.
+  ;; The declared identifiers are font-locked correctly as types, if
+  ;; that is what they are.
   (let ((prop (save-excursion
 		(c-backward-syntactic-ws)
 		(unless (bobp)
@@ -831,12 +843,19 @@
   nil)
 
 (defun c-font-lock-declarators (limit list types)
-  ;; Assuming the point is at the start of a declarator in a
-  ;; declaration, fontify it.  If LIST is non-nil, fontify also all
-  ;; following declarators in a comma separated list (e.g.  "foo" and
-  ;; "bar" in "int foo = 17, bar;").  Stop at LIMIT.  If TYPES is
-  ;; non-nil, fontify all identifiers as types.  Nil is always
-  ;; returned.
+  ;; Assuming the point is at the start of a declarator in a declaration,
+  ;; fontify the identifier it declares.  (If TYPES is set, it does this via
+  ;; the macro `c-fontify-types-and-refs'.)
+  ;;
+  ;; If LIST is non-nil, also fontify the ids in any following declarators in
+  ;; a comma separated list (e.g.  "foo" and "*bar" in "int foo = 17, *bar;");
+  ;; additionally, mark the commas with c-type property 'c-decl-id-start or
+  ;; 'c-decl-type-start (according to TYPES).  Stop at LIMIT.
+  ;;
+  ;; If TYPES is non-nil, fontify all identifiers as types.
+  ;;
+  ;; Nil is always returned.  The function leaves point at the delimiter after
+  ;; the last declarator it processes.
   ;;
   ;; This function might do hidden buffer changes.
 
@@ -848,18 +867,31 @@
        c-last-identifier-range
        (separator-prop (if types 'c-decl-type-start 'c-decl-id-start)))
 
-    (while (and
+    ;; The following `while' fontifies a single declarator id each time round.
+    ;; It loops only when LIST is non-nil.
+    (while
+	;; Inside the following "condition form", we move forward over the
+	;; declarator's identifier up as far as any opening bracket (for array
+	;; size) or paren (for parameters of function-type) or brace (for
+	;; array/struct initialisation) or "=" or terminating delimiter
+	;; (e.g. "," or ";" or "}").
+	(and
 	    pos
 	    (< (point) limit)
 
+	    ;; The following form moves forward over the declarator's
+	    ;; identifier (and what precedes it), returning t.  If there
+	    ;; wasn't one, it returns nil, terminating the `while'.
 	    (let (got-identifier)
 	      (setq paren-depth 0)
-	      ;; Skip over type decl prefix operators.  (Note similar
-	      ;; code in `c-forward-decl-or-cast-1'.)
+	      ;; Skip over type decl prefix operators, one for each iteration
+	      ;; of the while.  These are, e.g. "*" in "int *foo" or "(" and
+	      ;; "*" in "int (*foo) (void)" (Note similar code in
+	      ;; `c-forward-decl-or-cast-1'.)
 	      (while (and (looking-at c-type-decl-prefix-key)
 			  (if (and (c-major-mode-is 'c++-mode)
-				   (match-beginning 2))
-			      ;; If the second submatch matches in C++ then
+				   (match-beginning 3))
+			      ;; If the third submatch matches in C++ then
 			      ;; we're looking at an identifier that's a
 			      ;; prefix only if it specifies a member pointer.
 			      (progn
@@ -882,7 +914,7 @@
 		  (goto-char (match-end 1)))
 		(c-forward-syntactic-ws))
 
-	      ;; If we didn't pass the identifier above already, do it now.
+	      ;; If we haven't passed the identifier already, do it now.
 	      (unless got-identifier
 		(setq id-start (point))
 		(c-forward-name))
@@ -890,12 +922,14 @@
 
 	      (/= id-end pos))
 
-	    ;; Skip out of the parens surrounding the identifier.
+	    ;; Skip out of the parens surrounding the identifier.  If closing
+	    ;; parens are missing, this form returns nil.
 	    (or (= paren-depth 0)
 		(c-safe (goto-char (scan-lists (point) 1 paren-depth))))
 
 	    (<= (point) limit)
 
+	    ;; Skip over any trailing bit, such as "__attribute__".
 	    (progn
 	      (when (looking-at c-decl-hangon-key)
 		(c-forward-keyword-clause 1))
@@ -936,7 +970,7 @@
 				id-face)))
 
       (goto-char next-pos)
-      (setq pos nil)
+      (setq pos nil)	      ; So as to terminate the enclosing `while' form.
       (when list
 	;; Jump past any initializer or function prototype to see if
 	;; there's a ',' to continue at.
@@ -944,11 +978,11 @@
 	(cond ((eq id-face 'font-lock-function-name-face)
 	       ;; Skip a parenthesized initializer (C++) or a function
 	       ;; prototype.
-	       (if (c-safe (c-forward-sexp 1) t)
+	       (if (c-safe (c-forward-sexp 1) t) ; over the parameter list.
 		   (c-forward-syntactic-ws limit)
-		 (goto-char limit)))
+		 (goto-char limit)))	; unbalanced parens
 
-	      (got-init
+	      (got-init	; "=" sign OR opening "(", "[", or "{"
 	       ;; Skip an initializer expression.  If we're at a '='
 	       ;; then accept a brace list directly after it to cope
 	       ;; with array initializers.  Otherwise stop at braces
@@ -956,7 +990,7 @@
 	       (and (if (and (eq got-init ?=)
 			     (= (c-forward-token-2 1 nil limit) 0)
 			     (looking-at "{"))
-			(c-safe (c-forward-sexp) t)
+			(c-safe (c-forward-sexp) t) ; over { .... }
 		      t)
 		    ;; FIXME: Should look for c-decl-end markers here;
 		    ;; we might go far into the following declarations
@@ -971,7 +1005,7 @@
 	  (c-put-char-property (point) 'c-type separator-prop)
 	  (forward-char)
 	  (c-forward-syntactic-ws limit)
-	  (setq pos (point))))))
+	  (setq pos (point))))))     ; acts to make the `while' form continue.
   nil)
 
 (defconst c-font-lock-maybe-decl-faces
@@ -984,27 +1018,29 @@
 	font-lock-keyword-face))
 
 (defun c-font-lock-declarations (limit)
+  ;; Fontify all the declarations, casts and labels from the point to LIMIT.
+  ;; Assumes that strings and comments have been fontified already.
+  ;;
   ;; 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".
   ;;
-  ;; Fontify all the declarations, casts and labels from the point to LIMIT.
-  ;; Assumes that strings and comments have been fontified already.
-  ;;
   ;; This function might do hidden buffer changes.
 
   ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
 
   (save-restriction
-    (let (;; The position where `c-find-decl-spots' stopped.
+    (let (;; The position where `c-find-decl-spots' last stopped.
 	  start-pos
-	  ;; 'decl if we're in an arglist containing declarations (but
-	  ;; if `c-recognize-paren-inits' is set it might also be an
-	  ;; initializer arglist), '<> if the arglist is of angle
-	  ;; bracket type, 'arglist if it's some other arglist, or nil
-	  ;; if not in an arglist at all.
+	  ;; o - 'decl if we're in an arglist containing declarations
+	  ;;   (but if `c-recognize-paren-inits' is set it might also be
+	  ;;   an initializer arglist);
+	  ;; o - '<> if the arglist is of angle bracket type;
+	  ;; o - 'arglist if it's some other arglist;
+	  ;; o - nil, if not in an arglist at all.  This includes the
+	  ;;   parenthesised condition which follows "if", "while", etc.
 	  context
 	  ;; The position of the next token after the closing paren of
 	  ;; the last detected cast.
@@ -1082,57 +1118,106 @@
 	      ;; can't start a declaration.
 	      t
 
-	    ;; Set `context'.  Look for "<" for the sake of C++-style template
-	    ;; arglists.
-	    (if (memq (char-before match-pos) '(?\( ?, ?\[ ?<))
+	    ;; Set `context' and `c-restricted-<>-arglists'.  Look for
+	    ;; "<" for the sake of C++-style template arglists.
+	    ;; Ignore "(" when it's part of a control flow construct
+	    ;; (e.g. "for (").
+	    (let ((type (and (> match-pos (point-min))
+			     (c-get-char-property (1- match-pos) 'c-type))))
+	      (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
+		     (setq context nil
+			   c-restricted-<>-arglists nil))
+		    ;; A control flow expression
+		    ((and (eq (char-before match-pos) ?\()
+			  (save-excursion
+			    (goto-char match-pos)
+			    (backward-char)
+			    (c-backward-token-2)
+			    (looking-at c-block-stmt-2-key)))
+		     (setq context nil
+			   c-restricted-<>-arglists t))
+		    ;; Near BOB.
+		    ((<= match-pos (point-min))
+		     (setq context 'arglist
+			   c-restricted-<>-arglists t))
+		    ;; Got a cached hit in a declaration arglist.
+		    ((eq type 'c-decl-arg-start)
+		     (setq context 'decl
+			   c-restricted-<>-arglists nil))
+		    ;; Inside an angle bracket arglist.
+		    ((or (eq type 'c-<>-arg-sep)
+			 (eq (char-before match-pos) ?<))
+		     (setq context '<>
+			   c-restricted-<>-arglists nil))
+		    ;; Got a cached hit in some other type of arglist.
+		    (type
+		     (setq context 'arglist
+			   c-restricted-<>-arglists t))
+		    ((if inside-macro
+			 (< match-pos max-type-decl-end-before-token)
+		       (< match-pos max-type-decl-end))
+		     ;; The point is within the range of a previously
+		     ;; encountered type decl expression, so the arglist
+		     ;; is probably one that contains declarations.
+		     ;; However, if `c-recognize-paren-inits' is set it
+		     ;; might also be an initializer arglist.
+		     (setq context 'decl
+			   c-restricted-<>-arglists nil)
+		     ;; The result of this check is cached with a char
+		     ;; property on the match token, so that we can look
+		     ;; it up again when refontifying single lines in a
+		     ;; multiline declaration.
+		     (c-put-char-property (1- match-pos)
+					  'c-type 'c-decl-arg-start))
+		    (t (setq context 'arglist
+			     c-restricted-<>-arglists t))))
 
-		;; Find out the type of the arglist.
-		(if (<= match-pos (point-min))
-		    (setq context 'arglist)
-		  (let ((type (c-get-char-property (1- match-pos) 'c-type)))
-		    (cond ((eq type 'c-decl-arg-start)
-			   ;; Got a cached hit in a declaration arglist.
-			   (setq context 'decl))
-			  ((or (eq type 'c-<>-arg-sep)
-			       (eq (char-before match-pos) ?<))
-			   ;; Inside an angle bracket arglist.
-			   (setq context '<>))
-			  (type
-			   ;; Got a cached hit in some other type of arglist.
-			   (setq context 'arglist))
-			  ((if inside-macro
-			       (< match-pos max-type-decl-end-before-token)
-			     (< match-pos max-type-decl-end))
-			   ;; The point is within the range of a previously
-			   ;; encountered type decl expression, so the arglist
-			   ;; is probably one that contains declarations.
-			   ;; However, if `c-recognize-paren-inits' is set it
-			   ;; might also be an initializer arglist.
-			   (setq context 'decl)
-			   ;; The result of this check is cached with a char
-			   ;; property on the match token, so that we can look
-			   ;; it up again when refontifying single lines in a
-			   ;; multiline declaration.
-			   (c-put-char-property (1- match-pos)
-						'c-type 'c-decl-arg-start))
-			  (t
-			   (setq context 'arglist)))))
+	    ;; Check we haven't missed a preceding "typedef".
+	    (when (not (looking-at c-typedef-key))
+	      (c-backward-syntactic-ws)
+	      (c-backward-token-2)
+	      (or (looking-at c-typedef-key)
+		  (goto-char start-pos)))
 
-	      (setq context nil))
-
-	    ;; If we're in a normal arglist context we don't want to
-	    ;; recognize commas in nested angle bracket arglists since
-	    ;; those commas could be part of our own arglist.
-	    (setq c-restricted-<>-arglists (and c-recognize-<>-arglists
-						(eq context 'arglist))
-
-		  ;; Now analyze the construct.
-		  decl-or-cast (c-forward-decl-or-cast-1
+	    ;; Now analyze the construct.
+	    (setq decl-or-cast (c-forward-decl-or-cast-1
 				match-pos context last-cast-end))
 
 	    (if (not decl-or-cast)
-		;; False alarm.  Return t to go on to the next check.
-		t
+		;; Are we at a declarator?
+		;; Try to go back to the declaration to check this.
+		(let (paren-state bod-res lim encl-pos is-typedef)
+		  (goto-char start-pos)
+		  (save-excursion
+		    (setq lim (and (c-syntactic-skip-backward "^;" nil t)
+				   (point))))
+		  (save-excursion
+		    (setq bod-res (car (c-beginning-of-decl-1 lim)))
+		    (if (and (eq bod-res 'same)
+			     (progn
+			       (c-backward-syntactic-ws)
+			       (eq (char-before) ?\})))
+			(c-beginning-of-decl-1 lim))
+		    ;; We're now putatively at the declaration.
+		    (setq paren-state (c-parse-state))
+		    ;; At top level or inside a "{"?
+		    (if (or (not (setq encl-pos
+				       (c-most-enclosing-brace paren-state)))
+			    (eq (char-after encl-pos) ?\{))
+			(progn
+			  (when (looking-at c-typedef-key) ; "typedef"
+			    (setq is-typedef t)
+			    (goto-char (match-end 0))
+			    (c-forward-syntactic-ws))
+			  ;; At a real declaration?
+			  (if (memq (c-forward-type t) '(t known found))
+			      (progn
+				(c-font-lock-declarators limit t is-typedef)
+				nil)
+		      ;; False alarm.  Return t to go on to the next check.
+			    (goto-char start-pos)
+			    t))
+		      t)))
 
 	      (if (eq decl-or-cast 'cast)
 		  ;; Save the position after the previous cast so we can feed
@@ -1296,7 +1381,7 @@
   "Complex font lock matchers for types and declarations.  Used on level
 3 and higher."
 
-  ;; Note: This code in this form dumps a number of funtions into the
+  ;; Note: This code in this form dumps a number of functions into the
   ;; resulting constant, `c-matchers-3'.  At run time, font lock will call
   ;; each of them as a "FUNCTION" (see Elisp page "Search-based
   ;; Fontification").  The font lock region is delimited by POINT and the
@@ -1348,7 +1433,7 @@
 	   `(,(concat "\\<\\(" re "\\)\\>")
 	     1 'font-lock-type-face)))
 
-      ;; Fontify types preceded by `c-type-prefix-kwds'.
+      ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct").
       ,@(when (c-lang-const c-type-prefix-kwds)
 	  `((,(byte-compile
 	       `(lambda (limit)
@@ -1396,23 +1481,25 @@
       ;; override it if it turns out to be an new declaration, but
       ;; it will be wrong if it's an expression (see the test
       ;; decls-8.cc).
-      ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
-	  `((,(c-make-font-lock-search-function
-	       (concat "}"
-		       (c-lang-const c-single-line-syntactic-ws)
-		       "\\("		; 1 + c-single-line-syntactic-ws-depth
-		       (c-lang-const c-type-decl-prefix-key)
-		       "\\|"
-		       (c-lang-const c-symbol-key)
-		       "\\)")
-	       `((c-font-lock-declarators limit t nil)
-		 (progn
-		   (c-put-char-property (match-beginning 0) 'c-type
-					'c-decl-id-start)
-		   (goto-char (match-beginning
-			       ,(1+ (c-lang-const
-				     c-single-line-syntactic-ws-depth)))))
-		 (goto-char (match-end 0)))))))
+;;       ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
+;; 	  `((,(c-make-font-lock-search-function
+;; 	       (concat "}"
+;; 		       (c-lang-const c-single-line-syntactic-ws)
+;; 		       "\\("		; 1 + c-single-line-syntactic-ws-depth
+;; 		       (c-lang-const c-type-decl-prefix-key)
+;; 		       "\\|"
+;; 		       (c-lang-const c-symbol-key)
+;; 		       "\\)")
+;; 	       `((c-font-lock-declarators limit t nil) ; That `nil' says use `font-lock-variable-name-face';
+;; 					; `t' would mean `font-lock-function-name-face'.
+;; 		 (progn
+;; 		   (c-put-char-property (match-beginning 0) 'c-type
+;; 					'c-decl-id-start)
+;; ;					'c-decl-type-start)
+;; 		   (goto-char (match-beginning
+;; 			       ,(1+ (c-lang-const
+;; 				     c-single-line-syntactic-ws-depth)))))
+;; 		 (goto-char (match-end 0)))))))
 
       ;; Fontify the type in C++ "new" expressions.
       ,@(when (c-major-mode-is 'c++-mode)
@@ -1660,6 +1747,10 @@
 ;;; C++.
 
 (defun c-font-lock-c++-new (limit)
+  ;; FIXME!!!  Put in a comment about the context of this function's
+  ;; invocation.  I think it's called as an ANCHORED-MATCHER within an
+  ;; ANCHORED-HIGHLIGHTER.  (2007/2/10).
+  ;;
   ;; Assuming point is after a "new" word, check that it isn't inside
   ;; a string or comment, and if so try to fontify the type in the
   ;; allocation expression.  Nil is always returned.
--- a/lisp/progmodes/cc-langs.el	Sat Oct 09 12:39:42 2010 -0700
+++ b/lisp/progmodes/cc-langs.el	Sat Oct 09 19:58:28 2010 +0000
@@ -1565,6 +1565,17 @@
 	    ;; In CORBA PSDL:
 	    "strong"))
 
+(c-lang-defconst c-typedef-kwds
+  "Prefix keyword\(s\) like \"typedef\" which make a type declaration out
+of a variable declaration."
+  t        '("typedef")
+  (awk idl java) nil)
+
+(c-lang-defconst c-typedef-key
+  ;; Adorned regexp matching `c-typedef-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-typedef-kwds)))
+(c-lang-defvar c-typedef-key (c-lang-const c-typedef-key))
+
 (c-lang-defconst c-type-prefix-kwds
   "Keywords where the following name - if any - is a type name, and
 where the keyword together with the symbol works as a type in
@@ -1731,6 +1742,10 @@
   ;; types in IDL since they only can occur in "raises" specs.
   idl  (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil)))
 
+(c-lang-defconst c-typedef-decl-key
+  t  (c-make-keywords-re t (c-lang-const c-typedef-decl-kwds)))
+(c-lang-defvar c-typedef-decl-key (c-lang-const c-typedef-decl-key))
+
 (c-lang-defconst c-typeless-decl-kwds
   "Keywords introducing declarations where the \(first) identifier
 \(declarator) follows directly after the keyword, without any type.