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.
This commit is contained in:
rillig 2021-04-09 23:03:26 +00:00
parent 627f7eb200
commit 8ffcb97a78
5 changed files with 21 additions and 23 deletions

View File

@ -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_struct = {
/* 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",
};

View File

@ -8,7 +8,6 @@ d_c99_init.c(219): error: array subscript cannot be > 4: 5 [168]
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 struct/union initializers [172]
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]

View File

@ -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) */
}

View File

@ -6,5 +6,3 @@ d_init_array_using_string.c(59): error: cannot initialize 'array[10] of const ch
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]

View File

@ -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(const struct brace_level *bl)
}
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 brace_level *bl)
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 brace_level *bl)
/* 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_level *bl)
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 initialization *in)
* 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 initialization *in)
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(struct initialization *in, tnode_t *tn)
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(struct initialization *in, tnode_t *tn)
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 initialization *in, tnode_t *tn)
if (bl != NULL)
brace_level_apply_designation(bl);
tp = initialization_sub_type(in);
tp = initialization_sub_type(in, false);
if (tp == NULL)
goto done;