diff options
| author | Alan Mackenzie | 2016-01-22 22:31:23 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2016-01-22 22:31:23 +0000 |
| commit | bbbb038654eab73624a5d51faa52f2d3f5db14b5 (patch) | |
| tree | 60ec0e1a51aebf7d6060e9b469a45e815e8ae235 | |
| parent | 6ff8b45f18619c2dc95dfb1d92a5c48b14049973 (diff) | |
| download | emacs-bbbb038654eab73624a5d51faa52f2d3f5db14b5.tar.gz emacs-bbbb038654eab73624a5d51faa52f2d3f5db14b5.zip | |
Prevent spurious recognition of K&R argument declarations. Fixes bug #2203
* cc-engine.el (c-forward-declarator): New function.
(c-in-knr-argdecl): Before recognizing a K&R argument declaration, check it is
contained in the preceding arg list.
* cc-fonts.el (c-font-lock-declarators): Use the new function
`c-forward-declarator' in place of inline code.
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 171 | ||||
| -rw-r--r-- | lisp/progmodes/cc-fonts.el | 93 |
2 files changed, 168 insertions, 96 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 63f01829845..8113446e4d3 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -6808,6 +6808,110 @@ comment at the start of cc-engine.el for more info." | |||
| 6808 | ;; This identifier is bound only in the inner let. | 6808 | ;; This identifier is bound only in the inner let. |
| 6809 | '(setq start id-start)))) | 6809 | '(setq start id-start)))) |
| 6810 | 6810 | ||
| 6811 | (defun c-forward-declarator (&optional limit) | ||
| 6812 | ;; Assuming point is at the start of a declarator, move forward over it, | ||
| 6813 | ;; leaving point at the next token after it (e.g. a ) or a ; or a ,). | ||
| 6814 | ;; | ||
| 6815 | ;; Return a list (ID-START ID-END BRACKETS-AFTER-ID GOT-INIT), where ID-START and | ||
| 6816 | ;; ID-END are the bounds of the declarator's identifier, and | ||
| 6817 | ;; BRACKETS-AFTER-ID is non-nil if a [...] pair is present after the id. | ||
| 6818 | ;; GOT-INIT is non-nil when the declarator is followed by "=" or "(". | ||
| 6819 | ;; | ||
| 6820 | ;; If no declarator is found, leave point unmoved and return nil. LIMIT is | ||
| 6821 | ;; an optional limit for forward searching. | ||
| 6822 | ;; | ||
| 6823 | ;; Note that the global variable `c-last-identifier-range' is written to, so | ||
| 6824 | ;; the caller should bind it if necessary. | ||
| 6825 | |||
| 6826 | ;; Inside the following "condition form", we move forward over the | ||
| 6827 | ;; declarator's identifier up as far as any opening bracket (for array | ||
| 6828 | ;; size) or paren (for parameters of function-type) or brace (for | ||
| 6829 | ;; array/struct initialization) or "=" or terminating delimiter | ||
| 6830 | ;; (e.g. "," or ";" or "}"). | ||
| 6831 | (let ((here (point)) | ||
| 6832 | id-start id-end brackets-after-id paren-depth) | ||
| 6833 | (or limit (setq limit (point-max))) | ||
| 6834 | (if (and | ||
| 6835 | (< (point) limit) | ||
| 6836 | |||
| 6837 | ;; The following form moves forward over the declarator's | ||
| 6838 | ;; identifier (and what precedes it), returning t. If there | ||
| 6839 | ;; wasn't one, it returns nil. | ||
| 6840 | (let (got-identifier) | ||
| 6841 | (setq paren-depth 0) | ||
| 6842 | ;; Skip over type decl prefix operators, one for each iteration | ||
| 6843 | ;; of the while. These are, e.g. "*" in "int *foo" or "(" and | ||
| 6844 | ;; "*" in "int (*foo) (void)" (Note similar code in | ||
| 6845 | ;; `c-forward-decl-or-cast-1'.) | ||
| 6846 | (while (and (looking-at c-type-decl-prefix-key) | ||
| 6847 | (if (and (c-major-mode-is 'c++-mode) | ||
| 6848 | (match-beginning 3)) | ||
| 6849 | ;; If the third submatch matches in C++ then | ||
| 6850 | ;; we're looking at an identifier that's a | ||
| 6851 | ;; prefix only if it specifies a member pointer. | ||
| 6852 | (progn | ||
| 6853 | (setq id-start (point)) | ||
| 6854 | (c-forward-name) | ||
| 6855 | (if (looking-at "\\(::\\)") | ||
| 6856 | ;; We only check for a trailing "::" and | ||
| 6857 | ;; let the "*" that should follow be | ||
| 6858 | ;; matched in the next round. | ||
| 6859 | t | ||
| 6860 | ;; It turned out to be the real identifier, | ||
| 6861 | ;; so flag that and stop. | ||
| 6862 | (setq got-identifier t) | ||
| 6863 | nil)) | ||
| 6864 | t)) | ||
| 6865 | (if (eq (char-after) ?\() | ||
| 6866 | (progn | ||
| 6867 | (setq paren-depth (1+ paren-depth)) | ||
| 6868 | (forward-char)) | ||
| 6869 | (goto-char (match-end 1))) | ||
| 6870 | (c-forward-syntactic-ws)) | ||
| 6871 | |||
| 6872 | ;; If we haven't passed the identifier already, do it now. | ||
| 6873 | (unless got-identifier | ||
| 6874 | (setq id-start (point)) | ||
| 6875 | (c-forward-name)) | ||
| 6876 | (prog1 | ||
| 6877 | (/= (point) here) | ||
| 6878 | (save-excursion | ||
| 6879 | (c-backward-syntactic-ws) | ||
| 6880 | (setq id-end (point))))) | ||
| 6881 | |||
| 6882 | ;; Skip out of the parens surrounding the identifier. If closing | ||
| 6883 | ;; parens are missing, this form returns nil. | ||
| 6884 | (or (= paren-depth 0) | ||
| 6885 | (c-safe (goto-char (scan-lists (point) 1 paren-depth)))) | ||
| 6886 | |||
| 6887 | (<= (point) limit) | ||
| 6888 | |||
| 6889 | ;; Skip over any trailing bit, such as "__attribute__". | ||
| 6890 | (progn | ||
| 6891 | (when (looking-at c-decl-hangon-key) | ||
| 6892 | (c-forward-keyword-clause 1)) | ||
| 6893 | (<= (point) limit)) | ||
| 6894 | |||
| 6895 | ;; Search syntactically to the end of the declarator (";", | ||
| 6896 | ;; ",", a closing paren, eob etc) or to the beginning of an | ||
| 6897 | ;; initializer or function prototype ("=" or "\\s\("). | ||
| 6898 | ;; Note that square brackets are now not also treated as | ||
| 6899 | ;; initializers, since this broke when there were also | ||
| 6900 | ;; initializing brace lists. | ||
| 6901 | (let (found) | ||
| 6902 | (while | ||
| 6903 | (and (setq found (c-syntactic-re-search-forward | ||
| 6904 | "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t)) | ||
| 6905 | (eq (char-before) ?\[) | ||
| 6906 | (c-go-up-list-forward)) | ||
| 6907 | (setq brackets-after-id t)) | ||
| 6908 | (backward-char) | ||
| 6909 | found)) | ||
| 6910 | (list id-start id-end brackets-after-id (match-beginning 1)) | ||
| 6911 | |||
| 6912 | (goto-char here) | ||
| 6913 | nil))) | ||
| 6914 | |||
| 6811 | (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) | 6915 | (defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end) |
| 6812 | ;; Move forward over a declaration or a cast if at the start of one. | 6916 | ;; Move forward over a declaration or a cast if at the start of one. |
| 6813 | ;; The point is assumed to be at the start of some token. Nil is | 6917 | ;; The point is assumed to be at the start of some token. Nil is |
| @@ -8162,14 +8266,14 @@ comment at the start of cc-engine.el for more info." | |||
| 8162 | ;; Return the position of the first argument declaration if point is | 8266 | ;; Return the position of the first argument declaration if point is |
| 8163 | ;; inside a K&R style argument declaration list, nil otherwise. | 8267 | ;; inside a K&R style argument declaration list, nil otherwise. |
| 8164 | ;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a | 8268 | ;; `c-recognize-knr-p' is not checked. If LIM is non-nil, it's a |
| 8165 | ;; position that bounds the backward search for the argument list. | 8269 | ;; position that bounds the backward search for the argument list. This |
| 8270 | ;; function doesn't move point. | ||
| 8166 | ;; | 8271 | ;; |
| 8167 | ;; Point must be within a possible K&R region, e.g. just before a top-level | 8272 | ;; Point must be within a possible K&R region, e.g. just before a top-level |
| 8168 | ;; "{". It must be outside of parens and brackets. The test can return | 8273 | ;; "{". It must be outside of parens and brackets. The test can return |
| 8169 | ;; false positives otherwise. | 8274 | ;; false positives otherwise. |
| 8170 | ;; | 8275 | ;; |
| 8171 | ;; This function might do hidden buffer changes. | 8276 | ;; This function might do hidden buffer changes. |
| 8172 | |||
| 8173 | (save-excursion | 8277 | (save-excursion |
| 8174 | (save-restriction | 8278 | (save-restriction |
| 8175 | ;; If we're in a macro, our search range is restricted to it. Narrow to | 8279 | ;; If we're in a macro, our search range is restricted to it. Narrow to |
| @@ -8178,8 +8282,12 @@ comment at the start of cc-engine.el for more info." | |||
| 8178 | (macro-end (save-excursion (and macro-start (c-end-of-macro) (point)))) | 8282 | (macro-end (save-excursion (and macro-start (c-end-of-macro) (point)))) |
| 8179 | (low-lim (max (or lim (point-min)) (or macro-start (point-min)))) | 8283 | (low-lim (max (or lim (point-min)) (or macro-start (point-min)))) |
| 8180 | before-lparen after-rparen | 8284 | before-lparen after-rparen |
| 8181 | (pp-count-out 20)) ; Max number of paren/brace constructs before | 8285 | (here (point)) |
| 8286 | (pp-count-out 20) ; Max number of paren/brace constructs before | ||
| 8182 | ; we give up | 8287 | ; we give up |
| 8288 | ids ; List of identifiers in the parenthesised list. | ||
| 8289 | id-start after-prec-token decl-or-cast decl-res | ||
| 8290 | c-last-identifier-range identifier-ok) | ||
| 8183 | (narrow-to-region low-lim (or macro-end (point-max))) | 8291 | (narrow-to-region low-lim (or macro-end (point-max))) |
| 8184 | 8292 | ||
| 8185 | ;; Search backwards for the defun's argument list. We give up if we | 8293 | ;; Search backwards for the defun's argument list. We give up if we |
| @@ -8198,8 +8306,12 @@ comment at the start of cc-engine.el for more info." | |||
| 8198 | ;; int foo (bar, baz, yuk) | 8306 | ;; int foo (bar, baz, yuk) |
| 8199 | ;; int bar [] ; | 8307 | ;; int bar [] ; |
| 8200 | ;; int (*baz) (my_type) ; | 8308 | ;; int (*baz) (my_type) ; |
| 8201 | ;; int (*) (void) (*yuk) (void) ; | 8309 | ;; int (*(* yuk) (void)) (void) ; |
| 8202 | ;; { | 8310 | ;; { |
| 8311 | ;; | ||
| 8312 | ;; Additionally, for a knr list to be recognized: | ||
| 8313 | ;; o - The identifier of each deeclarator up to and including the | ||
| 8314 | ;; one "near" point must be contained in the arg list. | ||
| 8203 | 8315 | ||
| 8204 | (catch 'knr | 8316 | (catch 'knr |
| 8205 | (while (> pp-count-out 0) ; go back one paren/bracket pair each time. | 8317 | (while (> pp-count-out 0) ; go back one paren/bracket pair each time. |
| @@ -8245,21 +8357,58 @@ comment at the start of cc-engine.el for more info." | |||
| 8245 | (goto-char before-lparen) | 8357 | (goto-char before-lparen) |
| 8246 | (c-forward-token-2) ; to first token inside parens | 8358 | (c-forward-token-2) ; to first token inside parens |
| 8247 | (and | 8359 | (and |
| 8248 | (c-on-identifier) | 8360 | (setq id-start (c-on-identifier)) ; Must be at least one. |
| 8249 | (c-forward-token-2) | ||
| 8250 | (catch 'id-list | 8361 | (catch 'id-list |
| 8251 | (while (eq (char-after) ?\,) | 8362 | (while |
| 8363 | (progn | ||
| 8364 | (forward-char) | ||
| 8365 | (c-end-of-current-token) | ||
| 8366 | (push (buffer-substring-no-properties id-start | ||
| 8367 | (point)) | ||
| 8368 | ids) | ||
| 8369 | (c-forward-syntactic-ws) | ||
| 8370 | (eq (char-after) ?\,)) | ||
| 8252 | (c-forward-token-2) | 8371 | (c-forward-token-2) |
| 8253 | (unless (c-on-identifier) (throw 'id-list nil)) | 8372 | (unless (setq id-start (c-on-identifier)) |
| 8254 | (c-forward-token-2)) | 8373 | (throw 'id-list nil))) |
| 8255 | (eq (char-after) ?\)))))) | 8374 | (eq (char-after) ?\))))) |
| 8256 | 8375 | ||
| 8376 | ;; Are all the identifiers in the k&r list up to the | ||
| 8377 | ;; current one also in the argument list? | ||
| 8378 | (progn | ||
| 8379 | (forward-char) ; over the ) | ||
| 8380 | (setq after-prec-token after-rparen) | ||
| 8381 | (c-forward-syntactic-ws) | ||
| 8382 | (while (and | ||
| 8383 | (or (consp (setq decl-or-cast | ||
| 8384 | (c-forward-decl-or-cast-1 | ||
| 8385 | after-prec-token | ||
| 8386 | nil ; Or 'arglist ??? | ||
| 8387 | nil))) | ||
| 8388 | (progn | ||
| 8389 | (goto-char after-prec-token) | ||
| 8390 | (c-forward-syntactic-ws) | ||
| 8391 | (setq identifier-ok (eq (char-after) ?{)) | ||
| 8392 | nil)) | ||
| 8393 | (eq (char-after) ?\;) | ||
| 8394 | (setq after-prec-token (1+ (point))) | ||
| 8395 | (goto-char (car decl-or-cast)) | ||
| 8396 | (setq decl-res (c-forward-declarator)) | ||
| 8397 | (setq identifier-ok | ||
| 8398 | (member (buffer-substring-no-properties | ||
| 8399 | (car decl-res) (cadr decl-res)) | ||
| 8400 | ids)) | ||
| 8401 | (progn | ||
| 8402 | (goto-char after-prec-token) | ||
| 8403 | (prog1 (< (point) here) | ||
| 8404 | (c-forward-syntactic-ws)))) | ||
| 8405 | (setq identifier-ok nil)) | ||
| 8406 | identifier-ok)) | ||
| 8257 | ;; ...Yes. We've identified the function's argument list. | 8407 | ;; ...Yes. We've identified the function's argument list. |
| 8258 | (throw 'knr | 8408 | (throw 'knr |
| 8259 | (progn (goto-char after-rparen) | 8409 | (progn (goto-char after-rparen) |
| 8260 | (c-forward-syntactic-ws) | 8410 | (c-forward-syntactic-ws) |
| 8261 | (point))) | 8411 | (point))) |
| 8262 | |||
| 8263 | ;; ...No. The current parens aren't the function's arg list. | 8412 | ;; ...No. The current parens aren't the function's arg list. |
| 8264 | (goto-char before-lparen)) | 8413 | (goto-char before-lparen)) |
| 8265 | 8414 | ||
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 03e67a99515..1e101d12aac 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el | |||
| @@ -1006,6 +1006,7 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1006 | ;;(message "c-font-lock-declarators from %s to %s" (point) limit) | 1006 | ;;(message "c-font-lock-declarators from %s to %s" (point) limit) |
| 1007 | (c-fontify-types-and-refs | 1007 | (c-fontify-types-and-refs |
| 1008 | ((pos (point)) next-pos id-start id-end | 1008 | ((pos (point)) next-pos id-start id-end |
| 1009 | decl-res | ||
| 1009 | paren-depth | 1010 | paren-depth |
| 1010 | id-face got-init | 1011 | id-face got-init |
| 1011 | c-last-identifier-range | 1012 | c-last-identifier-range |
| @@ -1015,93 +1016,15 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 1015 | ;; The following `while' fontifies a single declarator id each time round. | 1016 | ;; The following `while' fontifies a single declarator id each time round. |
| 1016 | ;; It loops only when LIST is non-nil. | 1017 | ;; It loops only when LIST is non-nil. |
| 1017 | (while | 1018 | (while |
| 1018 | ;; Inside the following "condition form", we move forward over the | 1019 | (and pos (setq decl-res (c-forward-declarator limit))) |
| 1019 | ;; declarator's identifier up as far as any opening bracket (for array | 1020 | (setq next-pos (point) |
| 1020 | ;; size) or paren (for parameters of function-type) or brace (for | 1021 | id-start (car decl-res) |
| 1021 | ;; array/struct initialization) or "=" or terminating delimiter | 1022 | id-face (if (and (eq (char-after) ?\() |
| 1022 | ;; (e.g. "," or ";" or "}"). | 1023 | (not (car (cddr decl-res)))) ; brackets-after-id |
| 1023 | (and | ||
| 1024 | pos | ||
| 1025 | (< (point) limit) | ||
| 1026 | |||
| 1027 | ;; The following form moves forward over the declarator's | ||
| 1028 | ;; identifier (and what precedes it), returning t. If there | ||
| 1029 | ;; wasn't one, it returns nil, terminating the `while'. | ||
| 1030 | (let (got-identifier) | ||
| 1031 | (setq paren-depth 0) | ||
| 1032 | ;; Skip over type decl prefix operators, one for each iteration | ||
| 1033 | ;; of the while. These are, e.g. "*" in "int *foo" or "(" and | ||
| 1034 | ;; "*" in "int (*foo) (void)" (Note similar code in | ||
| 1035 | ;; `c-forward-decl-or-cast-1'.) | ||
| 1036 | (while (and (looking-at c-type-decl-prefix-key) | ||
| 1037 | (if (and (c-major-mode-is 'c++-mode) | ||
| 1038 | (match-beginning 3)) | ||
| 1039 | ;; If the third submatch matches in C++ then | ||
| 1040 | ;; we're looking at an identifier that's a | ||
| 1041 | ;; prefix only if it specifies a member pointer. | ||
| 1042 | (progn | ||
| 1043 | (setq id-start (point)) | ||
| 1044 | (c-forward-name) | ||
| 1045 | (if (looking-at "\\(::\\)") | ||
| 1046 | ;; We only check for a trailing "::" and | ||
| 1047 | ;; let the "*" that should follow be | ||
| 1048 | ;; matched in the next round. | ||
| 1049 | t | ||
| 1050 | ;; It turned out to be the real identifier, | ||
| 1051 | ;; so flag that and stop. | ||
| 1052 | (setq got-identifier t) | ||
| 1053 | nil)) | ||
| 1054 | t)) | ||
| 1055 | (if (eq (char-after) ?\() | ||
| 1056 | (progn | ||
| 1057 | (setq paren-depth (1+ paren-depth)) | ||
| 1058 | (forward-char)) | ||
| 1059 | (goto-char (match-end 1))) | ||
| 1060 | (c-forward-syntactic-ws)) | ||
| 1061 | |||
| 1062 | ;; If we haven't passed the identifier already, do it now. | ||
| 1063 | (unless got-identifier | ||
| 1064 | (setq id-start (point)) | ||
| 1065 | (c-forward-name)) | ||
| 1066 | (setq id-end (point)) | ||
| 1067 | |||
| 1068 | (/= id-end pos)) | ||
| 1069 | |||
| 1070 | ;; Skip out of the parens surrounding the identifier. If closing | ||
| 1071 | ;; parens are missing, this form returns nil. | ||
| 1072 | (or (= paren-depth 0) | ||
| 1073 | (c-safe (goto-char (scan-lists (point) 1 paren-depth)))) | ||
| 1074 | |||
| 1075 | (<= (point) limit) | ||
| 1076 | |||
| 1077 | ;; Skip over any trailing bit, such as "__attribute__". | ||
| 1078 | (progn | ||
| 1079 | (when (looking-at c-decl-hangon-key) | ||
| 1080 | (c-forward-keyword-clause 1)) | ||
| 1081 | (<= (point) limit)) | ||
| 1082 | |||
| 1083 | ;; Search syntactically to the end of the declarator (";", | ||
| 1084 | ;; ",", a closing paren, eob etc) or to the beginning of an | ||
| 1085 | ;; initializer or function prototype ("=" or "\\s("). | ||
| 1086 | ;; Note that square brackets are now not also treated as | ||
| 1087 | ;; initializers, since this broke when there were also | ||
| 1088 | ;; initializing brace lists. | ||
| 1089 | (let (found) | ||
| 1090 | (while | ||
| 1091 | (and (setq found (c-syntactic-re-search-forward | ||
| 1092 | "[;,]\\|\\s)\\|\\'\\|\\(=\\|\\s(\\)" limit t t)) | ||
| 1093 | (eq (char-before) ?\[) | ||
| 1094 | (c-go-up-list-forward)) | ||
| 1095 | (setq brackets-after-id t)) | ||
| 1096 | found)) | ||
| 1097 | |||
| 1098 | (setq next-pos (match-beginning 0) | ||
| 1099 | id-face (if (and (eq (char-after next-pos) ?\() | ||
| 1100 | (not brackets-after-id)) | ||
| 1101 | 'font-lock-function-name-face | 1024 | 'font-lock-function-name-face |
| 1102 | 'font-lock-variable-name-face) | 1025 | 'font-lock-variable-name-face) |
| 1103 | got-init (and (match-beginning 1) | 1026 | got-init (and (cadr (cddr decl-res)) ; got-init |
| 1104 | (char-after (match-beginning 1)))) | 1027 | (char-after))) |
| 1105 | 1028 | ||
| 1106 | (if types | 1029 | (if types |
| 1107 | ;; Register and fontify the identifier as a type. | 1030 | ;; Register and fontify the identifier as a type. |