From: Alan Mackenzie <acm@muc.de>
Date: Sun, 24 Aug 2014 20:50:11 +0000 (+0000)
Subject: Handle C++11's "auto" and "decltype" constructions.
X-Git-Tag: emacs-25.0.90~2635^2~679^2~442
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=4031fb7bac75dabf6c801721ef044a1d71fe6596;p=emacs.git

Handle C++11's "auto" and "decltype" constructions.
cc-engine.el (c-forward-type): Enhance to recognise and return 'decltype.
(c-forward-decl-or-cast-1): New let variables backup-kwd-sym,
prev-kwd-sym, new-style-auto.  Enhance to handle the new "auto" keyword.

cc-fonts.el (c-font-lock-declarations): Handle the "decltype" keyword.
(c-font-lock-c++-new): Handle "decltype" constructions.

cc-langs.el (c-auto-ops, c-auto-ops-re): New c-lang-defconsts/defvars.
(c-haskell-op, c-haskell-op-re): New c-lang-defconsts/defvars.
(c-typeof-kwds, c-typeof-key): New c-lang-defconsts/defvars.
(c-typeless-decl-kwds): Append "auto" onto the C++ value.
(c-not-decl-init-keywords): Also exclude c-typeof-kwds from value.
---

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 5b1c0b1b386..0b347f5a63a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,21 @@
 2014-08-24  Alan Mackenzie  <acm@muc.de>
 
+	Handle C++11's "auto" and "decltype" constructions.
+        * progmodes/cc-engine.el (c-forward-type): Enhance to recognise
+	and return 'decltype.
+        (c-forward-decl-or-cast-1): New let variables backup-kwd-sym,
+	prev-kwd-sym, new-style-auto.  Enhance to handle the new "auto"
+	keyword.
+        * progmodes/cc-fonts.el (c-font-lock-declarations): Handle the
+	"decltype" keyword.
+        (c-font-lock-c++-new): Handle "decltype" constructions.
+        * progmodes/cc-langs.el (c-auto-ops, c-auto-ops-re): New
+	c-lang-defconsts/defvars.
+        (c-haskell-op, c-haskell-op-re): New c-lang-defconsts/defvars.
+        (c-typeof-kwds, c-typeof-key): New c-lang-defconsts/defvars.
+        (c-typeless-decl-kwds): Append "auto" onto the C++ value.
+        (c-not-decl-init-keywords): Also exclude c-typeof-kwds from value.
+
 	Make ">>" act as double template ender in C++ Mode.
         * progmodes/cc-langs.el (c->-op-cont-tokens): New lang-const split
 	off from c->-op-cont-re.
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 8283bb38eae..9eb95f69c48 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -6286,7 +6286,8 @@ comment at the start of cc-engine.el for more info."
   ;;     `*-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 identifier that might be a type; or
+  ;;   o - 'maybe if it's an identfier that might be a type;
+  ;;   o - 'decltype if it's a decltype(variable) declaration; - 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.
@@ -6316,6 +6317,16 @@ comment at the start of cc-engine.el for more info."
 	(setq res 'prefix)))
 
     (cond
+     ((looking-at c-typeof-key) ; e.g. C++'s "decltype".
+      (goto-char (match-end 1))
+      (c-forward-syntactic-ws)
+      (setq res (and (eq (char-after) ?\()
+		     (c-safe (c-forward-sexp))
+		     'decltype))
+      (if res
+	  (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))
@@ -6442,7 +6453,7 @@ comment at the start of cc-engine.el for more info."
       ;; of these alter the classification of the found type, since
       ;; these operators typically are allowed in normal expressions
       ;; too.
-      (when c-opt-type-suffix-key
+      (when c-opt-type-suffix-key	; e.g. "..."
 	(while (looking-at c-opt-type-suffix-key)
 	  (goto-char (match-end 1))
 	  (c-forward-syntactic-ws)))
@@ -6654,6 +6665,13 @@ comment at the start of cc-engine.el for more info."
   ;;     Foo::Foo (int b) : Base (b) {}
   ;; car ^                ^ point
   ;;
+  ;;     auto foo = 5;
+  ;;      car ^   ^ point
+  ;;     auto cplusplus_11 (int a, char *b) -> decltype (bar):
+  ;;      car ^                             ^ point    
+  ;;   
+  ;;
+  ;;
   ;;   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
@@ -6719,6 +6737,10 @@ comment at the start of cc-engine.el for more info."
 	;; If `backup-at-type' is nil then the other variables have
 	;; undefined values.
 	backup-at-type backup-type-start backup-id-start
