aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2016-08-15 11:52:32 +0000
committerAlan Mackenzie2016-08-15 11:52:32 +0000
commitce1ed9c8116e280c69f04a455176f6097ca0855c (patch)
tree75e3dffe10372dee3d44466eb8be58ebbacc1d3c
parent9c2ce57719d0db8ac0a01b65d7e8d7ccc3f2d6ca (diff)
downloademacs-ce1ed9c8116e280c69f04a455176f6097ca0855c.tar.gz
emacs-ce1ed9c8116e280c69f04a455176f6097ca0855c.zip
Handle C++11 lambda functions.
* lisp/progmodes/cc-engine.el (c-looking-at-inexpr-block): Enhance also to handle C++ lambda functions. (c-looking-at-c++-lambda-capture-list): New function. * lisp/progmodes/cc-fonts.el (c-font-lock-declarations): Recognize the parameter list of a lambda function and set `context' and `c-restricted-<>-arglists' suitably for it. (c-font-lock-c++-lambda-captures): New function. (c-complex-decl-matchers): Insert c-font-lock-c++-lambda-captures into it. * lisp/progmodes/cc-langs.el (c-pre-lambda-tokens, c-pre-lambda-tokens-re): New language constants/variables. (c-paren-nontype-kwds): Include "noexcept" in the C++ value. * lisp/progmodes/cc-mode.el (c-fl-decl-start): Handle being in a C++ lambda function capture list.
-rw-r--r--lisp/progmodes/cc-engine.el85
-rw-r--r--lisp/progmodes/cc-fonts.el101
-rw-r--r--lisp/progmodes/cc-langs.el24
-rw-r--r--lisp/progmodes/cc-mode.el46
4 files changed, 243 insertions, 13 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index e22b98dbc4d..4a29896b4a5 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -10005,12 +10005,27 @@ comment at the start of cc-engine.el for more info."
10005 ;; This function might do hidden buffer changes. 10005 ;; This function might do hidden buffer changes.
10006 10006
10007 (save-excursion 10007 (save-excursion
10008 (let ((res 'maybe) passed-paren 10008 (let ((res 'maybe) (passed-bracket-pairs 0) bracket-pos passed-paren
10009 haskell-op-pos
10009 (closest-lim (or containing-sexp lim (point-min))) 10010 (closest-lim (or containing-sexp lim (point-min)))
10010 ;; Look at the character after point only as a last resort 10011 ;; Look at the character after point only as a last resort
10011 ;; when we can't disambiguate. 10012 ;; when we can't disambiguate.
10012 (block-follows (and (eq (char-after) ?{) (point)))) 10013 (block-follows (and (eq (char-after) ?{) (point))))
10013 10014
10015 ;; Search for a C++11 "->" which suggests a lambda declaration.
10016 (when (and (c-major-mode-is 'c++-mode)
10017 (setq haskell-op-pos
10018 (save-excursion
10019 (while
10020 (progn
10021 (c-syntactic-skip-backward "^;=}>" closest-lim t)
10022 (and (eq (char-before) ?>)
10023 (c-backward-token-2)
10024 (not (looking-at c-haskell-op-re)))))
10025 (and (looking-at c-haskell-op-re)
10026 (point)))))
10027 (goto-char haskell-op-pos))
10028
10014 (while (and (eq res 'maybe) 10029 (while (and (eq res 'maybe)
10015 (progn (c-backward-syntactic-ws) 10030 (progn (c-backward-syntactic-ws)
10016 (> (point) closest-lim)) 10031 (> (point) closest-lim))
@@ -10048,6 +10063,11 @@ comment at the start of cc-engine.el for more info."
10048 (zerop (c-forward-token-2 1 t))) 10063 (zerop (c-forward-token-2 1 t)))
10049 (eq (char-after) ?\()))) 10064 (eq (char-after) ?\())))
10050 (cons 'inexpr-class (point)))) 10065 (cons 'inexpr-class (point))))
10066 ((c-keyword-member kw-sym 'c-paren-any-kwds) ; e.g. C++11 "throw" or "noexcept"
10067 (setq passed-paren nil)
10068 (setq passed-bracket-pairs 0)
10069 (setq bracket-pos nil)
10070 'maybe)
10051 ((c-keyword-member kw-sym 'c-inexpr-block-kwds) 10071 ((c-keyword-member kw-sym 'c-inexpr-block-kwds)
10052 (when (not passed-paren) 10072 (when (not passed-paren)
10053 (cons 'inexpr-statement (point)))) 10073 (cons 'inexpr-statement (point))))
@@ -10062,20 +10082,49 @@ comment at the start of cc-engine.el for more info."
10062 10082
10063 (if (looking-at "\\s(") 10083 (if (looking-at "\\s(")
10064 (if passed-paren 10084 (if passed-paren
10065 (if (and (eq passed-paren ?\[) 10085 (cond
10066 (eq (char-after) ?\[)) 10086 ((and (eq passed-paren ?\[)
10067 ;; Accept several square bracket sexps for 10087 (eq (char-after) ?\[)
10068 ;; Java array initializations. 10088 (not (eq (char-after (1+ (point))) ?\[))) ; C++ attribute.
10069 'maybe) 10089 ;; Accept several square bracket sexps for
10070 (setq passed-paren (char-after)) 10090 ;; Java array initializations.
10091 (setq passed-bracket-pairs (1+ passed-bracket-pairs))
10092 'maybe)
10093 ((and (eq passed-paren ?\()
10094 (eq (char-after) ?\[)
10095 (not (eq (char-after (1+ (point))) ?\[))
10096 (eq passed-bracket-pairs 0))
10097 ;; C++11 lambda function declaration
10098 (setq passed-bracket-pairs 1)
10099 (setq bracket-pos (point))
10100 'maybe)
10101 (t nil))
10102 (when (not (looking-at "\\[\\["))
10103 (setq passed-paren (char-after))
10104 (when (eq passed-paren ?\[)
10105 (setq passed-bracket-pairs 1)
10106 (setq bracket-pos (point))))
10071 'maybe) 10107 'maybe)
10072 'maybe)))) 10108 'maybe))))
10073 10109
10074 (if (eq res 'maybe) 10110 (if (eq res 'maybe)
10075 (when (and c-recognize-paren-inexpr-blocks 10111 (cond
10076 block-follows 10112 ((and (c-major-mode-is 'c++-mode)
10077 containing-sexp 10113 block-follows
10078 (eq (char-after containing-sexp) ?\()) 10114 (eq passed-bracket-pairs 1)
10115 (save-excursion
10116 (goto-char bracket-pos)
10117 (or (<= (point) (or lim (point-min)))
10118 (progn
10119 (c-backward-token-2 1 nil lim)
10120 (and
10121 (not (c-on-identifier))
10122 (not (looking-at c-opt-op-identifier-prefix)))))))
10123 (cons 'inlambda bracket-pos))
10124 ((and c-recognize-paren-inexpr-blocks
10125 block-follows
10126 containing-sexp
10127 (eq (char-after containing-sexp) ?\())
10079 (goto-char containing-sexp) 10128 (goto-char containing-sexp)
10080 (if (or (save-excursion 10129 (if (or (save-excursion
10081 (c-backward-syntactic-ws lim) 10130 (c-backward-syntactic-ws lim)
@@ -10089,7 +10138,7 @@ comment at the start of cc-engine.el for more info."
10089 (and c-special-brace-lists 10138 (and c-special-brace-lists
10090 (c-looking-at-special-brace-list))) 10139 (c-looking-at-special-brace-list)))
10091 nil 10140 nil
10092 (cons 'inexpr-statement (point)))) 10141 (cons 'inexpr-statement (point)))))
10093 10142
10094 res)))) 10143 res))))
10095 10144
@@ -10115,6 +10164,18 @@ comment at the start of cc-engine.el for more info."
10115 paren-state) 10164 paren-state)
10116 containing-sexp))))) 10165 containing-sexp)))))
10117 10166
10167(defun c-looking-at-c++-lambda-capture-list ()
10168 ;; Return non-nil if we're at the opening "[" of the capture list of a C++
10169 ;; lambda function, nil otherwise.
10170 (and
10171 (eq (char-after) ?\[)
10172 (not (eq (char-before) ?\[))
10173 (not (eq (char-after (1+ (point))) ?\[))
10174 (save-excursion
10175 (or (eq (c-backward-token-2 1) 1)
10176 (looking-at c-pre-lambda-tokens-re)))
10177 (not (c-in-literal))))
10178
10118(defun c-at-macro-vsemi-p (&optional pos) 10179(defun c-at-macro-vsemi-p (&optional pos)
10119 ;; Is there a "virtual semicolon" at POS or point? 10180 ;; Is there a "virtual semicolon" at POS or point?
10120 ;; (See cc-defs.el for full details of "virtual semicolons".) 10181 ;; (See cc-defs.el for full details of "virtual semicolons".)
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index b45686c81b0..ae18d0a9436 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1242,6 +1242,20 @@ casts and declarations are fontified. Used on level 2 and higher."
1242 ((eq type 'c-decl-arg-start) 1242 ((eq type 'c-decl-arg-start)
1243 (setq context 'decl 1243 (setq context 'decl
1244 c-restricted-<>-arglists nil)) 1244 c-restricted-<>-arglists nil))
1245 ;; Inside a C++11 lambda function arglist.
1246 ((and (c-major-mode-is 'c++-mode)
1247 (eq (char-before match-pos) ?\()
1248 (save-excursion
1249 (goto-char match-pos)
1250 (c-backward-token-2)
1251 (and
1252 (c-safe (goto-char (scan-sexps (point) -1)))
1253 (c-looking-at-c++-lambda-capture-list))))
1254 (setq context 'decl
1255 c-restricted-<>-arglists nil)
1256 (c-put-char-property (1- match-pos) 'c-type
1257 'c-decl-arg-start))
1258
1245 ;; Inside an angle bracket arglist. 1259 ;; Inside an angle bracket arglist.
1246 ((or (eq type 'c-<>-arg-sep) 1260 ((or (eq type 'c-<>-arg-sep)
1247 (eq (char-before match-pos) ?<)) 1261 (eq (char-before match-pos) ?<))
@@ -1583,6 +1597,90 @@ casts and declarations are fontified. Used on level 2 and higher."
1583 (setq raw-id (match-string-no-properties 2))))))))) 1597 (setq raw-id (match-string-no-properties 2)))))))))
1584 nil) 1598 nil)
1585 1599
1600(defun c-font-lock-c++-lambda-captures (limit)
1601 ;; Fontify the lambda capture component of C++ lambda declarations.
1602 ;;
1603 ;; This function will be called from font-lock for a region bounded by POINT
1604 ;; and LIMIT, as though it were to identify a keyword for
1605 ;; font-lock-keyword-face. It always returns NIL to inhibit this and
1606 ;; prevent a repeat invocation. See elisp/lispref page "Search-based
1607 ;; Fontification".
1608 (let (mode capture-default id-start id-end declaration sub-begin sub-end)
1609 (while (and (< (point) limit)
1610 (search-forward "[" limit t))
1611 (when (progn (backward-char)
1612 (prog1
1613 (c-looking-at-c++-lambda-capture-list)
1614 (forward-char)))
1615 (c-forward-syntactic-ws)
1616 (setq mode (and (memq (char-after) '(?= ?&))
1617 (char-after)))
1618 ;; Is the first element of the list a bare "=" or "&"?
1619 (when mode
1620 (forward-char)
1621 (c-forward-syntactic-ws)
1622 (if (memq (char-after) '(?, ?\]))
1623 (progn
1624 (setq capture-default mode)
1625 (when (eq (char-after) ?,)
1626 (forward-char)
1627 (c-forward-syntactic-ws)))
1628 (c-backward-token-2)))
1629
1630 ;; Go round the following loop once per captured item.
1631 (while (and (not (eq (char-after) ?\]))
1632 (< (point) limit))
1633 (if (eq (char-after) ?&)
1634 (progn (setq mode ?&)
1635 (forward-char)
1636 (c-forward-syntactic-ws))
1637 (setq mode ?=))
1638 (if (c-on-identifier)
1639 (progn
1640 (setq id-start (point))
1641 (forward-char)
1642 (c-end-of-current-token)
1643 (setq id-end (point))
1644 (c-forward-syntactic-ws)
1645
1646 (setq declaration (eq (char-after) ?=))
1647 (when declaration
1648 (forward-char) ; over "="
1649 (c-forward-syntactic-ws)
1650 (setq sub-begin (point)))
1651 (if (or (and (< (point) limit)
1652 (c-syntactic-re-search-forward "," limit t t))
1653 (and (c-go-up-list-forward nil limit)
1654 (eq (char-before) ?\])))
1655 (backward-char)
1656 (goto-char limit))
1657 (when declaration
1658 (save-excursion
1659 (setq sub-end (point))
1660 (goto-char sub-begin)
1661 (c-font-lock-c++-lambda-captures sub-end)))
1662
1663 (c-put-font-lock-face id-start id-end
1664 (cond
1665 (declaration
1666 'font-lock-variable-name-face)
1667 ((and capture-default
1668 (eq mode capture-default))
1669 'font-lock-warning-face)
1670 ((eq mode ?=) font-lock-constant-face)
1671 (t 'font-lock-variable-name-face))))
1672 (c-syntactic-re-search-forward "," limit 'bound t))
1673
1674 (c-forward-syntactic-ws)
1675 (when (eq (char-after) ?,)
1676 (forward-char)
1677 (c-forward-syntactic-ws)))
1678
1679 (setq capture-default nil)
1680 (forward-char)))) ; over the terminating "]".
1681 nil)
1682
1683
1586(c-lang-defconst c-simple-decl-matchers 1684(c-lang-defconst c-simple-decl-matchers
1587 "Simple font lock matchers for types and declarations. These are used 1685 "Simple font lock matchers for types and declarations. These are used
1588on level 2 only and so aren't combined with `c-complex-decl-matchers'." 1686on level 2 only and so aren't combined with `c-complex-decl-matchers'."
@@ -1700,6 +1798,9 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
1700 ,@(when (c-lang-const c-recognize-<>-arglists) 1798 ,@(when (c-lang-const c-recognize-<>-arglists)
1701 `(c-font-lock-<>-arglists)) 1799 `(c-font-lock-<>-arglists))
1702 1800
1801 ,@(when (c-major-mode-is 'c++-mode)
1802 `(c-font-lock-c++-lambda-captures))
1803
1703 ;; The first two rules here mostly find occurrences that 1804 ;; The first two rules here mostly find occurrences that
1704 ;; `c-font-lock-declarations' has found already, but not 1805 ;; `c-font-lock-declarations' has found already, but not
1705 ;; declarations containing blocks in the type (see note below). 1806 ;; declarations containing blocks in the type (see note below).
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index ec894f619a8..934186da7bd 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -474,6 +474,7 @@ so that all identifiers are recognized as words.")
474 ;; The value here may be a list of functions or a single function. 474 ;; The value here may be a list of functions or a single function.
475 t nil 475 t nil
476 c++ '(c-extend-region-for-CPP 476 c++ '(c-extend-region-for-CPP
477; c-before-after-change-extend-region-for-lambda-capture ; doesn't seem needed.
477 c-before-change-check-raw-strings 478 c-before-change-check-raw-strings
478 c-before-change-check-<>-operators 479 c-before-change-check-<>-operators
479 c-depropertize-CPP 480 c-depropertize-CPP
@@ -517,6 +518,7 @@ parameters \(point-min) and \(point-max).")
517 c-change-expand-fl-region) 518 c-change-expand-fl-region)
518 c++ '(c-depropertize-new-text 519 c++ '(c-depropertize-new-text
519 c-extend-font-lock-region-for-macros 520 c-extend-font-lock-region-for-macros
521; c-before-after-change-extend-region-for-lambda-capture ; doens't seem needed.
520 c-before-after-change-digit-quote 522 c-before-after-change-digit-quote
521 c-after-change-re-mark-raw-strings 523 c-after-change-re-mark-raw-strings
522 c-neutralize-syntax-in-and-mark-CPP 524 c-neutralize-syntax-in-and-mark-CPP
@@ -1360,6 +1362,25 @@ operators."
1360 t '(";" "{" "}")) 1362 t '(";" "{" "}"))
1361(c-lang-defvar c-pre-start-tokens (c-lang-const c-pre-start-tokens)) 1363(c-lang-defvar c-pre-start-tokens (c-lang-const c-pre-start-tokens))
1362 1364
1365(c-lang-defconst c-pre-lambda-tokens
1366 "List of tokens which may precede a lambda declaration.
1367In C++ this is something like \"[a,b] (foo, bar) -> int { ... };\".
1368Currently (2016-08) only used in C++ mode."
1369 t (c--set-difference
1370 (c--delete-duplicates
1371 (append (c-lang-const c-operator-list)
1372 (c-lang-const c-other-op-syntax-tokens)))
1373 (append
1374 '("#" "%:" "??=" "##" "%:%:" "??=??=" "::" "." "->"
1375 "]" "<:" ":>" "??(" "??)" "??-" "new" "delete"
1376 ")" ".*" "->*" "??'" "??!" "??!??!" "??!=" "??'=")
1377 '("<%" "%>" "<:" ":>" "%:" "%:%:" "#" "##" "::" "..."))
1378 :test #'string-equal))
1379
1380(c-lang-defconst c-pre-lambda-tokens-re
1381 ;; Regexp matching any token in the list `c-pre-lambda-tokens'.
1382 t (regexp-opt (c-lang-const c-pre-lambda-tokens)))
1383(c-lang-defvar c-pre-lambda-tokens-re (c-lang-const c-pre-lambda-tokens-re))
1363 1384
1364;;; Syntactic whitespace. 1385;;; Syntactic whitespace.
1365 1386
@@ -2284,7 +2305,8 @@ contain type identifiers."
2284 (c c++) '(;; GCC extension. 2305 (c c++) '(;; GCC extension.
2285 "__attribute__" 2306 "__attribute__"
2286 ;; MSVC extension. 2307 ;; MSVC extension.
2287 "__declspec")) 2308 "__declspec")
2309 c++ (append (c-lang-const c-paren-nontype-kwds) '("noexcept")))
2288 2310
2289(c-lang-defconst c-paren-nontype-key 2311(c-lang-defconst c-paren-nontype-key
2290 t (c-make-keywords-re t (c-lang-const c-paren-nontype-kwds))) 2312 t (c-make-keywords-re t (c-lang-const c-paren-nontype-kwds)))
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 07476013354..f630b053edc 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1142,6 +1142,38 @@ Note that the style variables are always made local to the buffer."
1142 (goto-char try-end) 1142 (goto-char try-end)
1143 (setq num-begin (point))))) 1143 (setq num-begin (point)))))
1144 1144
1145;; The following doesn't seem needed at the moment (2016-08-15).
1146;; (defun c-before-after-change-extend-region-for-lambda-capture
1147;; (_beg _end &optional _old-len)
1148;; ;; In C++ Mode, extend the region (c-new-BEG c-new-END) to cover any lambda
1149;; ;; function capture lists we happen to be inside. This function is expected
1150;; ;; to be called both as a before-change and after change function.
1151;; ;;
1152;; ;; Note that these things _might_ be nested, with a capture list looking
1153;; ;; like:
1154;; ;;
1155;; ;; [ ...., &foo = [..](){...}(..), ... ]
1156;; ;;
1157;; ;; . What a wonderful language is C++. ;-)
1158;; (c-save-buffer-state (paren-state pos)
1159;; (goto-char c-new-BEG)
1160;; (setq paren-state (c-parse-state))
1161;; (while (setq pos (c-pull-open-brace paren-state))
1162;; (goto-char pos)
1163;; (when (c-looking-at-c++-lambda-capture-list)
1164;; (setq c-new-BEG (min c-new-BEG pos))
1165;; (if (c-go-list-forward)
1166;; (setq c-new-END (max c-new-END (point))))))
1167
1168;; (goto-char c-new-END)
1169;; (setq paren-state (c-parse-state))
1170;; (while (setq pos (c-pull-open-brace paren-state))
1171;; (goto-char pos)
1172;; (when (c-looking-at-c++-lambda-capture-list)
1173;; (setq c-new-BEG (min c-new-BEG pos))
1174;; (if (c-go-list-forward)
1175;; (setq c-new-END (max c-new-END (point))))))))
1176
1145(defun c-before-change (beg end) 1177(defun c-before-change (beg end)
1146 ;; Function to be put on `before-change-functions'. Primarily, this calls 1178 ;; Function to be put on `before-change-functions'. Primarily, this calls
1147 ;; the language dependent `c-get-state-before-change-functions'. It is 1179 ;; the language dependent `c-get-state-before-change-functions'. It is
@@ -1329,12 +1361,24 @@ Note that the style variables are always made local to the buffer."
1329 ;; lock context (etc.) fontification. 1361 ;; lock context (etc.) fontification.
1330 (let ((lit-start (c-literal-start)) 1362 (let ((lit-start (c-literal-start))
1331 (new-pos pos) 1363 (new-pos pos)
1364 capture-opener
1332 bod-lim bo-decl) 1365 bod-lim bo-decl)
1333 (goto-char (c-point 'bol new-pos)) 1366 (goto-char (c-point 'bol new-pos))
1334 (when lit-start ; Comment or string. 1367 (when lit-start ; Comment or string.
1335 (goto-char lit-start)) 1368 (goto-char lit-start))
1336 (setq bod-lim (c-determine-limit 500)) 1369 (setq bod-lim (c-determine-limit 500))
1337 1370
1371 ;; In C++ Mode, first check if we are within a (possibly nested) lambda
1372 ;; form capture list.
1373 (when (c-major-mode-is 'c++-mode)
1374 (let ((paren-state (c-parse-state))
1375 opener)
1376 (save-excursion
1377 (while (setq opener (c-pull-open-brace paren-state))
1378 (goto-char opener)
1379 (if (c-looking-at-c++-lambda-capture-list)
1380 (setq capture-opener (point)))))))
1381
1338 (while 1382 (while
1339 ;; Go to a less nested declaration each time round this loop. 1383 ;; Go to a less nested declaration each time round this loop.
1340 (and 1384 (and
@@ -1361,6 +1405,8 @@ Note that the style variables are always made local to the buffer."
1361 c-<-as-paren-syntax))))) 1405 c-<-as-paren-syntax)))))
1362 (not (bobp))) 1406 (not (bobp)))
1363 (backward-char)) ; back over (, [, <. 1407 (backward-char)) ; back over (, [, <.
1408 (when (and capture-opener (< capture-opener new-pos))
1409 (setq new-pos capture-opener))
1364 (and (/= new-pos pos) new-pos))) 1410 (and (/= new-pos pos) new-pos)))
1365 1411
1366(defun c-change-expand-fl-region (_beg _end _old-len) 1412(defun c-change-expand-fl-region (_beg _end _old-len)