Module Name:    src
Committed By:   rillig
Date:           Fri Apr  9 23:03:26 UTC 2021

Modified Files:
        src/tests/usr.bin/xlint/lint1: d_c99_init.c d_c99_init.exp
            d_init_array_using_string.c d_init_array_using_string.exp
        src/usr.bin/xlint/lint1: init.c

Log Message:
lint: fix initialization with brace-enclosed string literal

C99 allows this form in 6.7.8p14 and p15.

The previous lint tests did not cover the case of an array at the top
level of the object to be initialized, they only covered the error cases
(d_c99_init.c, variables 'prefixed_message' and 'message_with_suffix').

Lint is now more generous than strictly required by C99, but since GCC
and Clang already cover the case of 'message_with_suffix', this is ok.

The test d_init_array_using_string.c was wrong before in rejecting the
initializer for 'extra_braces'.  I had tested that Clang generated a
warning for this, but I had not inspected its warning carefully enough.
Clang had not warned about the extra braces but only about a type
mismatch since I tested on a platform where wchar_t was 16 bit.


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.33 src/tests/usr.bin/xlint/lint1/d_c99_init.c
cvs rdiff -u -r1.25 -r1.26 src/tests/usr.bin/xlint/lint1/d_c99_init.exp
cvs rdiff -u -r1.3 -r1.4 \
    src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c \
    src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp
cvs rdiff -u -r1.193 -r1.194 src/usr.bin/xlint/lint1/init.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/usr.bin/xlint/lint1/d_c99_init.c
diff -u src/tests/usr.bin/xlint/lint1/d_c99_init.c:1.32 src/tests/usr.bin/xlint/lint1/d_c99_init.c:1.33
--- src/tests/usr.bin/xlint/lint1/d_c99_init.c:1.32	Fri Apr  9 22:08:14 2021
+++ src/tests/usr.bin/xlint/lint1/d_c99_init.c	Fri Apr  9 23:03:26 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: d_c99_init.c,v 1.32 2021/04/09 22:08:14 rillig Exp $	*/
+/*	$NetBSD: d_c99_init.c,v 1.33 2021/04/09 23:03:26 rillig Exp $	*/
 # 3 "d_c99_init.c"
 
 /*
@@ -237,8 +237,8 @@ char prefixed_message[] = {
 };
 
 char message_with_suffix[] = {
-	"message",		/* expect: illegal combination */
-	/* */
+	"message",
+	/* The excess character is not detected by lint but by compilers. */
 	'\n',
 };
 
@@ -389,6 +389,5 @@ struct point designator_for_scalar_in_st
 
 /* Seen in pcidevs_data.h, variable 'pci_words'. */
 const char string_initialized_with_braced_literal[] = {
-	/* FIXME: *//* expect+1: illegal combination of integer (char) and pointer (pointer to char) [183] */
 	"initializer",
 };

Index: src/tests/usr.bin/xlint/lint1/d_c99_init.exp
diff -u src/tests/usr.bin/xlint/lint1/d_c99_init.exp:1.25 src/tests/usr.bin/xlint/lint1/d_c99_init.exp:1.26
--- src/tests/usr.bin/xlint/lint1/d_c99_init.exp:1.25	Fri Apr  9 22:08:14 2021
+++ src/tests/usr.bin/xlint/lint1/d_c99_init.exp	Fri Apr  9 23:03:26 2021
@@ -8,7 +8,6 @@ d_c99_init.c(219): error: array subscrip
 d_c99_init.c(221): error: array subscript cannot be > 1: 2 [168]
 d_c99_init.c(230): error: too many struct/union initializers [172]
 d_c99_init.c(236): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
-d_c99_init.c(240): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
 d_c99_init.c(321): error: duplicate case in switch: 0 [199]
 d_c99_init.c(330): error: type 'struct point' does not have member 'r' [101]
 d_c99_init.c(337): error: type 'struct point' does not have member 'r' [101]
@@ -24,4 +23,3 @@ d_c99_init.c(377): error: too many struc
 d_c99_init.c(381): error: syntax error 'scalar type cannot use designator' [249]
 d_c99_init.c(385): error: syntax error 'scalar type cannot use designator' [249]
 d_c99_init.c(386): error: syntax error 'scalar type cannot use designator' [249]
-d_c99_init.c(393): warning: illegal combination of integer (char) and pointer (pointer to char) [183]

Index: src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c
diff -u src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c:1.3 src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c:1.4
--- src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c:1.3	Tue Mar 30 14:25:28 2021
+++ src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c	Fri Apr  9 23:03:26 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: d_init_array_using_string.c,v 1.3 2021/03/30 14:25:28 rillig Exp $	*/
+/*	$NetBSD: d_init_array_using_string.c,v 1.4 2021/04/09 23:03:26 rillig Exp $	*/
 # 3 "d_init_array_using_string.c"
 
 /*
@@ -74,6 +74,4 @@ test_array_initialization_in_struct(void
 		{ "" },
 		{ L"" },
 	};
-	/* expect-3: illegal combination of integer (char) and pointer (pointer to char) */
-	/* expect-3: illegal combination of integer (int) and pointer (pointer to int) */
 }
Index: src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp
diff -u src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp:1.3 src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp:1.4
--- src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp:1.3	Tue Mar 30 14:25:28 2021
+++ src/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp	Fri Apr  9 23:03:26 2021
@@ -6,5 +6,3 @@ d_init_array_using_string.c(59): error: 
 d_init_array_using_string.c(60): error: cannot initialize 'array[10] of const int' from 'pointer to char' [185]
 d_init_array_using_string.c(69): warning: non-null byte ignored in string initializer [187]
 d_init_array_using_string.c(70): warning: non-null byte ignored in string initializer [187]
-d_init_array_using_string.c(74): warning: illegal combination of integer (char) and pointer (pointer to char) [183]
-d_init_array_using_string.c(75): warning: illegal combination of integer (int) and pointer (pointer to int) [183]

Index: src/usr.bin/xlint/lint1/init.c
diff -u src/usr.bin/xlint/lint1/init.c:1.193 src/usr.bin/xlint/lint1/init.c:1.194
--- src/usr.bin/xlint/lint1/init.c:1.193	Fri Apr  2 14:50:47 2021
+++ src/usr.bin/xlint/lint1/init.c	Fri Apr  9 23:03:26 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: init.c,v 1.193 2021/04/02 14:50:47 rillig Exp $	*/
+/*	$NetBSD: init.c,v 1.194 2021/04/09 23:03:26 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: init.c,v 1.193 2021/04/02 14:50:47 rillig Exp $");
+__RCSID("$NetBSD: init.c,v 1.194 2021/04/09 23:03:26 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -599,7 +599,7 @@ brace_level_sub_type_struct_or_union(con
 }
 
 static const type_t *
-brace_level_sub_type_array(const struct brace_level *bl)
+brace_level_sub_type_array(const struct brace_level *bl, bool is_string)
 {
 
 	if (!bl->bl_confused && !bl->bl_type->t_incomplete_array &&
@@ -608,6 +608,10 @@ brace_level_sub_type_array(const struct 
 		error(173, bl->bl_type->t_dim);
 	}
 
+	if (is_string && bl->bl_subscript == 0 &&
+	    bl->bl_type->t_subt->t_tspec != ARRAY)
+		return bl->bl_type;
+
 	return bl->bl_type->t_subt;
 }
 
@@ -625,7 +629,7 @@ brace_level_sub_type_scalar(const struct
 
 /* Return the type of the sub-object that is currently being initialized. */
 static const type_t *
-brace_level_sub_type(const struct brace_level *bl)
+brace_level_sub_type(const struct brace_level *bl, bool is_string)
 {
 
 	if (bl->bl_designation.dn_head != NULL)
@@ -636,7 +640,7 @@ brace_level_sub_type(const struct brace_
 	case UNION:
 		return brace_level_sub_type_struct_or_union(bl);
 	case ARRAY:
-		return brace_level_sub_type_array(bl);
+		return brace_level_sub_type_array(bl, is_string);
 	default:
 		return brace_level_sub_type_scalar(bl);
 	}
@@ -750,12 +754,12 @@ initialization_debug(const struct initia
  * initialized.
  */
 static const type_t *
-initialization_sub_type(struct initialization *in)
+initialization_sub_type(struct initialization *in, bool is_string)
 {
 	const type_t *tp;
 
 	tp = in->in_brace_level != NULL
-	    ? brace_level_sub_type(in->in_brace_level)
+	    ? brace_level_sub_type(in->in_brace_level, is_string)
 	    : in->in_sym->s_type;
 	if (tp == NULL)
 		in->in_err = true;
@@ -772,7 +776,7 @@ initialization_begin_brace_level(struct 
 
 	debug_enter();
 
-	tp = initialization_sub_type(in);
+	tp = initialization_sub_type(in, false);
 	if (tp == NULL) {
 		in->in_err = true;
 		goto done;
@@ -893,7 +897,7 @@ initialization_init_array_using_string(s
 		return false;
 
 	bl = in->in_brace_level;
-	tp = initialization_sub_type(in);
+	tp = initialization_sub_type(in, true);
 	strg = tn->tn_string;
 
 	if (!is_string_array(tp, strg->st_tspec))
@@ -901,14 +905,15 @@ initialization_init_array_using_string(s
 	if (bl != NULL && tp->t_tspec != ARRAY && bl->bl_subscript != 0)
 		return false;
 
-	if (bl != NULL && tp->t_dim < (int)strg->st_len) {
+	if (!tp->t_incomplete_array && tp->t_dim < (int)strg->st_len) {
 		/* non-null byte ignored in string initializer */
 		warning(187);
 	}
 
 	if (tp == in->in_sym->s_type && tp->t_incomplete_array) {
 		if (bl != NULL) {
-			bl->bl_subscript = strg->st_len + 1;
+			bl->bl_subscript = strg->st_len;
+			/* see brace_level_advance for the +1 */
 			/* see initialization_set_size_of_unknown_array */
 		} else
 			update_type_of_array_of_unknown_size(in->in_sym,
@@ -946,7 +951,7 @@ initialization_expr(struct initializatio
 
 	if (bl != NULL)
 		brace_level_apply_designation(bl);
-	tp = initialization_sub_type(in);
+	tp = initialization_sub_type(in, false);
 	if (tp == NULL)
 		goto done;
 

Reply via email to