Commit 4031fb7b authored by Alan Mackenzie's avatar Alan Mackenzie
Browse files

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.
parent 66bb9533
2014-08-24 Alan Mackenzie <acm@muc.de> 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. Make ">>" act as double template ender in C++ Mode.
* progmodes/cc-langs.el (c->-op-cont-tokens): New lang-const split * progmodes/cc-langs.el (c->-op-cont-tokens): New lang-const split
off from c->-op-cont-re. off from c->-op-cont-re.
......
...@@ -6286,7 +6286,8 @@ comment at the start of cc-engine.el for more info." ...@@ -6286,7 +6286,8 @@ comment at the start of cc-engine.el for more info."
;; `*-font-lock-extra-types'); ;; `*-font-lock-extra-types');
;; o - 'prefix if it's a known prefix of a type; ;; 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 - '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). ;; 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. ;; 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." ...@@ -6316,6 +6317,16 @@ comment at the start of cc-engine.el for more info."
(setq res 'prefix))) (setq res 'prefix)))
(cond (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 ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT
; "typedef". ; "typedef".
(goto-char (match-end 1)) (goto-char (match-end 1))
...@@ -6442,7 +6453,7 @@ comment at the start of cc-engine.el for more info." ...@@ -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 ;; of these alter the classification of the found type, since
;; these operators typically are allowed in normal expressions ;; these operators typically are allowed in normal expressions
;; too. ;; too.
(when c-opt-type-suffix-key (when c-opt-type-suffix-key ; e.g. "..."
(while (looking-at c-opt-type-suffix-key) (while (looking-at c-opt-type-suffix-key)
(goto-char (match-end 1)) (goto-char (match-end 1))
(c-forward-syntactic-ws))) (c-forward-syntactic-ws)))
...@@ -6654,6 +6665,13 @@ comment at the start of cc-engine.el for more info." ...@@ -6654,6 +6665,13 @@ comment at the start of cc-engine.el for more info."
;; Foo::Foo (int b) : Base (b) {} ;; Foo::Foo (int b) : Base (b) {}
;; car ^ ^ point ;; 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 ;; The cdr of the return value is non-nil when a
;; `c-typedef-decl-kwds' specifier is found in the declaration. ;; `c-typedef-decl-kwds' specifier is found in the declaration.
;; Specifically it is a dotted pair (A . B) where B is t when a ;; 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." ...@@ -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 ;; If `backup-at-type' is nil then the other variables have
;; undefined values. ;; undefined values.
backup-at-type backup-type-start backup-id-start 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 ;; Set if we've found a specifier (apart from "typedef") that makes
;; the defined identifier(s) types. ;; the defined identifier(s) types.
at-type-decl at-type-decl
...@@ -6727,6 +6749,10 @@ comment at the start of cc-engine.el for more info." ...@@ -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 ;; Set if we've found a specifier that can start a declaration
;; where there's no type. ;; where there's no type.
maybe-typeless 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, ;; If a specifier is found that also can be a type prefix,
;; these flags are set instead of those above. If we need to ;; these flags are set instead of those above. If we need to
;; back up an identifier, they are copied to the real flag ;; 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." ...@@ -6744,6 +6770,8 @@ comment at the start of cc-engine.el for more info."
backup-if-not-cast backup-if-not-cast
;; For casts, the return position. ;; For casts, the return position.
cast-end cast-end
;; Have we got a new-style C++11 "auto"?
new-style-auto
;; Save `c-record-type-identifiers' and ;; Save `c-record-type-identifiers' and
;; `c-record-ref-identifiers' since ranges are recorded ;; `c-record-ref-identifiers' since ranges are recorded
;; speculatively and should be thrown away if it turns out ;; 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." ...@@ -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) (let* ((start (point)) kwd-sym kwd-clause-end found-type)
;; Look for a specifier keyword clause. ;; 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) (and (c-major-mode-is 'java-mode)
(looking-at "@[A-Za-z0-9]+"))) (looking-at "@[A-Za-z0-9]+")))
(save-match-data
(if (looking-at c-typedef-key) (if (looking-at c-typedef-key)
(setq at-typedef t)) (setq at-typedef t)))
(setq kwd-sym (c-keyword-sym (match-string 1))) (setq kwd-sym (c-keyword-sym (match-string 1)))
(save-excursion (save-excursion
(c-forward-keyword-clause 1) (c-forward-keyword-clause 1)
...@@ -6774,6 +6803,12 @@ comment at the start of cc-engine.el for more info." ...@@ -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 (when (setq found-type (c-forward-type t)) ; brace-block-too
;; Found a known or possible type or a prefix of a known type. ;; 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 (when at-type
;; Got two identifiers with nothing but whitespace ;; Got two identifiers with nothing but whitespace
...@@ -6792,6 +6827,7 @@ comment at the start of cc-engine.el for more info." ...@@ -6792,6 +6827,7 @@ comment at the start of cc-engine.el for more info."
(setq backup-at-type at-type (setq backup-at-type at-type
backup-type-start type-start backup-type-start type-start
backup-id-start id-start backup-id-start id-start
backup-kwd-sym kwd-sym
at-type found-type at-type found-type
type-start start type-start start
id-start (point) id-start (point)
...@@ -6847,6 +6883,7 @@ comment at the start of cc-engine.el for more info." ...@@ -6847,6 +6883,7 @@ comment at the start of cc-engine.el for more info."
;; specifier keyword and we know we're in a ;; specifier keyword and we know we're in a
;; declaration. ;; declaration.
(setq at-decl-or-cast t) (setq at-decl-or-cast t)
(setq prev-kwd-sym kwd-sym)
(goto-char kwd-clause-end)))) (goto-char kwd-clause-end))))
...@@ -7038,15 +7075,26 @@ comment at the start of cc-engine.el for more info." ...@@ -7038,15 +7075,26 @@ comment at the start of cc-engine.el for more info."
(c-forward-syntactic-ws)) (c-forward-syntactic-ws))
(when (and (or maybe-typeless backup-maybe-typeless) (when (or (and new-style-auto
(looking-at c-auto-ops-re))
(and (or maybe-typeless backup-maybe-typeless)
(not got-identifier) (not got-identifier)
(not got-prefix) (not got-prefix)
at-type) at-type))
;; Have found no identifier but `c-typeless-decl-kwds' has ;; Have found no identifier but `c-typeless-decl-kwds' has
;; matched so we know we're inside a declaration. The ;; matched so we know we're inside a declaration. The
;; preceding type must be the identifier instead. ;; preceding type must be the identifier instead.
(c-fdoc-shift-type-backward)) (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 (setq
at-decl-or-cast at-decl-or-cast
(catch 'at-decl-or-cast (catch 'at-decl-or-cast
...@@ -7371,6 +7419,7 @@ comment at the start of cc-engine.el for more info." ...@@ -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 ;; is a declaration. Now we're being more defensive and prefer to
;; highlight things like "foo (bar);" as a declaration only if we're ;; highlight things like "foo (bar);" as a declaration only if we're
;; inside an arglist that contains declarations. ;; inside an arglist that contains declarations.
;; CASE 19
(eq context 'decl)))) (eq context 'decl))))
;; The point is now after the type decl expression. ;; The point is now after the type decl expression.
...@@ -7460,6 +7509,8 @@ comment at the start of cc-engine.el for more info." ...@@ -7460,6 +7509,8 @@ comment at the start of cc-engine.el for more info."
;; interactive refontification. ;; interactive refontification.
(c-put-c-type-property (point) 'c-decl-arg-start)) (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)) (when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
;; There seems no reason to exclude a token from ;; There seems no reason to exclude a token from
;; fontification just because it's "a known type that can't ;; fontification just because it's "a known type that can't
......
...@@ -1306,14 +1306,15 @@ casts and declarations are fontified. Used on level 2 and higher." ...@@ -1306,14 +1306,15 @@ casts and declarations are fontified. Used on level 2 and higher."
(cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<))) (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
(setq context nil (setq context nil
c-restricted-<>-arglists nil)) c-restricted-<>-arglists nil))
;; A control flow expression ;; A control flow expression or a decltype
((and (eq (char-before match-pos) ?\() ((and (eq (char-before match-pos) ?\()
(save-excursion (save-excursion
(goto-char match-pos) (goto-char match-pos)
(backward-char) (backward-char)
(c-backward-token-2) (c-backward-token-2)
(or (looking-at c-block-stmt-2-key) (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 (setq context nil
c-restricted-<>-arglists t)) c-restricted-<>-arglists t))
;; Near BOB. ;; Near BOB.
...@@ -1513,7 +1514,7 @@ casts and declarations are fontified. Used on level 2 and higher." ...@@ -1513,7 +1514,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(goto-char (match-end 0)) (goto-char (match-end 0))
(c-forward-syntactic-ws)) (c-forward-syntactic-ws))
;; At a real declaration? ;; At a real declaration?
(if (memq (c-forward-type t) '(t known found)) (if (memq (c-forward-type t) '(t known found decltype))
(progn (progn
(c-font-lock-declarators limit t is-typedef) (c-font-lock-declarators limit t is-typedef)
nil) nil)
...@@ -2130,7 +2131,7 @@ need for `c-font-lock-extra-types'.") ...@@ -2130,7 +2131,7 @@ need for `c-font-lock-extra-types'.")
;; Got two parenthesized expressions, so we have to look ;; Got two parenthesized expressions, so we have to look
;; closer at them to decide which is the type. No need to ;; closer at them to decide which is the type. No need to
;; handle `c-record-ref-identifiers' since all references ;; 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) (let (expr1-res expr2-res)
(goto-char expr1-pos) (goto-char expr1-pos)
...@@ -2165,6 +2166,9 @@ need for `c-font-lock-extra-types'.") ...@@ -2165,6 +2166,9 @@ need for `c-font-lock-extra-types'.")
;; unusual than an initializer. ;; unusual than an initializer.
(cond ((memq expr1-res '(t known prefix))) (cond ((memq expr1-res '(t known prefix)))
((memq expr2-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) ((eq expr1-res 'found)
(let ((c-promote-possible-types t)) (let ((c-promote-possible-types t))
(goto-char expr1-pos) (goto-char expr1-pos)
......
...@@ -940,10 +940,13 @@ Note that operators like \".\" and \"->\" which in language references ...@@ -940,10 +940,13 @@ Note that operators like \".\" and \"->\" which in language references
often are described as postfix operators are considered binary here, often are described as postfix operators are considered binary here,
since CC Mode treats every identifier as an expression." 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 ;; in this variable; precedence, associativity etc are present as a
;; preparation for future work. ;; preparation for future work.
;; FIXME!!! C++11's "auto" operators "=" and "->" need to go in here
;; somewhere. 2012-03-24.
t `(;; Preprocessor. t `(;; Preprocessor.
,@(when (c-lang-const c-opt-cpp-prefix) ,@(when (c-lang-const c-opt-cpp-prefix)
`((prefix "#" `((prefix "#"
...@@ -1266,6 +1269,21 @@ operators." ...@@ -1266,6 +1269,21 @@ operators."
(c-lang-defvar c-stmt-delim-chars-with-comma (c-lang-defvar c-stmt-delim-chars-with-comma
(c-lang-const 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. ;;; Syntactic whitespace.
...@@ -1673,6 +1691,18 @@ of a variable declaration." ...@@ -1673,6 +1691,18 @@ of a variable declaration."
t (c-make-keywords-re t (c-lang-const 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-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 (c-lang-defconst c-type-prefix-kwds
"Keywords where the following name - if any - is a type name, and "Keywords where the following name - if any - is a type name, and
where the keyword together with the symbol works as a type in where the keyword together with the symbol works as a type in
...@@ -1856,6 +1886,7 @@ will be handled." ...@@ -1856,6 +1886,7 @@ will be handled."
;; {...}"). ;; {...}").
t (append (c-lang-const c-class-decl-kwds) t (append (c-lang-const c-class-decl-kwds)
(c-lang-const c-brace-list-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 ;; Note: "manages" for CORBA CIDL clashes with its presence on
;; `c-type-list-kwds' for IDL. ;; `c-type-list-kwds' for IDL.
idl (append (c-lang-const c-typeless-decl-kwds) idl (append (c-lang-const c-typeless-decl-kwds)
...@@ -2005,7 +2036,8 @@ one of `c-type-list-kwds', `c-ref-list-kwds', ...@@ -2005,7 +2036,8 @@ one of `c-type-list-kwds', `c-ref-list-kwds',
t (c-make-keywords-re t t (c-make-keywords-re t
(set-difference (c-lang-const c-keywords) (set-difference (c-lang-const c-keywords)
(append (c-lang-const c-type-start-kwds) (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))) :test 'string-equal)))
(c-lang-defvar c-not-decl-init-keywords (c-lang-defvar c-not-decl-init-keywords
(c-lang-const c-not-decl-init-keywords)) (c-lang-const c-not-decl-init-keywords))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment