lint: concatenate string literals from left to right Previously, the string literals "1" "2" "3" "4" were concatenated in the order "23", "234", "1234". This influenced the location of the diagnostics for traditional C (which doesn't know concatenation at all) and for mixing regular strings and wide strings. Now the diagnostics occur exactly where they are expected. The first string literal defines whether the whole string is regular or wide, and any further string literals must match it. In traditional C mode, there are more diagnostics than before, but that doesn't hurt since they are still correct and nobody uses lint in traditional C mode anyway.diff -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/msg_219.c
(rillig)
--- src/tests/usr.bin/xlint/lint1/msg_219.c 2022/02/27 18:57:16 1.4
+++ src/tests/usr.bin/xlint/lint1/msg_219.c 2022/02/27 19:32:51 1.5
@@ -1,19 +1,27 @@ | @@ -1,19 +1,27 @@ | |||
1 | /* $NetBSD: msg_219.c,v 1.4 2022/02/27 18:57:16 rillig Exp $ */ | 1 | /* $NetBSD: msg_219.c,v 1.5 2022/02/27 19:32:51 rillig Exp $ */ | |
2 | # 3 "msg_219.c" | 2 | # 3 "msg_219.c" | |
3 | 3 | |||
4 | 4 | |||
5 | /* Test for message: concatenated strings are illegal in traditional C [219] */ | 5 | /* Test for message: concatenated strings are illegal in traditional C [219] */ | |
6 | 6 | |||
7 | /* lint1-flags: -t -w */ | 7 | /* lint1-flags: -t -w */ | |
8 | 8 | |||
9 | char concat1[] = "one"; | 9 | char concat1[] = "one"; | |
10 | char concat2[] = "one" "two"; /* expect: 219 */ | 10 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |
11 | char concat3[] = "one" "two" "three"; /* expect: 219 */ | 11 | char concat2[] = "one" "two"; | |
12 | char concat4[] = "one" "two" "three" "four"; /* expect: 219 */ | 12 | /* expect+2: warning: concatenated strings are illegal in traditional C [219] */ | |
13 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |||
14 | char concat3[] = "one" "two" "three"; | |||
15 | /* expect+3: warning: concatenated strings are illegal in traditional C [219] */ | |||
16 | /* expect+2: warning: concatenated strings are illegal in traditional C [219] */ | |||
17 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |||
18 | char concat4[] = "one" "two" "three" "four"; | |||
13 | 19 | |||
14 | char concat4lines[] = | 20 | char concat4lines[] = | |
15 | "one" | 21 | "one" | |
16 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | 22 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |
17 | "two" | 23 | "two" | |
24 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |||
18 | "three" | 25 | "three" | |
26 | /* expect+1: warning: concatenated strings are illegal in traditional C [219] */ | |||
19 | "four"; | 27 | "four"; |
--- src/tests/usr.bin/xlint/lint1/Attic/msg_219.exp 2022/02/27 18:57:16 1.4
+++ src/tests/usr.bin/xlint/lint1/Attic/msg_219.exp 2022/02/27 19:32:51 1.5
@@ -1,4 +1,9 @@ | @@ -1,4 +1,9 @@ | |||
1 | msg_219.c(10): warning: concatenated strings are illegal in traditional C [219] | |||
2 | msg_219.c(11): warning: concatenated strings are illegal in traditional C [219] | 1 | msg_219.c(11): warning: concatenated strings are illegal in traditional C [219] | |
3 | msg_219.c(12): warning: concatenated strings are illegal in traditional C [219] | 2 | msg_219.c(14): warning: concatenated strings are illegal in traditional C [219] | |
4 | msg_219.c(17): warning: concatenated strings are illegal in traditional C [219] | 3 | msg_219.c(14): warning: concatenated strings are illegal in traditional C [219] | |
4 | msg_219.c(18): warning: concatenated strings are illegal in traditional C [219] | |||
5 | msg_219.c(18): warning: concatenated strings are illegal in traditional C [219] | |||
6 | msg_219.c(18): warning: concatenated strings are illegal in traditional C [219] | |||
7 | msg_219.c(23): warning: concatenated strings are illegal in traditional C [219] | |||
8 | msg_219.c(25): warning: concatenated strings are illegal in traditional C [219] | |||
9 | msg_219.c(27): warning: concatenated strings are illegal in traditional C [219] |
--- src/tests/usr.bin/xlint/lint1/msg_292.c 2022/02/27 18:51:21 1.3
+++ src/tests/usr.bin/xlint/lint1/msg_292.c 2022/02/27 19:32:51 1.4
@@ -1,39 +1,31 @@ | @@ -1,39 +1,31 @@ | |||
1 | /* $NetBSD: msg_292.c,v 1.3 2022/02/27 18:51:21 rillig Exp $ */ | 1 | /* $NetBSD: msg_292.c,v 1.4 2022/02/27 19:32:51 rillig Exp $ */ | |
2 | # 3 "msg_292.c" | 2 | # 3 "msg_292.c" | |
3 | 3 | |||
4 | // Test for message: cannot concatenate wide and regular string literals [292] | 4 | // Test for message: cannot concatenate wide and regular string literals [292] | |
5 | 5 | |||
6 | const char c_c_c_w_w_w[] = | 6 | const char c_c_c_w_w_w[] = | |
7 | "c2" | 7 | "c2" | |
8 | "c 4" | 8 | "c 4" | |
9 | "c 8" | 9 | "c 8" | |
10 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 10 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
11 | L"w2" | 11 | L"w2" | |
12 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 12 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
13 | L"w 4" | 13 | L"w 4" | |
14 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 14 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
15 | L"w 8"; | 15 | L"w 8"; | |
16 | /* The 15 results from 2 + 4 + 8 + '\0'. */ | 16 | /* The 15 results from 2 + 4 + 8 + '\0'. */ | |
17 | /* expect+1: error: negative array dimension (-15) [20] */ | 17 | /* expect+1: error: negative array dimension (-15) [20] */ | |
18 | typedef int reveal_sizeof_c_c_c_w_w_w[-(int)sizeof(c_c_c_w_w_w)]; | 18 | typedef int reveal_sizeof_c_c_c_w_w_w[-(int)sizeof(c_c_c_w_w_w)]; | |
19 | 19 | |||
20 | const char c_w_c_w_c_w[] = | 20 | const char c_w_c_w_c_w[] = | |
21 | "c2" | 21 | "c2" | |
22 | L"w2" | |||
23 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 22 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
23 | L"w2" | |||
24 | "c 4" | 24 | "c 4" | |
25 | L"w 4" | |||
26 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 25 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
26 | L"w 4" | |||
27 | "c 8" | 27 | "c 8" | |
28 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | 28 | /* expect+1: error: cannot concatenate wide and regular string literals [292] */ | |
29 | L"w 8"; | 29 | L"w 8"; | |
30 | /* | 30 | /* expect+1: error: negative array dimension (-15) [20] */ | |
31 | * Concatenating L"w2" with "c4" fails, keeping L"w2". | |||
32 | * Concatenating L"w2" with L"w4" succeeds, resulting in L"w2w4". | |||
33 | * Concatenating L"w2w4" with "c8" fails, keeping L"w2w4". | |||
34 | * Concatenating L"w2w4" with L"w8" succeeds, resulting in L"w2w4w8". | |||
35 | * Concatenating "c2" with L"w2w4w8" fails, keeping "c2". | |||
36 | * The size of "c2" is 3. | |||
37 | */ | |||
38 | /* expect+1: error: negative array dimension (-3) [20] */ | |||
39 | typedef int reveal_sizeof_c_w_c_w_c_w[-(int)sizeof(c_w_c_w_c_w)]; | 31 | typedef int reveal_sizeof_c_w_c_w_c_w[-(int)sizeof(c_w_c_w_c_w)]; |
--- src/tests/usr.bin/xlint/lint1/Attic/msg_292.exp 2022/02/27 18:51:21 1.3
+++ src/tests/usr.bin/xlint/lint1/Attic/msg_292.exp 2022/02/27 19:32:51 1.4
@@ -1,8 +1,8 @@ | @@ -1,8 +1,8 @@ | |||
1 | msg_292.c(11): error: cannot concatenate wide and regular string literals [292] | 1 | msg_292.c(11): error: cannot concatenate wide and regular string literals [292] | |
2 | msg_292.c(13): error: cannot concatenate wide and regular string literals [292] | 2 | msg_292.c(13): error: cannot concatenate wide and regular string literals [292] | |
3 | msg_292.c(15): error: cannot concatenate wide and regular string literals [292] | 3 | msg_292.c(15): error: cannot concatenate wide and regular string literals [292] | |
4 | msg_292.c(18): error: negative array dimension (-15) [20] | 4 | msg_292.c(18): error: negative array dimension (-15) [20] | |
5 | msg_292.c(24): error: cannot concatenate wide and regular string literals [292] | 5 | msg_292.c(23): error: cannot concatenate wide and regular string literals [292] | |
6 | msg_292.c(27): error: cannot concatenate wide and regular string literals [292] | 6 | msg_292.c(26): error: cannot concatenate wide and regular string literals [292] | |
7 | msg_292.c(29): error: cannot concatenate wide and regular string literals [292] | 7 | msg_292.c(29): error: cannot concatenate wide and regular string literals [292] | |
8 | msg_292.c(39): error: negative array dimension (-3) [20] | 8 | msg_292.c(31): error: negative array dimension (-15) [20] |
--- src/usr.bin/xlint/lint1/cgram.y 2022/02/27 11:40:29 1.385
+++ src/usr.bin/xlint/lint1/cgram.y 2022/02/27 19:32:51 1.386
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | %{ | 1 | %{ | |
2 | /* $NetBSD: cgram.y,v 1.385 2022/02/27 11:40:29 rillig Exp $ */ | 2 | /* $NetBSD: cgram.y,v 1.386 2022/02/27 19:32:51 rillig Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. | 5 | * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. | |
6 | * Copyright (c) 1994, 1995 Jochen Pohl | 6 | * Copyright (c) 1994, 1995 Jochen Pohl | |
7 | * All Rights Reserved. | 7 | * All Rights Reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
@@ -25,27 +25,27 @@ | @@ -25,27 +25,27 @@ | |||
25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | #include <sys/cdefs.h> | 36 | #include <sys/cdefs.h> | |
37 | #if defined(__RCSID) && !defined(lint) | 37 | #if defined(__RCSID) && !defined(lint) | |
38 | __RCSID("$NetBSD: cgram.y,v 1.385 2022/02/27 11:40:29 rillig Exp $"); | 38 | __RCSID("$NetBSD: cgram.y,v 1.386 2022/02/27 19:32:51 rillig Exp $"); | |
39 | #endif | 39 | #endif | |
40 | 40 | |||
41 | #include <limits.h> | 41 | #include <limits.h> | |
42 | #include <stdlib.h> | 42 | #include <stdlib.h> | |
43 | #include <string.h> | 43 | #include <string.h> | |
44 | 44 | |||
45 | #include "lint1.h" | 45 | #include "lint1.h" | |
46 | 46 | |||
47 | extern char *yytext; | 47 | extern char *yytext; | |
48 | 48 | |||
49 | /* | 49 | /* | |
50 | * Contains the level of current declaration, used for symbol table entries. | 50 | * Contains the level of current declaration, used for symbol table entries. | |
51 | * 0 is the top-level, > 0 is inside a function body. | 51 | * 0 is the top-level, > 0 is inside a function body. | |
@@ -282,27 +282,26 @@ anonymize(sym_t *s) | @@ -282,27 +282,26 @@ anonymize(sym_t *s) | |||
282 | %left T_RELATIONAL | 282 | %left T_RELATIONAL | |
283 | %left T_SHIFT | 283 | %left T_SHIFT | |
284 | %left T_ADDITIVE | 284 | %left T_ADDITIVE | |
285 | %left T_ASTERISK T_MULTIPLICATIVE | 285 | %left T_ASTERISK T_MULTIPLICATIVE | |
286 | 286 | |||
287 | %token <y_name> T_NAME | 287 | %token <y_name> T_NAME | |
288 | %token <y_name> T_TYPENAME | 288 | %token <y_name> T_TYPENAME | |
289 | %token <y_val> T_CON | 289 | %token <y_val> T_CON | |
290 | %token <y_string> T_STRING | 290 | %token <y_string> T_STRING | |
291 | 291 | |||
292 | %type <y_sym> identifier_sym | 292 | %type <y_sym> identifier_sym | |
293 | %type <y_name> identifier | 293 | %type <y_name> identifier | |
294 | %type <y_string> string | 294 | %type <y_string> string | |
295 | %type <y_string> string2 | |||
296 | 295 | |||
297 | %type <y_tnode> primary_expression | 296 | %type <y_tnode> primary_expression | |
298 | %type <y_tnode> generic_selection | 297 | %type <y_tnode> generic_selection | |
299 | %type <y_generic> generic_assoc_list | 298 | %type <y_generic> generic_assoc_list | |
300 | %type <y_generic> generic_association | 299 | %type <y_generic> generic_association | |
301 | %type <y_tnode> postfix_expression | 300 | %type <y_tnode> postfix_expression | |
302 | %type <y_tnode> gcc_statement_expr_list | 301 | %type <y_tnode> gcc_statement_expr_list | |
303 | %type <y_tnode> gcc_statement_expr_item | 302 | %type <y_tnode> gcc_statement_expr_item | |
304 | %type <y_op> point_or_arrow | 303 | %type <y_op> point_or_arrow | |
305 | %type <y_tnode> argument_expression_list | 304 | %type <y_tnode> argument_expression_list | |
306 | %type <y_tnode> unary_expression | 305 | %type <y_tnode> unary_expression | |
307 | %type <y_tnode> cast_expression | 306 | %type <y_tnode> cast_expression | |
308 | %type <y_tnode> conditional_expression | 307 | %type <y_tnode> conditional_expression | |
@@ -395,41 +394,31 @@ identifier: | @@ -395,41 +394,31 @@ identifier: | |||
395 | T_NAME { | 394 | T_NAME { | |
396 | debug_step("cgram: name '%s'", $1->sb_name); | 395 | debug_step("cgram: name '%s'", $1->sb_name); | |
397 | $$ = $1; | 396 | $$ = $1; | |
398 | } | 397 | } | |
399 | | T_TYPENAME { | 398 | | T_TYPENAME { | |
400 | debug_step("cgram: typename '%s'", $1->sb_name); | 399 | debug_step("cgram: typename '%s'", $1->sb_name); | |
401 | $$ = $1; | 400 | $$ = $1; | |
402 | } | 401 | } | |
403 | ; | 402 | ; | |
404 | 403 | |||
405 | /* see C99 6.4.5, string literals are joined by 5.1.1.2 */ | 404 | /* see C99 6.4.5, string literals are joined by 5.1.1.2 */ | |
406 | string: | 405 | string: | |
407 | T_STRING | 406 | T_STRING | |
408 | | T_STRING string2 { | 407 | | string T_STRING { | |
409 | $$ = cat_strings($1, $2); | |||
410 | } | |||
411 | ; | |||
412 | ||||
413 | /* see C99 6.4.5, string literals are joined by 5.1.1.2 */ | |||
414 | string2: | |||
415 | T_STRING { | |||
416 | if (tflag) { | 408 | if (tflag) { | |
417 | /* concatenated strings are illegal in traditional C */ | 409 | /* concatenated strings are illegal in traditional C */ | |
418 | warning(219); | 410 | warning(219); | |
419 | } | 411 | } | |
420 | $$ = $1; | |||
421 | } | |||
422 | | string2 T_STRING { | |||
423 | $$ = cat_strings($1, $2); | 412 | $$ = cat_strings($1, $2); | |
424 | } | 413 | } | |
425 | ; | 414 | ; | |
426 | 415 | |||
427 | /* K&R 7.1, C90 ???, C99 6.5.1, C11 6.5.1 */ | 416 | /* K&R 7.1, C90 ???, C99 6.5.1, C11 6.5.1 */ | |
428 | primary_expression: | 417 | primary_expression: | |
429 | T_NAME { | 418 | T_NAME { | |
430 | bool sys_name, sys_next; | 419 | bool sys_name, sys_next; | |
431 | sys_name = in_system_header; | 420 | sys_name = in_system_header; | |
432 | if (yychar < 0) | 421 | if (yychar < 0) | |
433 | yychar = yylex(); | 422 | yychar = yylex(); | |
434 | sys_next = in_system_header; | 423 | sys_next = in_system_header; | |
435 | in_system_header = sys_name; | 424 | in_system_header = sys_name; |