Commit 96032047 by Martin Sebor

PR c++/71912 - [6/7 regression] flexible array in struct in union rejected

gcc/cp/ChangeLog:

	PR c++/71912
	* class.c (struct flexmems_t):  Add members.
	(find_flexarrays): Add arguments.  Correct handling of anonymous
	structs.
	(diagnose_flexarrays): Adjust to issue warnings in addition to errors.
	(check_flexarrays): Add argument.
	(diagnose_invalid_flexarray): New functions.

gcc/testsuite/ChangeLog:

	PR c++/71912
	* g++.dg/ext/flexary4.C: Adjust.
	* g++.dg/ext/flexary5.C: Same.
	* g++.dg/ext/flexary9.C: Same.
	* g++.dg/ext/flexary19.C: New test.
	* g++.dg/ext/flexary18.C: New test.
	* g++.dg/torture/pr64312.C: Add a dg-error directive to an ill-formed
	regression test.
        * g++.dg/compat/struct-layout-1_generate.c (subfield): Add argument.
        Avoid generating a flexible array member in an array.

From-SVN: r241143
parent 253abb2a
2016-10-13 Martin Sebor <msebor@redhat.com>
PR c++/71912
* class.c (struct flexmems_t): Add members.
(find_flexarrays): Add arguments. Correct handling of anonymous
structs.
(diagnose_flexarrays): Adjust to issue warnings in addition to errors.
(check_flexarrays): Add argument.
(diagnose_invalid_flexarray): New functions.
2016-10-13 Jakub Jelinek <jakub@redhat.com>
Jason Merrill <jason@redhat.com>
......@@ -39,6 +49,7 @@
* decl.c (mark_inline_variable): New.
>>>>>>> .r241142
2016-10-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
* decl2.c: Include memmodel.h.
......
......@@ -27,6 +27,19 @@
2016-10-13 Martin Sebor <msebor@redhat.com>
PR c++/71912
* g++.dg/ext/flexary4.C: Adjust.
* g++.dg/ext/flexary5.C: Same.
* g++.dg/ext/flexary9.C: Same.
* g++.dg/ext/flexary19.C: New test.
* g++.dg/ext/flexary18.C: New test.
* g++.dg/torture/pr64312.C: Add a dg-error directive to an ill-formed
regression test.
* g++.dg/compat/struct-layout-1_generate.c (subfield): Add argument.
Avoid generating a flexible array member in an array.
2016-10-13 Martin Sebor <msebor@redhat.com>
* gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Cast 0 to wint_t
to placate -Wformat on targets where the type is not int.
......@@ -1853,6 +1866,12 @@
* gcc.target/msp430/function-attributes-2.c: New test.
* gcc.target/msp430/function-attributes-3.c: New test.
2015-04-18 Martin Sebor <msebor@redhat.com>
* gfortran.dg/pr32627.f03 (strptr): Change size to match the number
of non-nul characters.
* gfortran.dg/substr_6.f90: Make the NUL character visible on stdout
2016-09-13 Jakub Jelinek <jakub@redhat.com>
* g++.dg/cpp0x/gen-attrs-61.C: New test.
......
......@@ -495,7 +495,16 @@ struct types attrib_array_types[] = {
#define HASH_SIZE 32749
static struct entry *hash_table[HASH_SIZE];
static int idx, limidx, output_one, short_enums;
/* The index of the current type being output. */
static int idx;
/* The maximum index of the type(s) to output. */
static int limidx;
/* Set to non-zero to output a single type in response to the -i option
(which sets LIMIDX to the index of the type to output. */
static int output_one;
static int short_enums;
static const char *destdir;
static const char *srcdir;
static const char *srcdir_safe;
......@@ -535,6 +544,7 @@ switchfiles (int fields)
fputs ("failed to create test files\n", stderr);
exit (1);
}
for (i = 0; i < NDG_OPTIONS; i++)
fprintf (outfile, dg_options[i], "", srcdir_safe);
fprintf (outfile, "\n\
......@@ -607,9 +617,14 @@ getrandll (void)
/* Generate a subfield. The object pointed to by FLEX is set to a non-zero
value when the generated field is a flexible array member. When set, it
prevents subsequent fields from being generated (a flexible array mem*/
prevents subsequent fields from being generated (a flexible array member
must be the last member of the struct it's defined in). ARRAY is non-
zero when the enclosing structure is part of an array. In that case,
avoid generating a flexible array member as a subfield (such a member
would be invalid). */
int
subfield (struct entry *e, char *letter, int *flex)
subfield (struct entry *e, char *letter, int *flex, int array)
{
int i, type;
char buf[20];
......@@ -664,7 +679,14 @@ subfield (struct entry *e, char *letter, int *flex)
}
for (i = 1; !*flex && i <= e[0].len; )
i += subfield (e + i, letter, flex);
{
/* Avoid generating flexible array members if the enclosing
type is an array. */
int array
= (e[0].etype == ETYPE_STRUCT_ARRAY
|| e[0].etype == ETYPE_UNION_ARRAY);
i += subfield (e + i, letter, flex, array);
}
switch (type)
{
......@@ -685,7 +707,7 @@ subfield (struct entry *e, char *letter, int *flex)
case ETYPE_ARRAY:
if (e[0].etype == ETYPE_ARRAY)
{
if (e[0].arr_len == 255)
if (!array && e[0].arr_len == 255)
{
*flex = 1;
snprintf (buf, 20, "%c[]", *letter);
......@@ -1141,6 +1163,7 @@ e_insert (struct entry *e)
hash_table[hval % HASH_SIZE] = e;
}
/* Output a single type. */
void
output (struct entry *e)
{
......@@ -1169,7 +1192,7 @@ output (struct entry *e)
int flex = 0;
for (i = 1; i <= e[0].len; )
i += subfield (e + i, &c, &flex);
i += subfield (e + i, &c, &flex, 0);
fputs (",", outfile);
c = 'a';
......
// PR c++/71912 - [6/7 regression] flexible array in struct in union rejected
// { dg-do compile }
// { dg-additional-options "-Wpedantic -Wno-error=pedantic" }
#if __cplusplus
namespace pr71912 {
#endif
struct foo {
int a;
char s[]; // { dg-message "array member .char pr71912::foo::s \\\[\\\]. declared here" }
};
struct bar {
double d;
char t[];
};
struct baz {
union {
struct foo f;
struct bar b;
}
// The definition of struct foo is fine but the use of struct foo
// in the definition of u below is what's invalid and must be clearly
// diagnosed.
u; // { dg-warning "invalid use of .struct pr71912::foo. with a flexible array member in .struct pr71912::baz." }
};
struct xyyzy {
union {
struct {
int a;
char s[]; // { dg-message "declared here" }
} f;
struct {
double d;
char t[];
} b;
} u; // { dg-warning "invalid use" }
};
struct baz b;
struct xyyzy x;
#if __cplusplus
}
#endif
// The following definitions aren't strictly valid but, like those above,
// are accepted for compatibility with GCC (in C mode). They are benign
// in that the flexible array member is at the highest offset within
// the outermost type and doesn't overlap with other members except for
// those of the union.
union UnionStruct1 {
struct { int n1, a[]; } s;
int n2;
};
union UnionStruct2 {
struct { int n1, a1[]; } s1;
struct { int n2, a2[]; } s2;
int n3;
};
union UnionStruct3 {
struct { int n1, a1[]; } s1;
struct { double n2, a2[]; } s2;
char n3;
};
union UnionStruct4 {
struct { int n1, a1[]; } s1;
struct { struct { int n2, a2[]; } s2; } s3;
char n3;
};
union UnionStruct5 {
struct { struct { int n1, a1[]; } s1; } s2; // { dg-warning "invalid use" }
struct { double n2, a2[]; } s3;
char n3;
};
union UnionStruct6 {
struct { struct { int n1, a1[]; } s1; } s2; // { dg-warning "invalid use" }
struct { struct { int n2, a2[]; } s3; } s4;
char n3;
};
union UnionStruct7 {
struct { int n1, a1[]; } s1;
struct { double n2, a2[]; } s2;
struct { struct { int n3, a3[]; } s3; } s4;
};
union UnionStruct8 {
struct { int n1, a1[]; } s1;
struct { struct { int n2, a2[]; } s2; } s3;
struct { struct { int n3, a3[]; } s4; } s5;
};
union UnionStruct9 {
struct { struct { int n1, a1[]; } s1; } s2; // { dg-warning "invalid use" }
struct { struct { int n2, a2[]; } s3; } s4;
struct { struct { int n3, a3[]; } s5; } s6;
};
struct StructUnion1 {
union {
struct { int n1, a1[]; } s1; // { dg-message "declared here" }
struct { double n2, a2[]; } s2;
char n3;
} u; // { dg-warning "invalid use" }
};
// The following are invalid and rejected.
struct StructUnion2 {
union {
struct { int n1, a1[]; } s1; // { dg-error "not at end" }
} u;
char n3; // { dg-message "next member" }
};
struct StructUnion3 {
union {
struct { int n1, a1[]; } s1; // { dg-error "not at end" }
struct { double n2, a2[]; } s2;
} u;
char n3; // { dg-message "next member" }
};
struct StructUnion4 {
union {
struct { int n1, a1[]; } s1; // { dg-error "not at end" }
} u1;
union {
struct { double n2, a2[]; } s2;
} u2; // { dg-message "next member" }
};
struct StructUnion5 {
union {
union {
struct { int n1, a1[]; } s1; // { dg-message "declared here" }
} u1;
union { struct { int n2, a2[]; } s2; } u2;
} u; // { dg-warning "invalid use" }
};
struct StructUnion6 {
union {
struct { int n1, a1[]; } s1; // { dg-message "declared here" }
union { struct { int n2, a2[]; } s2; } u2;
} u; // { dg-warning "invalid use" }
};
struct StructUnion7 {
union {
union {
struct { double n2, a2[]; } s2; // { dg-message "declared here" }
} u2;
struct { int n1, a1[]; } s1;
} u; // { dg-warning "invalid use" }
};
struct StructUnion8 {
struct {
union {
union {
struct { int n1, a1[]; } s1; // { dg-error "not at end" }
} u1;
union {
struct { double n2, a2[]; } s2;
} u2;
} u;
} s1;
struct {
union {
union {
struct { int n1, a1[]; } s1;
} u1;
union {
struct { double n2, a2[]; } s2;
} u2;
} u; } s2; // { dg-message "next member" }
};
struct StructUnion9 { // { dg-message "in the definition" }
struct A1 {
union B1 {
union C1 {
struct Sx1 { int n1, a1[]; } sx1; // { dg-error "not at end" }
} c1;
union D1 {
struct Sx2 { double n2, a2[]; } sx2;
} d1;
} b1; // { dg-warning "invalid use" }
} a1;
struct A2 {
union B2 {
union C2 {
struct Sx3 { int n3, a3[]; } sx3; // { dg-message "declared here" }
} c2;
union D2 { struct Sx4 { double n4, a4[]; } sx4; } d2;
} b2; // { dg-warning "invalid use" }
} a2; // { dg-message "next member" }
};
// { dg-do compile }
// { dg-additional-options "-Wpedantic -Wno-error=pedantic" }
// Verify that flexible array members are recognized as either valid
// or invalid in anonymous structs (a G++ extension) and C++ anonymous
// unions as well as in structs and unions that look anonymous but
// aren't.
struct S1
{
int i;
// The following declares a named data member of an unnamed struct
// (i.e., it is not an anonymous struct).
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s;
};
struct S2
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s[1];
};
struct S3
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s[];
};
struct S4
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s[2];
};
struct S5
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s[1][2];
};
struct S6
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s[][2];
};
struct S7
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} *s;
};
struct S8
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} **s;
};
struct S9
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} *s[1];
};
struct S10
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} *s[];
};
struct S11
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} **s[1];
};
struct S12
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} **s[];
};
struct S13
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} **s[2];
};
struct S14
{
int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} &s;
};
struct S15
{
int i;
typedef struct {
int a[]; // { dg-error "in an otherwise empty" }
} T15;
};
struct S16
{
int i;
struct { // { dg-warning "invalid use" }
// A flexible array as a sole member of an anonymous struct is
// rejected with an error in C mode but emits just a pedantic
// warning in C++. Other than excessive pedantry there is no
// reason to reject it.
int a[];
}; // { dg-warning "anonymous struct" }
};
struct S17
{
int i;
union { // anonymous union
int a[]; // { dg-error "flexible array member in union" }
};
};
struct S18
{
int i;
struct {
int j, a[]; // { dg-message "declared here" }
} s; // { dg-warning "invalid use" }
};
struct S19
{
int i;
struct { // { dg-warning "invalid use" }
int j, a[]; // { dg-message "declared here" }
}; // { dg-warning "anonymous struct" }
};
struct S20
{
static int i;
typedef int A[];
struct {
int j;
A a; // { dg-message "declared here" }
} s; // { dg-warning "invalid use" }
};
struct S21
{
static int i;
typedef int A[];
struct { // { dg-warning "invalid use" }
int j;
A a; // { dg-message "declared here" }
}; // { dg-warning "anonymous struct" }
};
struct S22
{
struct S22S {
static int i;
int a[]; // { dg-error "in an otherwise empty" }
} s;
};
struct S23
{
struct {
static int i; // { dg-error "static data member" }
int a[]; // { dg-error "in an otherwise empty" }
}; // { dg-warning "anonymous struct" }
};
struct S24
{
static int i;
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s;
};
struct S25
{
int i;
struct {
int j, a[]; // { dg-message "declared here" }
} s; // { dg-warning "invalid use" }
// Verify that a static data member of the enclosing class doesn't
// cause infinite recursion or some such badness.
static S25 s2;
};
struct S26
{
template <class>
struct S26S {
static int a;
};
struct {
int a[]; // { dg-error "in an otherwise empty" }
} s;
};
struct S27
{
S27 *p;
int a[];
};
struct S28
{
struct A {
struct B {
S28 *ps28;
A *pa;
B *pb;
} b, *pb;
A *pa;
} a, *pa;
S28::A *pa2;
S28::A::B *pb;
int flexarray[];
};
// Verify that the notes printed along with the warnings point to the types
// or members they should point to and mention the correct relationships
// with the flexible array members.
namespace Notes
{
union A
{
struct {
struct {
int i, a[]; // { dg-message "declared here" }
} c; // { dg-warning "invalid use" }
} d;
int j;
};
union B
{
struct {
struct { // { dg-warning "invalid use" }
int i, a[]; // { dg-message "declared here" }
}; // { dg-warning "anonymous struct" }
}; // { dg-warning "anonymous struct" }
int j;
};
}
typedef struct Opaque* P29;
struct S30 { P29 p; };
struct S31 { S30 s; };
typedef struct { } S32;
typedef struct { S32 *ps32; } S33;
typedef struct
{
S33 *ps33;
} S34;
struct S35
{
struct A {
int i1, a1[];
};
struct B {
int i2, a2[];
};
typedef struct {
int i3, a3[];
} C;
typedef struct {
int i4, a4[];
} D;
typedef A A2;
typedef B B2;
typedef C C2;
typedef D D2;
};
......@@ -102,31 +102,28 @@ struct Sx17 {
int a_0 [0];
};
// Empty structs are a GCC extension that (in C++ only) is treated
// as if it had a single member of type char. Therefore, a struct
// An empty struct is treated as if it had a single member of type
// char but the member cannot be accessed. Therefore, a struct
// containing a flexible array member followed by an empty struct
// is diagnosed to prevent the former subobject from sharing space
// with the latter.
struct Sx18 {
int a_x []; // { dg-error "flexible array member" }
struct S { };
struct { /* empty */ } s;
};
// Anonymous structs and unions are another GCC extension. Since
// they cannot be named and thus used to store the size of a flexible
// array member, a struct containing both is diagnosed as if
// the flexible array member appeared alone.
// Anonymous structs are a G++ extension. Members of anonymous structs
// are treated as if they were declared in the enclosing class.
struct Sx19 {
struct S { };
union U { };
int a_x []; // { dg-error "in an otherwise empty" }
struct { int i; }; // anonymous struct
int a_x [];
};
// Unlike in the case above, a named member of an anonymous struct
// prevents a subsequent flexible array member from being diagnosed.
// Unlike in the case above, a named struct is not anonymous and
// so doesn't contribute its member to that of the enclosing struct.
struct Sx20 {
struct S { } s;
int a_x [];
struct S { int i; };
int a_x []; // { dg-error "in an otherwise empty" }
};
struct Sx21 {
......@@ -298,6 +295,15 @@ struct Anon1 {
ASSERT_AT_END (Anon1, good);
struct NotAnon1 {
int n;
// The following is not an anonymous struct -- the type is unnamed
// but the object has a name.
struct {
int bad[]; // { dg-error "otherwise empty" }
} name;
};
struct Anon2 {
struct {
int n;
......@@ -352,7 +358,6 @@ struct Anon7 {
int n;
};
struct Six {
int i;
int a[];
......
......@@ -64,19 +64,29 @@ struct D5: E1, E2, NE { char a[]; };
ASSERT_AT_END (D5, a); // { dg-warning "offsetof within non-standard-layout" }
struct A2x {
struct A2x_1 {
size_t n;
size_t a[]; // { dg-error "not at end of .struct D6.| D7.| D8." }
size_t a[]; // { dg-error "not at end of .struct D6." }
};
struct A2x_2 {
size_t n;
size_t a[]; // { dg-error "not at end of .struct D7." }
};
struct A2x_3 {
size_t n;
size_t a[]; // { dg-error "not at end of .struct D8." }
};
// Verify that the flexible array member in A2x above is diagnosed
// for each of the three struct defintions below which also derive
// from another struct with a flexible array member.
struct D6: A2x, E1, A1x { };
struct D7: E1, A2x, E2, A1x { };
struct D8: E1, E2, A2x, A1x { };
struct D6: A2x_1, E1, A1x { };
struct D7: E1, A2x_2, E2, A1x { };
struct D8: E1, E2, A2x_3, A1x { };
struct DA2x: A2x { };
struct DA2x: A2x_1 { };
struct D9: DA2x, E1, E2 { };
......@@ -194,16 +204,27 @@ struct NE2: NE { };
struct D28: NE1, AA6x { };
struct D29: AA6x, NE1 { };
// Verify that a flexible array member in a virtual base class is not
// diagnosed.
struct A7x {
size_t n;
size_t a[];
size_t a[]; // { dg-error "flexible array member .A7x::a. not at end of .struct D33." }
};
// Verify that a flexible array member in a virtual base class is not
// diagnosed.
struct DA7xV1: virtual A7x { };
struct DA7xV2: virtual A7x { };
struct D30: DA7xV1, DA7xV2 { };
struct D31: DA7xV1, DA7xV2 { };
struct D32: D30, D31 { };
// Verify the diagnostic when the flexible array is in an anonymous struct.
struct A8x {
struct { // { dg-message "next member .A8x::<unnamed struct> A8x::<anonymous>. declared here" }
size_t n;
size_t a[];
};
};
struct D33: // { dg-message "in the definition of .struct D33." }
A7x, A8x { };
......@@ -281,15 +281,15 @@ struct S_S_S_x {
struct Anon1 {
int n;
struct {
int good[0]; // { dg-warning "zero-size array" }
struct { // { dg-warning "invalid use \[^\n\r\]* with a zero-size array" }
int good[0]; // { dg-warning "forbids zero-size array" }
}; // { dg-warning "anonymous struct" }
};
ASSERT_AT_END (Anon1, good);
struct Anon2 {
struct {
struct { // { dg-warning "invalid use" }
int n;
struct {
int good[0]; // { dg-warning "zero-size array" }
......@@ -300,7 +300,7 @@ struct Anon2 {
ASSERT_AT_END (Anon2, good);
struct Anon3 {
struct {
struct { // { dg-warning "invalid use" }
struct {
int n;
int good[0]; // { dg-warning "zero-size array" }
......
......@@ -44,7 +44,7 @@ class F
{
public:
int nelems;
int elems[];
int elems[]; // { dg-error "not at end" }
int *
m_fn1 ()
{
......@@ -88,7 +88,7 @@ public:
m_impl->~any_incrementable_iterator_interface ();
}
G m_buffer;
any_incrementable_iterator_interface *m_impl;
any_incrementable_iterator_interface *m_impl; // { dg-message "next member" }
};
template <class Reference> class K : public I<any_iterator<Reference> >
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment