On 07/23/2016 01:18 PM, Martin Sebor wrote:
+ /* A pair of the first non-static non-empty data members following
+ either the flexible array member, if found, or the zero-length
+ array member otherwise. AFTER[1] refers to the first such data
+ member of a union that the struct containing the flexible array
+ member or zero-length array is a member, or NULL when no such
+ union exists. AFTER[0] refers to the first such data member
+ that is not a member of such a union. */
This is pretty hard to follow, could you add an example? Why do we want
to track these separately rather than look at DECL_CONTEXT at diagnostic
time?
+ /* The type in which an anonymous struct or union containing ARRAY
+ is defined or null if no such anonymous struct or union exists. */
+ tree anonctx;
It seems clearer to find this at diagnostic time by following TYPE_CONTEXT.
/* Find the next non-static data member if it exists. */
for (next = fld;
(next = DECL_CHAIN (next))
&& TREE_CODE (next) != FIELD_DECL; );
I think next_initializable_field would be useful here.
if (TREE_CODE (fld) != TYPE_DECL
&& RECORD_OR_UNION_TYPE_P (fldtype)
- && TYPE_ANONYMOUS_P (fldtype))
+ && VAR_DECL != TREE_CODE (fld)
+ && (FIELD_DECL != TREE_CODE (fld) || !DECL_FIELD_IS_BASE (fld)))
Please put the constant on the RHS of comparisons.
It seems that you're only interested in FIELD_DECL here, so maybe move
up the
/* Skip anything that's not a (non-static) data member. */
if (TREE_CODE (fld) != FIELD_DECL)
continue;
and remove the checks for TYPE_DECL and VAR_DECL? For that matter, you
could also move up the DECL_ARTIFICIAL check so you don't need to check
DECL_FIELD_IS_BASE.
+ /* Is the member an anonymous struct or union? */
+ bool anon_p = (!TYPE_ANONYMOUS_P (fldtype)
+ || !DECL_NAME (fld)
+ || anon_aggrname_p (DECL_NAME (fld)));
This looks like anon_p will be true for any non-static data member of
non-anonymous type? Maybe you want ANON_AGGR_TYPE_P?
+ /* If this member isn't anonymous and a prior non-flexible array
+ member has been seen in one of the enclosing structs, clear
+ the FIRST member since it doesn't contribute to the flexible
+ array struct's members. */
+ if (first && !array && !anon_p)
+ fmem->first = NULL_TREE;
Why is this needed? For a non-anonymous member, presumably we'll give
an error when analyzing the type of the member on its own, so we
shouldn't need to complain again here.
/* Replace the zero-length array if it's been stored and
reset the after pointer. */
if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
{
fmem->after[bool (pun)] = NULL_TREE;
fmem->array = fld;
}
So we silently allow a zero-length array followed by a flexible array? Why?
+ msg = G_("zero-size array member %qD in an otherwise empty %q#T");
+
+ if (msg && pedwarn (DECL_SOURCE_LOCATION (fmem->array),
+ OPT_Wpedantic, msg, fmem->array, fmemctx))
+ {
+ inform (location_of (t), "in the definition of %q#T", fmemctx);
+
+ /* Prevent the same flexible array member from being diagnosed
+ more than once if it happens to be nested in more than one
+ union and overlap with another member. This avoids multiple
+ warnings for perverse cases like the the following where
+ U::U1::X::a1 would otherwise be diagnosed first followed by
+ S::U1::X::a1:
+ struct S {
+ union U {
+ union U1 { struct X { int n1, a1[]; } x1; } u1;
+ union U2 { struct X { int n2, a2[]; } x1; } u2;
+ } u;
+ } s;
+ */
+ TREE_NO_WARNING (fmem->array) = 1;
+ }
There doesn't seem to be anything that checks TREE_NO_WARNING for the
zero-size array case.
+ /* Avoid issuing further duiagnostics after the error above. */
Typo.
if (fmem == &flexmems
&& !TYPE_ANONYMOUS_P (t) && !anon_aggrname_p (TYPE_IDENTIFIER (t)))
I think you want ANON_AGGR_TYPE_P here, too.
I also wonder about integrating this with layout_class_type, since that
is also looking at layout issues.
Jason