Sun Feb 27 19:32:51 2022 UTC ()
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.


(rillig)
diff -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/msg_219.c
diff -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/msg_219.exp
diff -r1.3 -r1.4 src/tests/usr.bin/xlint/lint1/msg_292.c
diff -r1.3 -r1.4 src/tests/usr.bin/xlint/lint1/msg_292.exp
diff -r1.385 -r1.386 src/usr.bin/xlint/lint1/cgram.y

cvs diff -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/msg_219.c (expand / switch to unified diff)

--- 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
9char concat1[] = "one"; 9char concat1[] = "one";
10char concat2[] = "one" "two"; /* expect: 219 */ 10/* expect+1: warning: concatenated strings are illegal in traditional C [219] */
11char concat3[] = "one" "two" "three"; /* expect: 219 */ 11char concat2[] = "one" "two";
12char 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] */
 14char 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] */
 18char concat4[] = "one" "two" "three" "four";
13 19
14char concat4lines[] = 20char 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";

cvs diff -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/Attic/msg_219.exp (expand / switch to unified diff)

--- 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 @@
1msg_219.c(10): warning: concatenated strings are illegal in traditional C [219] 
2msg_219.c(11): warning: concatenated strings are illegal in traditional C [219] 1msg_219.c(11): warning: concatenated strings are illegal in traditional C [219]
3msg_219.c(12): warning: concatenated strings are illegal in traditional C [219] 2msg_219.c(14): warning: concatenated strings are illegal in traditional C [219]
4msg_219.c(17): warning: concatenated strings are illegal in traditional C [219] 3msg_219.c(14): warning: concatenated strings are illegal in traditional C [219]
 4msg_219.c(18): warning: concatenated strings are illegal in traditional C [219]
 5msg_219.c(18): warning: concatenated strings are illegal in traditional C [219]
 6msg_219.c(18): warning: concatenated strings are illegal in traditional C [219]
 7msg_219.c(23): warning: concatenated strings are illegal in traditional C [219]
 8msg_219.c(25): warning: concatenated strings are illegal in traditional C [219]
 9msg_219.c(27): warning: concatenated strings are illegal in traditional C [219]

cvs diff -r1.3 -r1.4 src/tests/usr.bin/xlint/lint1/msg_292.c (expand / switch to unified diff)

--- 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
6const char c_c_c_w_w_w[] = 6const 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] */
18typedef int reveal_sizeof_c_c_c_w_w_w[-(int)sizeof(c_c_c_w_w_w)]; 18typedef int reveal_sizeof_c_c_c_w_w_w[-(int)sizeof(c_c_c_w_w_w)];
19 19
20const char c_w_c_w_c_w[] = 20const 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] */ 
39typedef int reveal_sizeof_c_w_c_w_c_w[-(int)sizeof(c_w_c_w_c_w)]; 31typedef int reveal_sizeof_c_w_c_w_c_w[-(int)sizeof(c_w_c_w_c_w)];

cvs diff -r1.3 -r1.4 src/tests/usr.bin/xlint/lint1/Attic/msg_292.exp (expand / switch to unified diff)

--- 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 @@
1msg_292.c(11): error: cannot concatenate wide and regular string literals [292] 1msg_292.c(11): error: cannot concatenate wide and regular string literals [292]
2msg_292.c(13): error: cannot concatenate wide and regular string literals [292] 2msg_292.c(13): error: cannot concatenate wide and regular string literals [292]
3msg_292.c(15): error: cannot concatenate wide and regular string literals [292] 3msg_292.c(15): error: cannot concatenate wide and regular string literals [292]
4msg_292.c(18): error: negative array dimension (-15) [20] 4msg_292.c(18): error: negative array dimension (-15) [20]
5msg_292.c(24): error: cannot concatenate wide and regular string literals [292] 5msg_292.c(23): error: cannot concatenate wide and regular string literals [292]
6msg_292.c(27): error: cannot concatenate wide and regular string literals [292] 6msg_292.c(26): error: cannot concatenate wide and regular string literals [292]
7msg_292.c(29): error: cannot concatenate wide and regular string literals [292] 7msg_292.c(29): error: cannot concatenate wide and regular string literals [292]
8msg_292.c(39): error: negative array dimension (-3) [20] 8msg_292.c(31): error: negative array dimension (-15) [20]

cvs diff -r1.385 -r1.386 src/usr.bin/xlint/lint1/cgram.y (expand / switch to unified diff)

--- 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
47extern char *yytext; 47extern 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 */
406string: 405string:
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 */ 
414string2: 
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 */
428primary_expression: 417primary_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;