+	;; This stores `kwd-sym' of the symbol before the current one.
+	;; This is needed to distinguish the C++11 version of "auto" from
+	;; the pre C++11 meaning.
+	backup-kwd-sym
 	;; Set if we've found a specifier (apart from "typedef") that makes
 	;; the defined identifier(s) types.
 	at-type-decl
@@ -6727,6 +6749,10 @@ comment at the start of cc-engine.el for more info."
 	;; Set if we've found a specifier that can start a declaration
 	;; where there's no type.
 	maybe-typeless
+	;; Save the value of kwd-sym between loops of the "Check for a
+	;; type" loop.  Needed to distinguish a C++11 "auto" from a pre
+	;; C++11 one.
+	prev-kwd-sym
 	;; If a specifier is found that also can be a type prefix,
 	;; these flags are set instead of those above.  If we need to
 	;; back up an identifier, they are copied to the real flag
@@ -6744,6 +6770,8 @@ comment at the start of cc-engine.el for more info."
 	backup-if-not-cast
 	;; For casts, the return position.
 	cast-end
+	;; Have we got a new-style C++11 "auto"?
+	new-style-auto
 	;; Save `c-record-type-identifiers' and
 	;; `c-record-ref-identifiers' since ranges are recorded
 	;; speculatively and should be thrown away if it turns out
@@ -6762,11 +6790,12 @@ comment at the start of cc-engine.el for more info."
 	(let* ((start (point)) kwd-sym kwd-clause-end found-type)
 
 	  ;; Look for a specifier keyword clause.
-	  (when (or (looking-at c-prefix-spec-kwds-re)
+	  (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto
 		    (and (c-major-mode-is 'java-mode)
 			 (looking-at "@[A-Za-z0-9]+")))
-	    (if (looking-at c-typedef-key)
-		(setq at-typedef t))
+	    (save-match-data
+	      (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)
@@ -6774,6 +6803,12 @@ comment at the start of cc-engine.el for more info."
 
 	  (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 (and (c-major-mode-is 'c++-mode) ; C++11 style "auto"?
+		       (eq prev-kwd-sym (c-keyword-sym "auto"))
+		       (looking-at "[=(]")) ; FIXME!!! proper regexp.
+	      (setq new-style-auto t)
+	      (setq found-type nil)
+	      (goto-char start))	; position of foo in "auto foo"
 
 	    (when at-type
 	      ;; Got two identifiers with nothing but whitespace
@@ -6792,6 +6827,7 @@ comment at the start of cc-engine.el for more info."
 	    (setq backup-at-type at-type
 		  backup-type-start type-start
 		  backup-id-start id-start
+		  backup-kwd-sym kwd-sym
 		  at-type found-type
 		  type-start start
 		  id-start (point)
@@ -6847,6 +6883,7 @@ comment at the start of cc-engine.el for more info."
 		    ;; specifier keyword and we know we're in a
 		    ;; declaration.
 		    (setq at-decl-or-cast t)
+		    (setq prev-kwd-sym kwd-sym)
 
 		    (goto-char kwd-clause-end))))
 
@@ -7038,15 +7075,26 @@ comment at the start of cc-engine.el for more info."
 
 	(c-forward-syntactic-ws))
 
-      (when (and (or maybe-typeless backup-maybe-typeless)
-		 (not got-identifier)
-		 (not got-prefix)
-		 at-type)
+      (when (or (and new-style-auto
+		     (looking-at c-auto-ops-re))
+		(and (or maybe-typeless backup-maybe-typeless)
+		     (not got-identifier)
+		     (not got-prefix)
+		     at-type))
 	;; 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.
 	(c-fdoc-shift-type-backward))
 
+      ;; Prepare the "-> type;" for fontification later on.
+      (when (and new-style-auto
+		 (looking-at c-haskell-op-re))
+	(save-excursion
+	  (goto-char (match-end 0))
+	  (c-forward-syntactic-ws)
+	  (setq type-start (point))
+	  (setq at-type (c-forward-type))))
+
       (setq
        at-decl-or-cast
        (catch 'at-decl-or-cast
@@ -7371,6 +7419,7 @@ comment at the start of cc-engine.el for more info."
 	;; is a declaration.  Now we're being more defensive and prefer to
 	;; highlight things like "foo (bar);" as a declaration only if we're
 	;; inside an arglist that contains declarations.
+	;; CASE 19
 	(eq context 'decl))))
 
     ;; The point is now after the type decl expression.
@@ -7460,6 +7509,8 @@ comment at the start of cc-engine.el for more info."
 	;; interactive refontification.
 	(c-put-c-type-property (point) 'c-decl-arg-start))
 
+      ;; Record the type's coordinates in `c-record-type-identifiers' for
+      ;; later fontification.
       (when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
 		 ;; There seems no reason to exclude a token from
 		 ;; fontification just because it's "a known type that can't
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index ceb86b45fb1..c056091ca46 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1306,14 +1306,15 @@ casts and declarations are fontified.  Used on level 2 and higher."
 	      (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
 		     (setq context nil
 			   c-restricted-<>-arglists nil))
-		    ;; A control flow expression
+		    ;; A control flow expression or a decltype
 		    ((and (eq (char-before match-pos) ?\()
 			  (save-excursion
 			    (goto-char match-pos)
 			    (backward-char)
 			    (c-backward-token-2)
 			    (or (looking-at c-block-stmt-2-key)
-				(looking-at c-block-stmt-1-2-key))))
+				(looking-at c-block-stmt-1-2-key)
+				(looking-at c-typeof-key))))
 		     (setq context nil
 			   c-restricted-<>-arglists t))
 		    ;; Near BOB.
