mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
c: Give permerror for excess braces in scalar initializers [PR88642]
As noted in bug 88642, the C front end fails to give errors or pedwarns for scalar initializers with too many levels of surrounding braces. There is a warning for redundant braces around a scalar initializer within a larger braced initializer (valid for a single such level within a structure, union or array initializer; not valid for more than one such level, or where the outer layer of braces is itself for a scalar, either redundant braces themselves or part of a compound literal), but this never becomes an error even for invalid cases. Check for this case and turn the warning into a permerror when there are more levels of braces than permitted. The existing warning is unchanged for a single (permitted) level of redundant braces around a scalar initializer inside a structure, union or array initializer, and it's also unchanged that no such warning is given for a single (permitted) level of redundant braces around a top-level scalar initializer. Technically this is a C2y issue (these rules on valid initializers moved into Constraints as a result of N3346, accepted in Minneapolis; previously, as a "shall" outside constraints, violating these rules resulted in compile-time undefined behavior without requiring a diagnostic). Hopefully little code is actually relying on not getting an error here. In view of gcc.dg/tree-ssa/ssa-dse-10.c showing that at least some code may be using such over-braced initializers (initializer of pubKeys at line 1167 in that test; I'm not at all sure how that initializer ends up getting interpreted to translate it to something equivalent but properly structured), this is made a permerror rather than a hard error, so -fpermissive (as already used by that test) can be used to disable the error (the default -fpermissive for old standards modes is not a problem given that before C2y this is undefined behavior not a constraint violation). Bootstrapped with no regressions for x86_64-pc-linux-gnu. PR c/88642 gcc/c/ * c-typeck.cc (constructor_braced_scalar): New variable. (struct constructor_stack): Add braced_scalar field. (really_start_incremental_init): Handle constructor_braced_scalar and braced_scalar field. (push_init_level): Handle constructor_braced_scalar and braced_scalar field. Give permerror rather than warning for nested braces around scalar initializer. (pop_init_level): Handle constructor_braced_scalar and braced_scalar field. gcc/testsuite/ * gcc.dg/c2y-init-1.c: New test.
This commit is contained in:
@@ -10132,6 +10132,10 @@ static int constructor_zeroinit;
|
||||
/* 1 if this constructor should have padding bits zeroed (C23 {}. */
|
||||
static bool constructor_zero_padding_bits;
|
||||
|
||||
/* 1 if this constructor is a braced scalar initializer (further nested levels
|
||||
of braces are an error). */
|
||||
static bool constructor_braced_scalar;
|
||||
|
||||
/* Structure for managing pending initializer elements, organized as an
|
||||
AVL tree. */
|
||||
|
||||
@@ -10203,6 +10207,7 @@ struct constructor_stack
|
||||
char incremental;
|
||||
char designated;
|
||||
bool zero_padding_bits;
|
||||
bool braced_scalar;
|
||||
int designator_depth;
|
||||
};
|
||||
|
||||
@@ -10379,6 +10384,7 @@ really_start_incremental_init (tree type)
|
||||
p->incremental = constructor_incremental;
|
||||
p->designated = constructor_designated;
|
||||
p->zero_padding_bits = constructor_zero_padding_bits;
|
||||
p->braced_scalar = constructor_braced_scalar;
|
||||
p->designator_depth = designator_depth;
|
||||
p->next = 0;
|
||||
constructor_stack = p;
|
||||
@@ -10394,6 +10400,7 @@ really_start_incremental_init (tree type)
|
||||
constructor_designated = 0;
|
||||
constructor_zero_padding_bits = false;
|
||||
constructor_zeroinit = 1;
|
||||
constructor_braced_scalar = false;
|
||||
designator_depth = 0;
|
||||
designator_erroneous = 0;
|
||||
|
||||
@@ -10453,6 +10460,7 @@ really_start_incremental_init (tree type)
|
||||
/* Handle the case of int x = {5}; */
|
||||
constructor_fields = constructor_type;
|
||||
constructor_unfilled_fields = constructor_type;
|
||||
constructor_braced_scalar = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10529,6 +10537,7 @@ push_init_level (location_t loc, int implicit,
|
||||
p->incremental = constructor_incremental;
|
||||
p->designated = constructor_designated;
|
||||
p->zero_padding_bits = constructor_zero_padding_bits;
|
||||
p->braced_scalar = constructor_braced_scalar;
|
||||
p->designator_depth = designator_depth;
|
||||
p->next = constructor_stack;
|
||||
p->range_stack = 0;
|
||||
@@ -10546,6 +10555,7 @@ push_init_level (location_t loc, int implicit,
|
||||
/* If the upper initializer has padding bits zeroed, that includes
|
||||
all nested initializers as well. */
|
||||
constructor_zero_padding_bits = p->zero_padding_bits;
|
||||
constructor_braced_scalar = false;
|
||||
constructor_pending_elts = 0;
|
||||
if (!implicit)
|
||||
{
|
||||
@@ -10664,7 +10674,15 @@ push_init_level (location_t loc, int implicit,
|
||||
else
|
||||
{
|
||||
if (constructor_type != error_mark_node)
|
||||
warning_init (input_location, 0, "braces around scalar initializer");
|
||||
{
|
||||
if (p->braced_scalar)
|
||||
permerror_init (input_location, 0,
|
||||
"braces around scalar initializer");
|
||||
else
|
||||
warning_init (input_location, 0,
|
||||
"braces around scalar initializer");
|
||||
constructor_braced_scalar = true;
|
||||
}
|
||||
constructor_fields = constructor_type;
|
||||
constructor_unfilled_fields = constructor_type;
|
||||
}
|
||||
@@ -10886,6 +10904,7 @@ pop_init_level (location_t loc, int implicit,
|
||||
constructor_incremental = p->incremental;
|
||||
constructor_designated = p->designated;
|
||||
constructor_zero_padding_bits = p->zero_padding_bits;
|
||||
constructor_braced_scalar = p->braced_scalar;
|
||||
designator_depth = p->designator_depth;
|
||||
constructor_pending_elts = p->pending_elts;
|
||||
constructor_depth = p->depth;
|
||||
|
||||
48
gcc/testsuite/gcc.dg/c2y-init-1.c
Normal file
48
gcc/testsuite/gcc.dg/c2y-init-1.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Test invalid initializers that are consistent with the syntax: undefined
|
||||
behavior ("shall" in Semantics not Constraints) before C2y, constraint
|
||||
violation in C2y. Scalar cases; see bug 88642. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=c2y -pedantic-errors" } */
|
||||
|
||||
struct s { int a; };
|
||||
union u { int a; };
|
||||
|
||||
int i1 = { 1, 2 }; /* { dg-error "excess elements in scalar initializer" } */
|
||||
int i2 = { { 1 } }; /* { dg-error "braces around scalar initializer" } */
|
||||
int i3 = { { 1, } }; /* { dg-error "braces around scalar initializer" } */
|
||||
int i4 = { { 1 }, }; /* { dg-error "braces around scalar initializer" } */
|
||||
int i5 = { 1, { } }; /* { dg-error "excess elements in scalar initializer" } */
|
||||
/* { dg-error "braces around scalar initializer" "braces" { target *-*-* } .-1 } */
|
||||
int i6 = { { } }; /* { dg-error "braces around scalar initializer" } */
|
||||
int i7 = { { }, }; /* { dg-error "braces around scalar initializer" } */
|
||||
int i8 = { { { 1 } } }; /* { dg-error "braces around scalar initializer" } */
|
||||
struct s s1 =
|
||||
{
|
||||
{ /* { dg-warning "braces around scalar initializer" } */
|
||||
{ 1 } /* { dg-error "braces around scalar initializer" } */
|
||||
}
|
||||
};
|
||||
union u u1 =
|
||||
{
|
||||
{ /* { dg-warning "braces around scalar initializer" } */
|
||||
{ 1 } /* { dg-error "braces around scalar initializer" } */
|
||||
}
|
||||
};
|
||||
int a1[1] =
|
||||
{
|
||||
{ /* { dg-warning "braces around scalar initializer" } */
|
||||
{ 1 } /* { dg-error "braces around scalar initializer" } */
|
||||
}
|
||||
};
|
||||
int *p1 = &(int) { { 1 } }; /* { dg-error "braces around scalar initializer" } */
|
||||
int *p2 = &(int) { { 1, } }; /* { dg-error "braces around scalar initializer" } */
|
||||
|
||||
int ok1 = { 1 };
|
||||
struct s ok2 = { { 1 } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
struct s ok3 = { { 1, } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
int *ok4 = &(int) { 1 };
|
||||
int *ok5 = &(int) { 1, };
|
||||
int ok6[1] = { { 1 } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
int ok7[1] = { { 1, } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
union u ok8 = { { 1 } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
union u ok9 = { { 1, } }; /* { dg-warning "braces around scalar initializer" } */
|
||||
Reference in New Issue
Block a user