aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2018-01-28 17:53:07 +0000
committerAlan Mackenzie2018-01-28 17:53:07 +0000
commita718e1593ae7332fafe734f880181e2d8ecc34df (patch)
tree0c5fba91628217df4bba90f25ee6dace9572f901
parent36c8128e740ce91af10769bef46a21a72dafc56c (diff)
downloademacs-a718e1593ae7332fafe734f880181e2d8ecc34df.tar.gz
emacs-a718e1593ae7332fafe734f880181e2d8ecc34df.zip
Fix some errors in c-display-defun-name when the type is "struct {..}", etc.
Also fix some errors with c-display-defun-name when there are nested classes. * lisp/progmodes/cc-cmds.el (c-in-function-trailer-p): Deal with a struct {..} being merely the type of a function. (c-where-wrt-brace-construct): Deal with a struct {..} being merely the type of a function. Rearrange the order of some Lisp forms. Insert a check for c-protection-key ("private", etc.) alongside the checking for a label. (c-defun-name-1): New function extracted form c-defun-name, which works within the existing restriction. Don't regard 'at-function-end as being within the defun any more. Recognize "struct", etc., with the new c-defun-type-name-decl-key rather than c-type-prefix-key. Make the recognition of a normal function more accurate. (c-defun-name): Part left after extracting the above function. It now just widens and calls c-defun-name-1. (c-declaration-limits-1): New function extracted from c-declaration-limits, which works within the existing restriction. Move LIM back one block to account for the possibility of struct {..} as a function type. Check we're not inside a declaration without braces. (c-declaration-limits): Part left after extracting the above function. It now just narrows to an enclosing decl block and calls c-declaration-limits-1. (c-defun-name-and-limits): New function which identifies the name and limits of the most nested enclosing declaration or macro. (c-display-defun-name): Use c-defun-name-and-limits rather than two separate functions (which didn't always agree on which function). * lisp/progmodes/cc-engine.el (c-beginning-of-statement-1): If we have struct {..} as the type of a function, go back over this, too. * lisp/progmodes/cc-langs.el (c-defun-type-name-decl-kwds) (c-defun-type-name-decl-key): New lang const/var.
-rw-r--r--lisp/progmodes/cc-cmds.el548
-rw-r--r--lisp/progmodes/cc-engine.el11
-rw-r--r--lisp/progmodes/cc-langs.el12
3 files changed, 329 insertions, 242 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 0c4829e103f..31cf0b11596 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1397,6 +1397,16 @@ No indentation or other \"electric\" behavior is performed."
1397 (not (eq (char-before) ?_)) 1397 (not (eq (char-before) ?_))
1398 (c-syntactic-re-search-forward "[;=([{]" eo-block t t t) 1398 (c-syntactic-re-search-forward "[;=([{]" eo-block t t t)
1399 (eq (char-before) ?\{) 1399 (eq (char-before) ?\{)
1400 ;; Exclude the entire "struct {...}" being the type of a
1401 ;; function being declared.
1402 (not
1403 (and
1404 (c-go-up-list-forward)
1405 (eq (char-before) ?})
1406 (progn (c-forward-syntactic-ws)
1407 (c-syntactic-re-search-forward
1408 "[;=([{]" nil t t t))
1409 (eq (char-before) ?\()))
1400 bod))))) 1410 bod)))))
1401 1411
1402(defun c-where-wrt-brace-construct () 1412(defun c-where-wrt-brace-construct ()
@@ -1434,7 +1444,11 @@ No indentation or other \"electric\" behavior is performed."
1434 ((and (not least-enclosing) 1444 ((and (not least-enclosing)
1435 (consp paren-state) 1445 (consp paren-state)
1436 (consp (car paren-state)) 1446 (consp (car paren-state))
1437 (eq start (cdar paren-state))) 1447 (eq start (cdar paren-state))
1448 (not
1449 (progn
1450 (c-forward-syntactic-ws)
1451 (looking-at c-symbol-start))))
1438 'at-function-end) 1452 'at-function-end)
1439 (t 1453 (t
1440 ;; Find the start of the current declaration. NOTE: If we're in the 1454 ;; Find the start of the current declaration. NOTE: If we're in the
@@ -1450,6 +1464,18 @@ No indentation or other \"electric\" behavior is performed."
1450"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)"))) 1464"\\([;#]\\|\\'\\|\\s(\\|\\s)\\|\\s\"\\|\\s\\\\|\\s$\\|\\s<\\|\\s>\\|\\s!\\)")))
1451 (forward-char)) 1465 (forward-char))
1452 (setq kluge-start (point)) 1466 (setq kluge-start (point))
1467 ;; First approximation as to whether the current "header" we're in is
1468 ;; one followed by braces.
1469 (setq brace-decl-p
1470 (save-excursion
1471 (and (c-syntactic-re-search-forward "[;{]" nil t t)
1472 (or (eq (char-before) ?\{)
1473 (and c-recognize-knr-p
1474 ;; Might have stopped on the
1475 ;; ';' in a K&R argdecl. In
1476 ;; that case the declaration
1477 ;; should contain a block.
1478 (c-in-knr-argdecl))))))
1453 (setq decl-result 1479 (setq decl-result
1454 (car (c-beginning-of-decl-1 1480 (car (c-beginning-of-decl-1
1455 ;; NOTE: If we're in a K&R region, this might be the start 1481 ;; NOTE: If we're in a K&R region, this might be the start
@@ -1460,17 +1486,9 @@ No indentation or other \"electric\" behavior is performed."
1460 (c-safe-position least-enclosing paren-state))))) 1486 (c-safe-position least-enclosing paren-state)))))
1461 1487
1462 ;; Has the declaration we've gone back to got braces? 1488 ;; Has the declaration we've gone back to got braces?
1463 (or (eq decl-result 'label) 1489 (if (or (eq decl-result 'label)
1464 (setq brace-decl-p 1490 (looking-at c-protection-key))
1465 (save-excursion 1491 (setq brace-decl-p nil))
1466 (and (c-syntactic-re-search-forward "[;{]" nil t t)
1467 (or (eq (char-before) ?\{)
1468 (and c-recognize-knr-p
1469 ;; Might have stopped on the
1470 ;; ';' in a K&R argdecl. In
1471 ;; that case the declaration
1472 ;; should contain a block.
1473 (c-in-knr-argdecl)))))))
1474 1492
1475 (cond 1493 (cond
1476 ((or (eq decl-result 'label) ; e.g. "private:" or invalid syntax. 1494 ((or (eq decl-result 'label) ; e.g. "private:" or invalid syntax.
@@ -1817,251 +1835,298 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
1817 (c-keep-region-active) 1835 (c-keep-region-active)
1818 (= arg 0)))) 1836 (= arg 0))))
1819 1837
1820(defun c-defun-name () 1838(defun c-defun-name-1 ()
1821 "Return the name of the current defun, or NIL if there isn't one. 1839 "Return the name of the current defun, at the current narrowing,
1822\"Defun\" here means a function, or other top level construct 1840or NIL if there isn't one. \"Defun\" here means a function, or
1823with a brace block." 1841other top level construct with a brace block."
1824 (c-save-buffer-state 1842 (c-save-buffer-state
1825 (beginning-of-defun-function end-of-defun-function 1843 (beginning-of-defun-function end-of-defun-function
1826 where pos name-end case-fold-search) 1844 where pos decl name-start name-end case-fold-search)
1845
1846 (save-excursion
1847 ;; Move back out of any macro/comment/string we happen to be in.
1848 (c-beginning-of-macro)
1849 (setq pos (c-literal-start))
1850 (if pos (goto-char pos))
1851
1852 (setq where (c-where-wrt-brace-construct))
1853
1854 ;; Move to the beginning of the current defun, if any, if we're not
1855 ;; already there.
1856 (if (memq where '(outwith-function at-function-end))
1857 nil
1858 (unless (eq where 'at-header)
1859 (c-backward-to-nth-BOF-{ 1 where)
1860 (c-beginning-of-decl-1))
1861 (when (looking-at c-typedef-key)
1862 (goto-char (match-end 0))
1863 (c-forward-syntactic-ws))
1864
1865 ;; Pick out the defun name, according to the type of defun.
1866 (cond
1867 ;; struct, union, enum, or similar:
1868 ((save-excursion
1869 (and
1870 (looking-at c-defun-type-name-decl-key)
1871 (consp (c-forward-decl-or-cast-1 (c-point 'bosws) 'top nil))
1872 (or (not (or (eq (char-after) ?{)
1873 (and c-recognize-knr-p
1874 (c-in-knr-argdecl))))
1875 (progn (c-backward-syntactic-ws)
1876 (not (eq (char-before) ?\)))))))
1877 (let ((key-pos (point)))
1878 (c-forward-over-token-and-ws) ; over "struct ".
1879 (cond
1880 ((looking-at c-symbol-key) ; "struct foo { ..."
1881 (buffer-substring-no-properties key-pos (match-end 0)))
1882 ((eq (char-after) ?{) ; "struct { ... } foo"
1883 (when (c-go-list-forward)
1884 (c-forward-syntactic-ws)
1885 (when (looking-at c-symbol-key) ; a bit bogus - there might
1886 ; be several identifiers.
1887 (match-string-no-properties 0)))))))
1888
1889 ((looking-at "DEFUN\\s-*(") ;"DEFUN\\_>") think of XEmacs!
1890 ;; DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory, ...) ==> Ffile_name_directory
1891 ;; DEFUN(POSIX::STREAM-LOCK, stream lockp &key BLOCK SHARED START LENGTH) ==> POSIX::STREAM-LOCK
1892 (down-list 1)
1893 (c-forward-syntactic-ws)
1894 (when (eq (char-after) ?\")
1895 (forward-sexp 1)
1896 (c-forward-token-2)) ; over the comma and following WS.
1897 (buffer-substring-no-properties
1898 (point)
1899 (progn
1900 (c-forward-token-2)
1901 (c-backward-syntactic-ws)
1902 (point))))
1903
1904 (t
1905 ;; Normal function or initializer.
1906 (when
1907 (and
1908 (consp
1909 (setq decl
1910 (c-forward-decl-or-cast-1 (c-point 'bosws) 'top nil)))
1911 (setq name-start (car decl))
1912 (progn (if (and (looking-at c-after-suffixed-type-decl-key)
1913 (match-beginning 1))
1914 (c-forward-keyword-clause 1))
1915 t)
1916 (or (eq (char-after) ?{)
1917 (and c-recognize-knr-p
1918 (c-in-knr-argdecl)))
1919 (goto-char name-start)
1920 (c-forward-name)
1921 (eq (char-after) ?\())
1922 (c-backward-syntactic-ws)
1923 (when (eq (char-before) ?\=) ; struct foo bar = {0, 0} ;
1924 (c-backward-token-2)
1925 (c-backward-syntactic-ws))
1926 (setq name-end (point))
1927 (c-back-over-compound-identifier)
1928 (and (looking-at c-symbol-start)
1929 (buffer-substring-no-properties (point) name-end)))))))))
1827 1930
1931(defun c-defun-name ()
1932 "Return the name of the current defun, or NIL if there isn't one.
1933\"Defun\" here means a function, or other top level construct
1934with a brace block, at the outermost level of nesting."
1935 (c-save-buffer-state ()
1828 (save-restriction 1936 (save-restriction
1829 (widen) 1937 (widen)
1830 (save-excursion 1938 (c-defun-name-1))))
1831 ;; Move back out of any macro/comment/string we happen to be in.
1832 (c-beginning-of-macro)
1833 (setq pos (c-literal-start))
1834 (if pos (goto-char pos))
1835
1836 (setq where (c-where-wrt-brace-construct))
1837
1838 ;; Move to the beginning of the current defun, if any, if we're not
1839 ;; already there.
1840 (if (eq where 'outwith-function)
1841 nil
1842 (unless (eq where 'at-header)
1843 (c-backward-to-nth-BOF-{ 1 where)
1844 (c-beginning-of-decl-1))
1845 (when (looking-at c-typedef-key)
1846 (goto-char (match-end 0))
1847 (c-forward-syntactic-ws))
1848
1849 ;; Pick out the defun name, according to the type of defun.
1850 (cond
1851 ;; struct, union, enum, or similar:
1852 ((save-excursion
1853 (and
1854 (looking-at c-type-prefix-key)
1855 (consp (c-forward-decl-or-cast-1 (c-point 'bosws) 'top nil))
1856 (or (not (or (eq (char-after) ?{)
1857 (and c-recognize-knr-p
1858 (c-in-knr-argdecl))))
1859 (progn (c-backward-syntactic-ws)
1860 (not (eq (char-before) ?\)))))))
1861 (let ((key-pos (point)))
1862 (c-forward-over-token-and-ws) ; over "struct ".
1863 (cond
1864 ((looking-at c-symbol-key) ; "struct foo { ..."
1865 (buffer-substring-no-properties key-pos (match-end 0)))
1866 ((eq (char-after) ?{) ; "struct { ... } foo"
1867 (when (c-go-list-forward)
1868 (c-forward-syntactic-ws)
1869 (when (looking-at c-symbol-key) ; a bit bogus - there might
1870 ; be several identifiers.
1871 (match-string-no-properties 0)))))))
1872
1873 ((looking-at "DEFUN\\s-*(") ;"DEFUN\\_>") think of XEmacs!
1874 ;; DEFUN ("file-name-directory", Ffile_name_directory, Sfile_name_directory, ...) ==> Ffile_name_directory
1875 ;; DEFUN(POSIX::STREAM-LOCK, stream lockp &key BLOCK SHARED START LENGTH) ==> POSIX::STREAM-LOCK
1876 (down-list 1)
1877 (c-forward-syntactic-ws)
1878 (when (eq (char-after) ?\")
1879 (forward-sexp 1)
1880 (c-forward-token-2)) ; over the comma and following WS.
1881 (buffer-substring-no-properties
1882 (point)
1883 (progn
1884 (c-forward-token-2)
1885 (when (looking-at ":") ; CLISP: DEFUN(PACKAGE:LISP-SYMBOL,...)
1886 (skip-chars-forward "^,"))
1887 (c-backward-syntactic-ws)
1888 (point))))
1889
1890 ((looking-at "DEF[a-zA-Z0-9_]* *( *\\([^, ]*\\) *,")
1891 ;; DEFCHECKER(sysconf_arg,prefix=_SC,default=, ...) ==> sysconf_arg
1892 ;; DEFFLAGSET(syslog_opt_flags,LOG_PID ...) ==> syslog_opt_flags
1893 (match-string-no-properties 1))
1894
1895 ;; Objc selectors.
1896 ((assq 'objc-method-intro (c-guess-basic-syntax))
1897 (let ((bound (save-excursion (c-end-of-statement) (point)))
1898 (kw-re (concat "\\(?:" c-symbol-key "\\)?:"))
1899 (stretches))
1900 (when (c-syntactic-re-search-forward c-symbol-key bound t t t)
1901 (push (match-string-no-properties 0) stretches)
1902 (while (c-syntactic-re-search-forward kw-re bound t t t)
1903 (push (match-string-no-properties 0) stretches)))
1904 (apply 'concat (nreverse stretches))))
1905
1906 (t
1907 ;; Normal function or initializer.
1908 (when
1909 (and
1910 (consp (c-forward-decl-or-cast-1 (c-point 'bosws) 'top nil))
1911 (or (eq (char-after) ?{)
1912 (and c-recognize-knr-p
1913 (c-in-knr-argdecl)))
1914 (progn
1915 (c-backward-syntactic-ws)
1916 (eq (char-before) ?\)))
1917 (c-go-list-backward))
1918 (c-backward-syntactic-ws)
1919 (when (eq (char-before) ?\=) ; struct foo bar = {0, 0} ;
1920 (c-backward-token-2)
1921 (c-backward-syntactic-ws))
1922 (setq name-end (point))
1923 (c-back-over-compound-identifier)
1924 (and (looking-at c-symbol-start)
1925 (buffer-substring-no-properties (point) name-end))))))))))
1926 1939
1927(defun c-declaration-limits (near) 1940(defun c-declaration-limits-1 (near)
1928 ;; Return a cons of the beginning and end positions of the current 1941 ;; Return a cons of the beginning and end position of the current
1929 ;; top level declaration or macro. If point is not inside any then 1942 ;; declaration or macro in the current narrowing. If there is no current
1930 ;; nil is returned, unless NEAR is non-nil in which case the closest 1943 ;; declaration or macro, return nil, unless NEAR is non-nil, in which case
1931 ;; following one is chosen instead (if there is any). The end 1944 ;; the closest following one is chosen instead (if there is any). The end
1932 ;; position is at the next line, providing there is one before the 1945 ;; position is at the next line, providing there is one before the
1933 ;; declaration. 1946 ;; declaration.
1934 ;; 1947 ;;
1935 ;; This function might do hidden buffer changes. 1948 ;; This function might do hidden buffer changes.
1936 (save-excursion 1949 (save-excursion
1937 (save-restriction 1950 (let ((start (point))
1938 (let ((start (point)) 1951 (paren-state (c-parse-state))
1939 (paren-state (c-parse-state)) 1952 lim pos end-pos where)
1940 lim pos end-pos where) 1953 (or
1941 ;; Narrow enclosing brace blocks out, as required by the values of 1954 ;; Note: Some code duplication in `c-beginning-of-defun' and
1942 ;; `c-defun-tactic', `near', and the position of point. 1955 ;; `c-end-of-defun'.
1943 (when (eq c-defun-tactic 'go-outward) 1956 (catch 'exit
1944 (let ((bounds 1957 (unless (c-safe
1945 (save-restriction 1958 (goto-char (c-least-enclosing-brace paren-state))
1946 (if (and (not (save-excursion (c-beginning-of-macro))) 1959 ;; If we moved to the outermost enclosing paren
1947 (save-restriction 1960 ;; then we can use c-safe-position to set the
1948 (c-narrow-to-most-enclosing-decl-block) 1961 ;; limit. Can't do that otherwise since the
1949 (memq (c-where-wrt-brace-construct) 1962 ;; earlier paren pair on paren-state might very
1950 '(at-function-end outwith-function))) 1963 ;; well be part of the declaration we should go
1951 (not near)) 1964 ;; to.
1952 (c-narrow-to-most-enclosing-decl-block nil 2) 1965 (setq lim (c-safe-position (point) paren-state))
1953 (c-narrow-to-most-enclosing-decl-block)) 1966 ;; We might have a struct foo {...} as the type of the
1954 (cons (point-min) (point-max))))) 1967 ;; function, so set LIM back one further block.
1955 (narrow-to-region (car bounds) (cdr bounds)))) 1968 (if (eq (char-before lim) ?})
1956 (setq paren-state (c-parse-state)) 1969 (setq lim
1957 1970 (or
1958 (or 1971 (save-excursion
1959 ;; Note: Some code duplication in `c-beginning-of-defun' and 1972 (and
1960 ;; `c-end-of-defun'. 1973 (c-go-list-backward lim)
1961 (catch 'exit 1974 (let ((paren-state-1 (c-parse-state)))
1962 (unless (c-safe 1975 (c-safe-position
1963 (goto-char (c-least-enclosing-brace paren-state)) 1976 (point) paren-state-1))))
1964 ;; If we moved to the outermost enclosing paren 1977 (point-min))))
1965 ;; then we can use c-safe-position to set the 1978 t)
1966 ;; limit. Can't do that otherwise since the 1979 ;; At top level. Make sure we aren't inside a literal.
1967 ;; earlier paren pair on paren-state might very 1980 (setq pos (c-literal-start
1968 ;; well be part of the declaration we should go 1981 (c-safe-position (point) paren-state)))
1969 ;; to. 1982 (if pos (goto-char pos)))
1970 (setq lim (c-safe-position (point) paren-state)) 1983
1971 t) 1984 (when (c-beginning-of-macro)
1972 ;; At top level. Make sure we aren't inside a literal. 1985 (throw 'exit
1973 (setq pos (c-literal-start 1986 (cons (point)
1974 (c-safe-position (point) paren-state))) 1987 (save-excursion
1975 (if pos (goto-char pos))) 1988 (c-end-of-macro)
1976 1989 (forward-line 1)
1977 (when (c-beginning-of-macro) 1990 (point)))))
1991
1992 (setq pos (point))
1993 (setq where (and (not (save-excursion (c-beginning-of-macro)))
1994 (c-where-wrt-brace-construct)))
1995 (when (and (not (eq where 'at-header))
1996 (or (and near
1997 (memq where
1998 '(at-function-end outwith-function))
1999 ;; Check we're not inside a declaration without
2000 ;; braces.
2001 (save-excursion
2002 (memq (car (c-beginning-of-decl-1 lim))
2003 '(previous label))))
2004 (eq (car (c-beginning-of-decl-1 lim)) 'previous)
2005 (= pos (point))))
2006 ;; We moved back over the previous defun. Skip to the next
2007 ;; one. Not using c-forward-syntactic-ws here since we
2008 ;; should not skip a macro. We can also be directly after
2009 ;; the block in a `c-opt-block-decls-with-vars-key'
2010 ;; declaration, but then we won't move significantly far
2011 ;; here.
2012 (goto-char pos)
2013 (c-forward-comments)
2014
2015 (when (and near (c-beginning-of-macro))
1978 (throw 'exit 2016 (throw 'exit
1979 (cons (point) 2017 (cons (point)
1980 (save-excursion 2018 (save-excursion
1981 (c-end-of-macro) 2019 (c-end-of-macro)
1982 (forward-line 1) 2020 (forward-line 1)
1983 (point))))) 2021 (point))))))
1984 2022
1985 (setq pos (point)) 2023 (if (eobp) (throw 'exit nil))
1986 (setq where (and (not (save-excursion (c-beginning-of-macro)))
1987 (c-where-wrt-brace-construct)))
1988 (when (and (not (eq where 'at-header))
1989 (or (and near
1990 (memq where
1991 '(at-function-end outwith-function)))
1992 (eq (car (c-beginning-of-decl-1 lim)) 'previous)
1993 (= pos (point))))
1994 ;; We moved back over the previous defun. Skip to the next
1995 ;; one. Not using c-forward-syntactic-ws here since we
1996 ;; should not skip a macro. We can also be directly after
1997 ;; the block in a `c-opt-block-decls-with-vars-key'
1998 ;; declaration, but then we won't move significantly far
1999 ;; here.
2000 (goto-char pos)
2001 (c-forward-comments)
2002
2003 (when (and near (c-beginning-of-macro))
2004 (throw 'exit
2005 (cons (point)
2006 (save-excursion
2007 (c-end-of-macro)
2008 (forward-line 1)
2009 (point))))))
2010 2024
2011 (if (eobp) (throw 'exit nil)) 2025 ;; Check if `c-beginning-of-decl-1' put us after the block in a
2026 ;; declaration that doesn't end there. We're searching back and
2027 ;; forth over the block here, which can be expensive.
2028 (setq pos (point))
2029 (if (and c-opt-block-decls-with-vars-key
2030 (progn
2031 (c-backward-syntactic-ws)
2032 (eq (char-before) ?}))
2033 (eq (car (c-beginning-of-decl-1))
2034 'previous)
2035 (save-excursion
2036 (c-end-of-decl-1)
2037 (and (> (point) pos)
2038 (setq end-pos (point)))))
2039 nil
2040 (goto-char pos))
2041
2042 (if (or (and (not near) (> (point) start))
2043 (not (eq (c-where-wrt-brace-construct) 'at-header)))
2044 nil
2045
2046 ;; Try to be line oriented; position the limits at the
2047 ;; closest preceding boi, and after the next newline, that
2048 ;; isn't inside a comment, but if we hit a neighboring
2049 ;; declaration then we instead use the exact declaration
2050 ;; limit in that direction.
2051 (cons (progn
2052 (setq pos (point))
2053 (while (and (/= (point) (c-point 'boi))
2054 (c-backward-single-comment)))
2055 (if (/= (point) (c-point 'boi))
2056 pos
2057 (point)))
2058 (progn
2059 (if end-pos
2060 (goto-char end-pos)
2061 (c-end-of-decl-1))
2062 (setq pos (point))
2063 (while (and (not (bolp))
2064 (not (looking-at "\\s *$"))
2065 (c-forward-single-comment)))
2066 (cond ((bolp)
2067 (point))
2068 ((looking-at "\\s *$")
2069 (forward-line 1)
2070 (point))
2071 (t
2072 pos))))))
2073 (and (not near)
2074 (goto-char (point-min))
2075 (c-forward-decl-or-cast-1 -1 nil nil)
2076 (eq (char-after) ?\{)
2077 (cons (point-min) (point-max)))))))
2012 2078
2013 ;; Check if `c-beginning-of-decl-1' put us after the block in a 2079(defun c-declaration-limits (near)
2014 ;; declaration that doesn't end there. We're searching back and 2080 ;; Return a cons of the beginning and end positions of the current
2015 ;; forth over the block here, which can be expensive. 2081 ;; top level declaration or macro. If point is not inside any then
2016 (setq pos (point)) 2082 ;; nil is returned, unless NEAR is non-nil in which case the closest
2017 (if (and c-opt-block-decls-with-vars-key 2083 ;; following one is chosen instead (if there is any). The end
2018 (progn 2084 ;; position is at the next line, providing there is one before the
2019 (c-backward-syntactic-ws) 2085 ;; declaration.
2020 (eq (char-before) ?})) 2086 ;;
2021 (eq (car (c-beginning-of-decl-1)) 2087 ;; This function might do hidden buffer changes.
2022 'previous) 2088 (save-restriction
2023 (save-excursion 2089 ;; Narrow enclosing brace blocks out, as required by the values of
2024 (c-end-of-decl-1) 2090 ;; `c-defun-tactic', `near', and the position of point.
2025 (and (> (point) pos) 2091 (when (eq c-defun-tactic 'go-outward)
2026 (setq end-pos (point))))) 2092 (let ((bounds
2027 nil 2093 (save-restriction
2028 (goto-char pos)) 2094 (if (and (not (save-excursion (c-beginning-of-macro)))
2029 2095 (save-restriction
2030 (if (and (not near) (> (point) start)) 2096 (c-narrow-to-most-enclosing-decl-block)
2031 nil 2097 (memq (c-where-wrt-brace-construct)
2032 2098 '(at-function-end outwith-function)))
2033 ;; Try to be line oriented; position the limits at the 2099 (not near))
2034 ;; closest preceding boi, and after the next newline, that 2100 (c-narrow-to-most-enclosing-decl-block nil 2)
2035 ;; isn't inside a comment, but if we hit a neighboring 2101 (c-narrow-to-most-enclosing-decl-block))
2036 ;; declaration then we instead use the exact declaration 2102 (cons (point-min) (point-max)))))
2037 ;; limit in that direction. 2103 (narrow-to-region (car bounds) (cdr bounds))))
2038 (cons (progn 2104 (c-declaration-limits-1 near)))
2039 (setq pos (point)) 2105
2040 (while (and (/= (point) (c-point 'boi)) 2106(defun c-defun-name-and-limits (near)
2041 (c-backward-single-comment))) 2107 ;; Return a cons of the name and limits (itself a cons) of the current
2042 (if (/= (point) (c-point 'boi)) 2108 ;; top-level declaration or macro, or nil of there is none.
2043 pos 2109 ;;
2044 (point))) 2110 ;; If `c-defun-tactic' is 'go-outward, we return the name and limits of the
2045 (progn 2111 ;; most tightly enclosing declaration or macro. Otherwise, we return that
2046 (if end-pos 2112 ;; at the file level.
2047 (goto-char end-pos) 2113 (save-restriction
2048 (c-end-of-decl-1)) 2114 (widen)
2049 (setq pos (point)) 2115 (if (eq c-defun-tactic 'go-outward)
2050 (while (and (not (bolp)) 2116 (c-save-buffer-state ((paren-state (c-parse-state))
2051 (not (looking-at "\\s *$")) 2117 (orig-point-min (point-min))
2052 (c-forward-single-comment))) 2118 (orig-point-max (point-max))
2053 (cond ((bolp) 2119 lim name where limits fdoc)
2054 (point)) 2120 (setq lim (c-widen-to-enclosing-decl-scope
2055 ((looking-at "\\s *$") 2121 paren-state orig-point-min orig-point-max))
2056 (forward-line 1) 2122 (and lim (setq lim (1- lim)))
2057 (point)) 2123 (c-while-widening-to-decl-block (not (setq name (c-defun-name-1))))
2058 (t 2124 (when name
2059 pos)))))) 2125 (setq limits (c-declaration-limits-1 near))
2060 (and (not near) 2126 (cons name limits)))
2061 (goto-char (point-min)) 2127 (c-save-buffer-state ((name (c-defun-name))
2062 (c-forward-decl-or-cast-1 -1 nil nil) 2128 (limits (c-declaration-limits near)))
2063 (eq (char-after) ?\{) 2129 (and name limits (cons name limits))))))
2064 (cons (point-min) (point-max))))))))
2065 2130
2066(defun c-display-defun-name (&optional arg) 2131(defun c-display-defun-name (&optional arg)
2067 "Display the name of the current CC mode defun and the position in it. 2132 "Display the name of the current CC mode defun and the position in it.
@@ -2069,12 +2134,13 @@ With a prefix arg, push the name onto the kill ring too."
2069 (interactive "P") 2134 (interactive "P")
2070 (save-restriction 2135 (save-restriction
2071 (widen) 2136 (widen)
2072 (c-save-buffer-state ((name (c-defun-name)) 2137 (c-save-buffer-state ((name-and-limits (c-defun-name-and-limits nil))
2073 (limits (c-declaration-limits t)) 2138 (name (car name-and-limits))
2139 (limits (cdr name-and-limits))
2074 (point-bol (c-point 'bol))) 2140 (point-bol (c-point 'bol)))
2075 (when name 2141 (when name
2076 (message "%s. Line %s/%s." name 2142 (message "%s. Line %s/%s." name
2077 (1+ (count-lines (car limits) point-bol)) 2143 (1+ (count-lines (car limits) (max point-bol (car limits))))
2078 (count-lines (car limits) (cdr limits))) 2144 (count-lines (car limits) (cdr limits)))
2079 (if arg (kill-new name)) 2145 (if arg (kill-new name))
2080 (sit-for 3 t))))) 2146 (sit-for 3 t)))))
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index b78e85a6708..ceeee6b357d 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1124,7 +1124,16 @@ comment at the start of cc-engine.el for more info."
1124 (not (c-looking-at-inexpr-block lim nil t)) 1124 (not (c-looking-at-inexpr-block lim nil t))
1125 (save-excursion 1125 (save-excursion
1126 (c-backward-token-2 1 t nil) 1126 (c-backward-token-2 1 t nil)
1127 (not (looking-at "=\\([^=]\\|$\\)")))) 1127 (not (looking-at "=\\([^=]\\|$\\)")))
1128 (or
1129 (not c-opt-block-decls-with-vars-key)
1130 (save-excursion
1131 (c-backward-token-2 1 t nil)
1132 (if (and (looking-at c-symbol-start)
1133 (not (looking-at c-keywords-regexp)))
1134 (c-backward-token-2 1 t nil))
1135 (not (looking-at
1136 c-opt-block-decls-with-vars-key)))))
1128 (save-excursion 1137 (save-excursion
1129 (c-forward-sexp) (point))) 1138 (c-forward-sexp) (point)))
1130 ;; Just gone back over some paren block? 1139 ;; Just gone back over some paren block?
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index c06dd2164db..f1ef89a76ad 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -2107,6 +2107,18 @@ will be handled."
2107 "Alist associating keywords in c-other-decl-block-decl-kwds with 2107 "Alist associating keywords in c-other-decl-block-decl-kwds with
2108their matching \"in\" syntactic symbols.") 2108their matching \"in\" syntactic symbols.")
2109 2109
2110(c-lang-defconst c-defun-type-name-decl-kwds
2111 "Keywords introducing a named block, where the name is a \"defun\"
2112 name."
2113 t (append (c-lang-const c-class-decl-kwds)
2114 (c-lang-const c-brace-list-decl-kwds)))
2115
2116(c-lang-defconst c-defun-type-name-decl-key
2117 ;; Regexp matching a keyword in `c-defun-name-decl-kwds'.
2118 t (c-make-keywords-re t (c-lang-const c-defun-type-name-decl-kwds)))
2119(c-lang-defvar c-defun-type-name-decl-key
2120 (c-lang-const c-defun-type-name-decl-key))
2121
2110(c-lang-defconst c-typedef-decl-kwds 2122(c-lang-defconst c-typedef-decl-kwds
2111 "Keywords introducing declarations where the identifier(s) being 2123 "Keywords introducing declarations where the identifier(s) being
2112declared are types. 2124declared are types.