@@ -1513,7 +1514,7 @@ casts and declarations are fontified.  Used on level 2 and higher."
 			  (goto-char (match-end 0))
 			  (c-forward-syntactic-ws))
 			;; At a real declaration?
-			(if (memq (c-forward-type t) '(t known found))
+			(if (memq (c-forward-type t) '(t known found decltype))
 			    (progn
 			      (c-font-lock-declarators limit t is-typedef)
 			      nil)
@@ -2130,7 +2131,7 @@ need for `c-font-lock-extra-types'.")
 	      ;; Got two parenthesized expressions, so we have to look
 	      ;; closer at them to decide which is the type.  No need to
 	      ;; handle `c-record-ref-identifiers' since all references
-	      ;; has already been handled by other fontification rules.
+	      ;; have already been handled by other fontification rules.
 	      (let (expr1-res expr2-res)
 
 		(goto-char expr1-pos)
@@ -2165,6 +2166,9 @@ need for `c-font-lock-extra-types'.")
 		;; unusual than an initializer.
 		(cond ((memq expr1-res '(t known prefix)))
 		      ((memq expr2-res '(t known prefix)))
+		      ;; Presumably 'decltype's will be fontified elsewhere.
+		      ((eq expr1-res 'decltype))
+		      ((eq expr2-res 'decltype))
 		      ((eq expr1-res 'found)
 		       (let ((c-promote-possible-types t))
 			 (goto-char expr1-pos)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 2bf660a32eb..73b75dc671a 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -940,10 +940,13 @@ Note that operators like \".\" and \"->\" which in language references
 often are described as postfix operators are considered binary here,
 since CC Mode treats every identifier as an expression."
 
-  ;; There's currently no code in CC Mode that exploit all the info
+  ;; There's currently no code in CC Mode that exploits all the info
   ;; in this variable; precedence, associativity etc are present as a
   ;; preparation for future work.
 
+  ;; FIXME!!!  C++11's "auto" operators "=" and "->" need to go in here
+  ;; somewhere.  2012-03-24.
+
   t `(;; Preprocessor.
       ,@(when (c-lang-const c-opt-cpp-prefix)
 	  `((prefix "#"
@@ -1266,6 +1269,21 @@ operators."
 (c-lang-defvar c-stmt-delim-chars-with-comma
   (c-lang-const c-stmt-delim-chars-with-comma))
 
+(c-lang-defconst c-auto-ops
+  ;; Ops which signal C++11's new auto uses.
+  t nil
+  c++ '("=" "->"))
+(c-lang-defconst c-auto-ops-re
+  t (c-make-keywords-re nil (c-lang-const c-auto-ops)))
+(c-lang-defvar c-auto-ops-re (c-lang-const c-auto-ops-re))
+
+(c-lang-defconst c-haskell-op
+  ;; Op used in the new C++11 auto function definition, indicating type.
+  t nil
+  c++ '("->"))
+(c-lang-defconst c-haskell-op-re
+  t (c-make-keywords-re nil (c-lang-const c-haskell-op)))
+(c-lang-defvar c-haskell-op-re (c-lang-const c-haskell-op-re))
 
 ;;; Syntactic whitespace.
 
@@ -1673,6 +1691,18 @@ of a variable declaration."
   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-typeof-kwds
+  "Keywords followed by a parenthesized expression, which stands for
+the type of that expression."
+  t nil
+  c '("typeof")				; longstanding GNU C(++) extension.
+  c++ '("decltype" "typeof"))
+
+(c-lang-defconst c-typeof-key
+  ;; Adorned regexp matching `c-typeof-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-typeof-kwds)))
+(c-lang-defvar c-typeof-key (c-lang-const c-typeof-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
@@ -1856,6 +1886,7 @@ will be handled."
   ;; {...}").
   t    (append (c-lang-const c-class-decl-kwds)
 	       (c-lang-const c-brace-list-decl-kwds))
+  c++  (append (c-lang-const c-typeless-decl-kwds) '("auto")) ; C++11.
   ;; Note: "manages" for CORBA CIDL clashes with its presence on
   ;; `c-type-list-kwds' for IDL.
   idl  (append (c-lang-const c-typeless-decl-kwds)
@@ -2005,7 +2036,8 @@ one of `c-type-list-kwds', `c-ref-list-kwds',
   t (c-make-keywords-re t
       (set-difference (c-lang-const c-keywords)
 		      (append (c-lang-const c-type-start-kwds)
-			      (c-lang-const c-prefix-spec-kwds))
+			      (c-lang-const c-prefix-spec-kwds)
+			      (c-lang-const c-typeof-kwds))
 		      :test 'string-equal)))
 (c-lang-defvar c-not-decl-init-keywords
   (c-lang-const c-not-decl-init-keywords))