[V7,2/2] Update documentation to clarify a GCC extension [PR77650]
Checks
Commit Message
on a structure with a C99 flexible array member being nested in
another structure.
"GCC extension accepts a structure containing an ISO C99 "flexible array
member", or a union containing such a structure (possibly recursively)
to be a member of a structure.
There are two situations:
* A structure containing a C99 flexible array member, or a union
containing such a structure, is the last field of another structure,
for example:
struct flex { int length; char data[]; };
union union_flex { int others; struct flex f; };
struct out_flex_struct { int m; struct flex flex_data; };
struct out_flex_union { int n; union union_flex flex_data; };
In the above, both 'out_flex_struct.flex_data.data[]' and
'out_flex_union.flex_data.f.data[]' are considered as flexible
arrays too.
* A structure containing a C99 flexible array member, or a union
containing such a structure, is the middle field of another structure,
for example:
struct flex { int length; char data[]; };
struct mid_flex { int m; struct flex flex_data; int n; };
In the above, 'mid_flex.flex_data.data[]' has undefined behavior.
Compilers do not handle such case consistently, Any code relying on
such case should be modified to ensure that flexible array members
only end up at the ends of structures.
Please use warning option '-Wflex-array-member-not-at-end' to
identify all such cases in the source code and modify them. This
warning will be on by default starting from GCC 15.
"
gcc/c-family/ChangeLog:
* c.opt: New option -Wflex-array-member-not-at-end.
gcc/c/ChangeLog:
* c-decl.cc (finish_struct): Issue warnings for new option.
gcc/ChangeLog:
* doc/extend.texi: Document GCC extension on a structure containing
a flexible array member to be a member of another structure.
gcc/testsuite/ChangeLog:
* gcc.dg/variable-sized-type-flex-array.c: New test.
---
gcc/c-family/c.opt | 5 +++
gcc/c/c-decl.cc | 9 ++++
gcc/doc/extend.texi | 45 ++++++++++++++++++-
.../gcc.dg/variable-sized-type-flex-array.c | 31 +++++++++++++
4 files changed, 89 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
Comments
On Fri, 19 May 2023, Qing Zhao via Gcc-patches wrote:
> +GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
"The GCC extension" or "A GCC extension".
> +@item
> +A structure containing a C99 flexible array member, or a union containing
> +such a structure, is the middle field of another structure, for example:
There might be more than one middle field, and I think this case also
includes where it's the *first* field - any field other than the last.
> +@smallexample
> +struct flex @{ int length; char data[]; @};
> +
> +struct mid_flex @{ int m; struct flex flex_data; int n; @};
> +@end smallexample
> +
> +In the above, @code{mid_flex.flex_data.data[]} has undefined behavior.
And it's not literally mid_flex.flex_data.data[] that has undefined
behavior, but trying to access a member of that array.
> +Compilers do not handle such case consistently, Any code relying on
"such a case", and "," should be "." at the end of a sentence.
Joseph,
Thanks a lot for the review. And sorry for my late reply (just came back from a short vacation).
> On May 19, 2023, at 5:12 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Fri, 19 May 2023, Qing Zhao via Gcc-patches wrote:
>
>> +GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
>
> "The GCC extension" or "A GCC extension".
Okay.
>
>> +@item
>> +A structure containing a C99 flexible array member, or a union containing
>> +such a structure, is the middle field of another structure, for example:
>
> There might be more than one middle field, and I think this case also
> includes where it's the *first* field - any field other than the last.
Good point. Will fix this.
>
>> +@smallexample
>> +struct flex @{ int length; char data[]; @};
>> +
>> +struct mid_flex @{ int m; struct flex flex_data; int n; @};
>> +@end smallexample
>> +
>> +In the above, @code{mid_flex.flex_data.data[]} has undefined behavior.
>
> And it's not literally mid_flex.flex_data.data[] that has undefined
> behavior, but trying to access a member of that array.
Yes, you are right. Will fix this.
>
>> +Compilers do not handle such case consistently, Any code relying on
>
> "such a case", and "," should be "." at the end of a sentence.
Okay, will fix this.
Thanks
Qing
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
Hi, Joseph,
I modified the gcc/doc/extend.texi per your suggestion as following:
Let me know if you have further comment and suggestion on this patch.
I will send out the V8 of the patch after some testing.
Thanks.
Qing.
============================================
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 6425ba57e88..9aedaa802e0 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1754,7 +1754,7 @@ structure or an element of an array. (However, these uses are
permitted by GCC as extensions, see details below.)
@end itemize
-GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
+The GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
member}, or a union containing such a structure (possibly recursively)
to be a member of a structure.
@@ -1776,10 +1776,9 @@ struct out_flex_union @{ int n; union union_flex flex_data; @};
In the above, both @code{out_flex_struct.flex_data.data[]} and
@code{out_flex_union.flex_data.f.data[]} are considered as flexible arrays too.
-
@item
A structure containing a C99 flexible array member, or a union containing
-such a structure, is the middle field of another structure, for example:
+such a structure, is not the last field of another structure, for example:
@smallexample
struct flex @{ int length; char data[]; @};
@@ -1787,12 +1786,12 @@ struct flex @{ int length; char data[]; @};
struct mid_flex @{ int m; struct flex flex_data; int n; @};
@end smallexample
-In the above, @code{mid_flex.flex_data.data[]} has undefined behavior.
-Compilers do not handle such case consistently, Any code relying on
-such case should be modified to ensure that flexible array members
-only end up at the ends of structures.
+In the above, accessing a member of the array @code{mid_flex.flex_data.data[]}
+might have undefined behavior. Compilers do not handle such a case
+consistently. Any code relying on this case should be modified to ensure
+that flexible array members only end up at the ends of structures.
-Please use warning option @option{-Wflex-array-member-not-at-end} to
+Please use the warning option @option{-Wflex-array-member-not-at-end} to
identify all such cases in the source code and modify them. This warning
will be on by default starting from GCC 15.
@end itemize
> On May 19, 2023, at 5:12 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Fri, 19 May 2023, Qing Zhao via Gcc-patches wrote:
>
>> +GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
>
> "The GCC extension" or "A GCC extension".
>
>> +@item
>> +A structure containing a C99 flexible array member, or a union containing
>> +such a structure, is the middle field of another structure, for example:
>
> There might be more than one middle field, and I think this case also
> includes where it's the *first* field - any field other than the last.
>
>> +@smallexample
>> +struct flex @{ int length; char data[]; @};
>> +
>> +struct mid_flex @{ int m; struct flex flex_data; int n; @};
>> +@end smallexample
>> +
>> +In the above, @code{mid_flex.flex_data.data[]} has undefined behavior.
>
> And it's not literally mid_flex.flex_data.data[] that has undefined
> behavior, but trying to access a member of that array.
>
>> +Compilers do not handle such case consistently, Any code relying on
>
> "such a case", and "," should be "." at the end of a sentence.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
@@ -737,6 +737,11 @@ Wformat-truncation=
C ObjC C++ LTO ObjC++ Joined RejectNegative UInteger Var(warn_format_trunc) Warning LangEnabledBy(C ObjC C++ LTO ObjC++,Wformat=, warn_format >= 1, 0) IntegerRange(0, 2)
Warn about calls to snprintf and similar functions that truncate output.
+Wflex-array-member-not-at-end
+C C++ Var(warn_flex_array_member_not_at_end) Warning
+Warn when a structure containing a C99 flexible array member as the last
+field is not at the end of another structure.
+
Wif-not-aligned
C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning
Warn when the field in a struct is not aligned.
@@ -9293,6 +9293,15 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
TYPE_INCLUDE_FLEXARRAY (t)
= is_last_field && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x));
+ if (warn_flex_array_member_not_at_end
+ && !is_last_field
+ && RECORD_OR_UNION_TYPE_P (TREE_TYPE (x))
+ && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x)))
+ warning_at (DECL_SOURCE_LOCATION (x),
+ OPT_Wflex_array_member_not_at_end,
+ "structure containing a flexible array member"
+ " is not at the end of another structure");
+
if (DECL_NAME (x)
|| RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
saw_named_field = true;
@@ -1751,7 +1751,50 @@ Flexible array members may only appear as the last member of a
A structure containing a flexible array member, or a union containing
such a structure (possibly recursively), may not be a member of a
structure or an element of an array. (However, these uses are
-permitted by GCC as extensions.)
+permitted by GCC as extensions, see details below.)
+@end itemize
+
+GCC extension accepts a structure containing an ISO C99 @dfn{flexible array
+member}, or a union containing such a structure (possibly recursively)
+to be a member of a structure.
+
+There are two situations:
+
+@itemize @bullet
+@item
+A structure containing a C99 flexible array member, or a union containing
+such a structure, is the last field of another structure, for example:
+
+@smallexample
+struct flex @{ int length; char data[]; @};
+union union_flex @{ int others; struct flex f; @};
+
+struct out_flex_struct @{ int m; struct flex flex_data; @};
+struct out_flex_union @{ int n; union union_flex flex_data; @};
+@end smallexample
+
+In the above, both @code{out_flex_struct.flex_data.data[]} and
+@code{out_flex_union.flex_data.f.data[]} are considered as flexible arrays too.
+
+
+@item
+A structure containing a C99 flexible array member, or a union containing
+such a structure, is the middle field of another structure, for example:
+
+@smallexample
+struct flex @{ int length; char data[]; @};
+
+struct mid_flex @{ int m; struct flex flex_data; int n; @};
+@end smallexample
+
+In the above, @code{mid_flex.flex_data.data[]} has undefined behavior.
+Compilers do not handle such case consistently, Any code relying on
+such case should be modified to ensure that flexible array members
+only end up at the ends of structures.
+
+Please use warning option @option{-Wflex-array-member-not-at-end} to
+identify all such cases in the source code and modify them. This warning
+will be on by default starting from GCC 15.
@end itemize
Non-empty initialization of zero-length
new file mode 100644
@@ -0,0 +1,31 @@
+/* Test for -Wflex-array-member-not-at-end on structure/union with
+ C99 flexible array members being embedded into another structure. */
+/* { dg-do compile } */
+/* { dg-options "-Wflex-array-member-not-at-end" } */
+
+struct flex { int n; int data[]; };
+struct out_flex_end { int m; struct flex flex_data; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct out_flex_mid { struct flex flex_data; int m; }; /* { dg-warning "structure containing a flexible array member is not at the end of another structure" } */
+/* since the warning has been issued for out_flex_mid, no need to
+ issue warning again when it is included in another structure/union. */
+struct outer_flex_mid { struct out_flex_mid out_flex_data; int p; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+union flex_union_mid { int a; struct outer_flex_mid b; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+
+
+struct flex0 { int n; int data[0]; };
+struct out_flex_end0 { int m; struct flex0 flex_data; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct out_flex_mid0 { struct flex0 flex_data; int m; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct outer_flex_mid0 { struct out_flex_mid0 out_flex_data; int p; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+union flex_union_mid0 { int a; struct outer_flex_mid0 b; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+
+struct flex1 { int n; int data[1]; };
+struct out_flex_end1 { int m; struct flex1 flex_data; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct out_flex_mid1 { struct flex1 flex_data; int m; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct outer_flex_mid1 { struct out_flex_mid1 out_flex_data; int p; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+union flex_union_mid1 { int a; struct outer_flex_mid1 b; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+
+struct flexn { int n; int data[8]; };
+struct out_flex_endn { int m; struct flexn flex_data; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */
+struct out_flex_midn { struct flexn flex_data; int m; }; /* { dg-bogus"structure containing a flexible array member is not at the end of another structure" } */
+struct outer_flex_midn { struct out_flex_midn out_flex_data; int p; }; /* { dg-bogus"structure containing a flexible array member is not at the end of another structure" } */
+union flex_union_midn { int a; struct outer_flex_midn b; }; /* { dg-bogus "structure containing a flexible array member is not at the end of another structure" } */