c: Don't emit -Wunterminated-string-initialization warning for multi-dimensional nonstring array initializers [PR117178]

My/Kees' earlier patches adjusted -Wunterminated-string-initialization
warning so that it doesn't warn about initializers of nonstring decls
and that nonstring attribute is allowed on multi-dimensional arrays.
Unfortunately as this testcase shows, we still warn about initializers
of multi-dimensional array nonstring decls.

The problem is that in that case field passed to output_init_element
is actually INTEGER_CST, index into the array.
For RECORD_OR_UNION_TYPE_P (constructor_type) field is a FIELD_DECL
which we want to use, but otherwise (in arrays) IMHO we want to use
constructor_fields (which is the innermost FIELD_DECL whose part
is being initialized), or - if that is NULL - constructor_decl, the
whole decl being initialized with multi-dimensional array type.

2025-03-11  Jakub Jelinek  <jakub@redhat.com>

	PR c/117178
	* c-typeck.cc (output_init_element): Pass field to digest_init
	only for record/union types, otherwise pass constructor_fields
	if non-NULL and constructor_decl if constructor_fields is NULL.

	* gcc.dg/Wunterminated-string-initialization-2.c: New test.
This commit is contained in:
Jakub Jelinek 2025-03-11 23:08:38 +01:00 committed by Jakub Jelinek
parent 799ed87bcf
commit afb46540d3
2 changed files with 125 additions and 1 deletions

View file

@ -11419,7 +11419,11 @@ output_init_element (location_t loc, tree value, tree origtype,
if (!require_constexpr_value
|| !npc
|| TREE_CODE (constructor_type) != POINTER_TYPE)
new_value = digest_init (loc, field, type, new_value, origtype, npc,
new_value = digest_init (loc,
RECORD_OR_UNION_TYPE_P (constructor_type)
? field : constructor_fields
? constructor_fields : constructor_decl,
type, new_value, origtype, npc,
int_const_expr, arith_const_expr, strict_string,
require_constant_value, require_constexpr_value);
if (new_value == error_mark_node)

View file

@ -0,0 +1,120 @@
/* PR c/117178 */
/* { dg-do compile } */
/* { dg-options "-Wunterminated-string-initialization" } */
const char a[][4] __attribute__((nonstring)) = {
"ABCD",
"EFGH",
"IJK",
"LMNO"
};
const char b[][2][2] __attribute__((nonstring)) = {
{ "PQ",
"R" },
{ "S",
"TU" }
};
struct S { int c; char d[3][5] __attribute__((nonstring)); int e; } f = {
0,
{ "abcde",
"defg",
"hijkl" },
1
};
struct T { int g; char h[3][2][2] __attribute__((nonstring)); int i; } j = {
0,
{ { "m",
"no" },
{ "pq",
"r" },
{ "s",
"tu" } },
1
};
const char k[][4] = {
"ABCD", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
"EFGH", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
"IJK",
"LMNO" /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
};
const char l[][2][2] = {
{ "PQ", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
"R" },
{ "S",
"TU" } /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
};
struct U { int m; char n[3][5]; int o; } p = {
0,
{ "abcde", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(6 chars into 5 available\\\)" } */
"defg",
"hijkl" }, /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(6 chars into 5 available\\\)" } */
1
};
struct V { int q; char r[3][2][2]; int s; } t = {
0,
{ { "m",
"no" }, /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
{ "pq", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
"r" },
{ "s",
"tu" } }, /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
1
};
const char u[][4] __attribute__((nonstring)) = {
[3] = "ABCD",
[1] = "EFGH",
"IJK",
[0] = "LMNO"
};
const char v[][2][2] __attribute__((nonstring)) = {
[1][1] = "PQ",
[0][1] = "R",
[0][0] = "S",
[1][0] = "TU"
};
struct S w = {
0,
{ [2] = "abcde",
[0] = "defg",
[1] = "hijkl" },
1
};
struct T x = {
.i = 0,
.h = { [2][1] = "m",
[1][1] = "no",
[0][0] = "pq" },
.h[1][0] = "r",
.h[2][0] = "s",
.g = 1,
.h[0][1] = "tu"
};
const char y[][4] = {
[3] = "ABCD", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
[1] = "EFGH", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
"IJK",
[0] = "LMNO" /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(5 chars into 4 available\\\)" } */
};
const char z[][2][2] = {
[1][1] = "PQ", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
[0][1] = "R",
[0][0] = "S",
[1][0] = "TU" /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
};
struct U aa = {
0,
{ [2] = "abcde", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(6 chars into 5 available\\\)" } */
[0] = "defg",
[1] = "hijkl" }, /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(6 chars into 5 available\\\)" } */
1
};
struct V ab = {
.s = 0,
.r = { [2][1] = "m",
[1][1] = "no", /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
[0][0] = "pq" }, /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
.r[1][0] = "r",
.r[2][0] = "s",
.q = 1,
.r[0][1] = "tu" /* { dg-warning "initializer-string for array of 'char' truncates NUL terminator but destination lacks 'nonstring' attribute \\\(3 chars into 2 available\\\)" } */
};