public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size
@ 2023-02-11  0:50 Qing Zhao
  2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-11  0:50 UTC (permalink / raw)
  To: joseph, rguenther; +Cc: siddhesh, keescook, gcc-patches, Qing Zhao

These are the 3rd version of the patches for PR101832, to fix
builtin_object_size to correctly handle component_ref to a
structure/union field that includes a flexible array member.

also includes a documentation update for the GCC extension on embedding
a structure/union with flexible array member into another structure.
which includes a fix to PR77650.

compared to the 2nd version of the patch, the major changes are:
1. only include C99 flexible array member to this extension, trailing [0], [1]
   and [4] are all excluded.
2. for the new bit type_include_flexarray in tree_type_common, print it
   and also stream in/out it. 
3. update testing cases.
4. more clarification on the documentation. warnings for deprecating the 
   case when the structure with C99 FAM is embedded in the middle of
   another structure. 
5. add a new warning option -Wgnu-variable-sized-type-not-at-end for
   identifing all such cases.

bootstrapped and regression tested on aarch64 and x86.

Okay for commit?

thanks.

Qing


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832]
  2023-02-11  0:50 [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
@ 2023-02-11  0:50 ` Qing Zhao
  2023-02-17 13:57   ` Qing Zhao
  2023-02-23 14:12   ` Fwd: " Qing Zhao
  2023-02-11  0:50 ` [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650) Qing Zhao
  2023-02-17 13:57 ` [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
  2 siblings, 2 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-11  0:50 UTC (permalink / raw)
  To: joseph, rguenther; +Cc: siddhesh, keescook, gcc-patches, Qing Zhao

GCC extension accepts the case when a struct with a C99 flexible array member
is embedded into another struct or union (possibly recursively).
__builtin_object_size should treat such struct as flexible size.

gcc/c/ChangeLog:

	PR tree-optimization/101832
	* c-decl.cc (finish_struct): Set TYPE_INCLUDE_FLEXARRAY for
	struct/union type.

gcc/cp/ChangeLog:

	PR tree-optimization/101832
	* module.cc (trees_out::core_bools): Stream out new bit
	type_include_flexarray.
	(trees_in::core_bools): Stream in new bit type_include_flexarray.

gcc/ChangeLog:

	PR tree-optimization/101832
	* print-tree.cc (print_node): Print new bit type_include_flexarray.
	* tree-core.h (struct tree_type_common): New bit
	type_include_flexarray.
	* tree-object-size.cc (addr_object_size): Handle structure/union type
	when it has flexible size.
	* tree-streamer-in.cc (unpack_ts_type_common_value_fields): Stream
	in new bit type_include_flexarray.
	* tree-streamer-out.cc (pack_ts_type_common_value_fields): Stream
	out new bit type_include_flexarray.
	* tree.h (TYPE_INCLUDE_FLEXARRAY): New macro
	TYPE_INCLUDE_FLEXARRAY.

gcc/testsuite/ChangeLog:

	PR tree-optimization/101832
	* gcc.dg/builtin-object-size-pr101832.c: New test.
---
 gcc/c/c-decl.cc                               |  12 ++
 gcc/cp/module.cc                              |   2 +
 gcc/print-tree.cc                             |   5 +
 .../gcc.dg/builtin-object-size-pr101832.c     | 134 ++++++++++++++++++
 gcc/tree-core.h                               |   4 +-
 gcc/tree-object-size.cc                       |  79 +++++++----
 gcc/tree-streamer-in.cc                       |   1 +
 gcc/tree-streamer-out.cc                      |   1 +
 gcc/tree.h                                    |   6 +
 9 files changed, 215 insertions(+), 29 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 20e7d1855bf..741a37560b0 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9277,6 +9277,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
       /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x.  */
       DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
 
+      /* Set TYPE_INCLUDE_FLEXARRAY for the context of x, t
+       * when x is an array.  */
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+	TYPE_INCLUDE_FLEXARRAY (t) = flexible_array_member_type_p (TREE_TYPE (x)) ;
+      /* Recursively set TYPE_INCLUDE_FLEXARRAY for the context of x, t
+	 when x is the last field.  */
+      else if ((TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+		|| TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+	       && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x))
+	       && is_last_field)
+	TYPE_INCLUDE_FLEXARRAY (t) = true;
+
       if (DECL_NAME (x)
 	  || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
 	saw_named_field = true;
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index ac2fe66b080..c750361b704 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -5371,6 +5371,7 @@ trees_out::core_bools (tree t)
       WB (t->type_common.lang_flag_5);
       WB (t->type_common.lang_flag_6);
       WB (t->type_common.typeless_storage);
+      WB (t->type_common.type_include_flexarray);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
@@ -5551,6 +5552,7 @@ trees_in::core_bools (tree t)
       RB (t->type_common.lang_flag_5);
       RB (t->type_common.lang_flag_6);
       RB (t->type_common.typeless_storage);
+      RB (t->type_common.type_include_flexarray);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
diff --git a/gcc/print-tree.cc b/gcc/print-tree.cc
index 1f3afcbbc86..efacdb7686f 100644
--- a/gcc/print-tree.cc
+++ b/gcc/print-tree.cc
@@ -631,6 +631,11 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
 	  && TYPE_CXX_ODR_P (node))
 	fputs (" cxx-odr-p", file);
 
+      if ((code == RECORD_TYPE
+	   || code == UNION_TYPE)
+	  && TYPE_INCLUDE_FLEXARRAY (node))
+	fputs (" include-flexarray", file);
+
       /* The transparent-union flag is used for different things in
 	 different nodes.  */
       if ((code == UNION_TYPE || code == RECORD_TYPE)
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
new file mode 100644
index 00000000000..60078e11634
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
@@ -0,0 +1,134 @@
+/* PR 101832: 
+   GCC extension accepts the case when a struct with a C99 flexible array
+   member is embedded into another struct (possibly recursively).
+   __builtin_object_size will treat such struct as flexible size.
+   However, when a structure with non-C99 flexible array member, i.e, trailing
+   [0], [1], or [4], is embedded into anther struct, the stucture will not
+   be treated as flexible size.  */ 
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+
+#define expect(p, _v) do { \
+  size_t v = _v; \
+  if (p == v) \
+    __builtin_printf ("ok:  %s == %zd\n", #p, p); \
+  else {\
+    __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
+    FAIL (); \
+  } \
+} while (0);
+
+
+struct A {
+  int n;
+  char data[];
+};
+
+struct B {
+  int m;
+  struct A a;
+};
+
+struct C {
+  int q;
+  struct B b;
+};
+
+struct A0 {
+  int n;
+  char data[0];
+};
+
+struct B0 {
+  int m;
+  struct A0 a;
+};
+
+struct C0 {
+  int q;
+  struct B0 b;
+};
+
+struct A1 {
+  int n;
+  char data[1];
+};
+
+struct B1 {
+  int m;
+  struct A1 a;
+};
+
+struct C1 {
+  int q;
+  struct B1 b;
+};
+
+struct An {
+  int n;
+  char data[8];
+};
+
+struct Bn {
+  int m;
+  struct An a;
+};
+
+struct Cn {
+  int q;
+  struct Bn b;
+};
+
+volatile void *magic1, *magic2;
+
+int main (int argc, char *argv[])
+{
+  struct B *outer;
+  struct C *outest;
+
+  /* Make sure optimization can't find some other object size. */
+  outer = (void *)magic1;
+  outest = (void *)magic2;
+
+  expect (__builtin_object_size (&outer->a, 1), -1);
+  expect (__builtin_object_size (&outest->b, 1), -1);
+  expect (__builtin_object_size (&outest->b.a, 1), -1);
+
+  struct B0 *outer0;
+  struct C0 *outest0;
+
+  /* Make sure optimization can't find some other object size. */
+  outer0 = (void *)magic1;
+  outest0 = (void *)magic2;
+
+  expect (__builtin_object_size (&outer0->a, 1), sizeof (outer0->a));
+  expect (__builtin_object_size (&outest0->b, 1), sizeof (outest0->b));
+  expect (__builtin_object_size (&outest0->b.a, 1), sizeof (outest0->b.a));
+
+  struct B1 *outer1;
+  struct C1 *outest1;
+
+  /* Make sure optimization can't find some other object size. */
+  outer1 = (void *)magic1;
+  outest1 = (void *)magic2;
+
+  expect (__builtin_object_size (&outer1->a, 1), sizeof (outer1->a));
+  expect (__builtin_object_size (&outest1->b, 1), sizeof (outest1->b));
+  expect (__builtin_object_size (&outest1->b.a, 1), sizeof (outest1->b.a));
+
+  struct Bn *outern;
+  struct Cn *outestn;
+
+  /* Make sure optimization can't find some other object size. */
+  outern = (void *)magic1;
+  outestn = (void *)magic2;
+
+  expect (__builtin_object_size (&outern->a, 1), sizeof (outern->a));
+  expect (__builtin_object_size (&outestn->b, 1), sizeof (outestn->b));
+  expect (__builtin_object_size (&outestn->b.a, 1), sizeof (outestn->b.a));
+
+  DONE ();
+  return 0;
+}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index acd8deea34e..705d5702b9c 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1718,7 +1718,9 @@ struct GTY(()) tree_type_common {
   unsigned empty_flag : 1;
   unsigned indivisible_p : 1;
   unsigned no_named_args_stdarg_p : 1;
-  unsigned spare : 15;
+  /* TYPE_INCLUDE_FLEXARRAY flag for RECORD_TYPE and UNION_TYPE.  */
+  unsigned int type_include_flexarray : 1;
+  unsigned spare : 14;
 
   alias_set_type alias_set;
   tree pointer_to;
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index 9a936a91983..22b3c72ea6e 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -633,45 +633,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
 		    v = NULL_TREE;
 		    break;
 		  case COMPONENT_REF:
-		    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+		    /* When the ref is not to an array, a record or a union, it
+		       will not have flexible size, compute the object size
+		       directly.  */
+		    if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+			&& (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE)
+			&& (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE))
 		      {
 			v = NULL_TREE;
 			break;
 		      }
-		    is_flexible_array_mem_ref = array_ref_flexible_size_p (v);
-		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
-		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			  != UNION_TYPE
-			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			  != QUAL_UNION_TYPE)
-			break;
-		      else
-			v = TREE_OPERAND (v, 0);
-		    if (TREE_CODE (v) == COMPONENT_REF
-			&& TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			   == RECORD_TYPE)
+		    if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE
+			|| TREE_CODE (TREE_TYPE (v)) == UNION_TYPE)
+		    /* if the record or union does not include a flexible array
+		       recursively, compute the object size directly.  */
 		      {
-			/* compute object size only if v is not a
-			   flexible array member.  */
-			if (!is_flexible_array_mem_ref)
+			if (!TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (v)))
 			  {
 			    v = NULL_TREE;
 			    break;
 			  }
-			v = TREE_OPERAND (v, 0);
+			else
+			  v = TREE_OPERAND (v, 0);
 		      }
-		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
-		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			  != UNION_TYPE
-			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-			  != QUAL_UNION_TYPE)
-			break;
-		      else
-			v = TREE_OPERAND (v, 0);
-		    if (v != pt_var)
-		      v = NULL_TREE;
 		    else
-		      v = pt_var;
+		      {
+			/* Now the ref is to an array type.  */
+			is_flexible_array_mem_ref
+			  = array_ref_flexible_size_p (v);
+			while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+			if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+			      != UNION_TYPE
+			    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+				 != QUAL_UNION_TYPE)
+			  break;
+			else
+			  v = TREE_OPERAND (v, 0);
+			if (TREE_CODE (v) == COMPONENT_REF
+			    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+				 == RECORD_TYPE)
+			  {
+			    /* compute object size only if v is not a
+			       flexible array member.  */
+			    if (!is_flexible_array_mem_ref)
+			      {
+				v = NULL_TREE;
+				break;
+			      }
+			    v = TREE_OPERAND (v, 0);
+			  }
+			while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+			  if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+				!= UNION_TYPE
+			      && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+				   != QUAL_UNION_TYPE)
+			    break;
+			  else
+			    v = TREE_OPERAND (v, 0);
+			if (v != pt_var)
+			  v = NULL_TREE;
+			else
+			  v = pt_var;
+		      }
 		    break;
 		  default:
 		    v = pt_var;
diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
index d4dc30f048f..c19ede0631d 100644
--- a/gcc/tree-streamer-in.cc
+++ b/gcc/tree-streamer-in.cc
@@ -390,6 +390,7 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
       TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
       TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
       TYPE_CXX_ODR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+      TYPE_INCLUDE_FLEXARRAY (expr) = (unsigned) bp_unpack_value (bp, 1);
     }
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc
index d107229da5c..73e4b4e547c 100644
--- a/gcc/tree-streamer-out.cc
+++ b/gcc/tree-streamer-out.cc
@@ -357,6 +357,7 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
       bp_pack_value (bp, flag_wpa && TYPE_CANONICAL (expr)
 			 ? TYPE_CXX_ODR_P (TYPE_CANONICAL (expr))
 			 : TYPE_CXX_ODR_P (expr), 1);
+      bp_pack_value (bp, TYPE_INCLUDE_FLEXARRAY (expr), 1);
     }
   else if (TREE_CODE (expr) == ARRAY_TYPE)
     bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
diff --git a/gcc/tree.h b/gcc/tree.h
index c656cd5b7bf..a27b9bb43bc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -778,6 +778,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 #define TYPE_NO_NAMED_ARGS_STDARG_P(NODE) \
   (TYPE_CHECK (NODE)->type_common.no_named_args_stdarg_p)
 
+/* True if this RECORD_TYPE or UNION_TYPE includes a flexible array member
+   at the last field recursively.  */
+#define TYPE_INCLUDE_FLEXARRAY(NODE) \
+  (TYPE_CHECK (NODE)->type_common.type_include_flexarray)
+
+
 /* In an IDENTIFIER_NODE, this means that assemble_name was called with
    this string as an argument.  */
 #define TREE_SYMBOL_REFERENCED(NODE) \
-- 
2.31.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-11  0:50 [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
  2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
@ 2023-02-11  0:50 ` Qing Zhao
  2023-02-17 13:58   ` Qing Zhao
  2023-02-23 14:14   ` Fwd: " Qing Zhao
  2023-02-17 13:57 ` [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
  2 siblings, 2 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-11  0:50 UTC (permalink / raw)
  To: joseph, rguenther; +Cc: siddhesh, keescook, gcc-patches, Qing Zhao

on structure with C99 flexible array member being nested in another structure.

This is also fixed PR77650.

" GCC extension accepts a structure containing a ISO C99 "flexible array
member", or a union containing such a structure (possibly recursively)
to be a member of a structure.

 There are three situations:

   * The structure with a C99 flexible array member is the last field of
     another structure, for example:

          struct flex  { int length; char data[]; };

          struct out_flex { int m; struct flex flex_data; };

     In the above, 'flex_data.data[]' is considered as a flexible array
     too.

   * The structure with a C99 flexible array member is the field of
     another union, for example:

          struct flex1  { int length1; char data1[]; }
          struct flex2  { int length2; char data2[]; }

          union out_flex { struct flex1 flex_data1; struct flex2 flex_data2; }

     In the above, 'flex_data1.data1[]' or 'flex_data2.data2[]' is
     considered as flexible arrays too.

   * The structure with a C99 flexible array member 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, 'flex_data.data[]' is allowed to be extended flexibly
     to the padding.  E.g, up to 4 elements.

     However, relying on space in struct padding is a bad programming
     practice, compilers do not handle such extension consistently, Any
     code relying on this behavior should be modified to ensure that
     flexible array members only end up at the ends of structures.

     Please use warning option '-Wgnu-variable-sized-type-not-at-end' to
     identify all such cases in the source code and modify them.  This
     extension will be deprecated from gcc in the next release. "

gcc/c-family/ChangeLog:

	PR c/77650
	* c.opt: New option -Wgnu-variable-sized-type-not-at-end.

gcc/c/ChangeLog:

	PR c/77650
	* c-decl.cc (finish_struct): Issue warnings for new option.

gcc/ChangeLog:

	PR c/77650
	* doc/extend.texi: Document GCC extension on a structure containing
	a flexible array member to be a member of another structure.

gcc/testsuite/ChangeLog:

	PR c/77650
	* gcc.dg/variable-sized-type-flex-array.c: New test.
---
 gcc/c-family/c.opt                            |  5 ++
 gcc/c/c-decl.cc                               |  7 +++
 gcc/doc/extend.texi                           | 58 ++++++++++++++++++-
 .../gcc.dg/variable-sized-type-flex-array.c   | 31 ++++++++++
 4 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c0fea56a8f5..fd720538800 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -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.
 
+Wgnu-variable-sized-type-not-at-end
+C C++ Var(warn_variable_sized_type_not_at_end) Warning
+Warn about structures or unions with C99 flexible array members are not
+at the end of a 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.
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 741a37560b0..041df4355da 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9289,6 +9289,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 	       && is_last_field)
 	TYPE_INCLUDE_FLEXARRAY (t) = true;
 
+      if (warn_variable_sized_type_not_at_end
+	  && !is_last_field
+	  && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x)))
+	warning_at (DECL_SOURCE_LOCATION (x),
+		    OPT_Wgnu_variable_sized_type_not_at_end,
+		    "variable sized type not at the end of a struct");
+
       if (DECL_NAME (x)
 	  || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
 	saw_named_field = true;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5a026c4b48c..737228b35ac 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1748,7 +1748,63 @@ 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 a ISO C99 @dfn{flexible array
+member}, or a union containing such a structure (possibly recursively)
+to be a member of a structure.
+
+There are three situations:
+
+@itemize @bullet
+@item
+The structure with a C99 flexible array member is the last field of another
+structure, for example:
+
+@smallexample
+struct flex  @{ int length; char data[]; @};
+
+struct out_flex @{ int m; struct flex flex_data; @};
+@end smallexample
+
+In the above, @code{flex_data.data[]} is considered as a flexible array too.
+
+@item
+The structure with a C99 flexible array member is the field of
+another union, for example:
+
+@smallexample
+struct flex1  @{ int length1; char data1[]; @}
+struct flex2  @{ int length2; char data2[]; @}
+
+union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}
+@end smallexample
+
+In the above, @code{flex_data1.data1[]} or @code{flex_data2.data2[]}
+is considered as flexible arrays too.
+
+@item
+The structure with a C99 flexible array member 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{flex_data.data[]} is allowed to be extended flexibly to
+the padding.  E.g, up to 4 elements.
+
+However, relying on space in struct padding is a bad programming practice,
+compilers do not handle such extension consistently, Any code relying on
+this behavior should be modified to ensure that flexible array members
+only end up at the ends of structures.
+
+Please use warning option  @option{-Wgnu-variable-sized-type-not-at-end} to
+identify all such cases in the source code and modify them.  This extension
+will be deprecated from gcc in the next release.
 @end itemize
 
 Non-empty initialization of zero-length
diff --git a/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
new file mode 100644
index 00000000000..e3f65c5ed07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
@@ -0,0 +1,31 @@
+/* Test for -Wgnu-variable-sized-type-not-at-end on structure/union with 
+   C99 flexible array members being embedded into another structure.  */
+/* { dg-do compile } */
+/* { dg-options "-Wgnu-variable-sized-type-not-at-end" } */
+
+struct flex { int n; int data[]; };
+struct out_flex_end { int m; struct flex flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid { struct flex flex_data; int m; };  /* { dg-warning "variable sized type not at the end of a struct" } */
+/* 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 "variable sized type not at the end of a struct" } */
+union flex_union_mid { int a; struct outer_flex_mid b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+
+struct flex0 { int n; int data[0]; };
+struct out_flex_end0 { int m; struct flex0 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid0 { struct flex0 flex_data; int m; };  /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct outer_flex_mid0 { struct out_flex_mid0 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+union flex_union_mid0 { int a; struct outer_flex_mid0 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+struct flex1 { int n; int data[1]; };
+struct out_flex_end1 { int m; struct flex1 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid1 { struct flex1 flex_data; int m; }; /* { dg-bogus "variable sized type not at the end of a struct" } */ 
+struct outer_flex_mid1 { struct out_flex_mid1 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+union flex_union_mid1 { int a; struct outer_flex_mid1 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+struct flexn { int n; int data[8]; }; 
+struct out_flex_endn { int m; struct flexn flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_midn { struct flexn flex_data; int m; }; /* { dg-bogus"variable sized type not at the end of a struct" } */ 
+struct outer_flex_midn { struct out_flex_midn out_flex_data; int p; }; /* { dg-bogus"variable sized type not at the end of a struct" } */
+union flex_union_midn { int a; struct outer_flex_midn b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
-- 
2.31.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size
  2023-02-11  0:50 [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
  2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
  2023-02-11  0:50 ` [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650) Qing Zhao
@ 2023-02-17 13:57 ` Qing Zhao
  2 siblings, 0 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-17 13:57 UTC (permalink / raw)
  To: Joseph Myers, Richard Biener; +Cc: siddhesh, keescook, gcc-patches

Ping…

Qing

> On Feb 10, 2023, at 7:50 PM, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
> These are the 3rd version of the patches for PR101832, to fix
> builtin_object_size to correctly handle component_ref to a
> structure/union field that includes a flexible array member.
> 
> also includes a documentation update for the GCC extension on embedding
> a structure/union with flexible array member into another structure.
> which includes a fix to PR77650.
> 
> compared to the 2nd version of the patch, the major changes are:
> 1. only include C99 flexible array member to this extension, trailing [0], [1]
>   and [4] are all excluded.
> 2. for the new bit type_include_flexarray in tree_type_common, print it
>   and also stream in/out it. 
> 3. update testing cases.
> 4. more clarification on the documentation. warnings for deprecating the 
>   case when the structure with C99 FAM is embedded in the middle of
>   another structure. 
> 5. add a new warning option -Wgnu-variable-sized-type-not-at-end for
>   identifing all such cases.
> 
> bootstrapped and regression tested on aarch64 and x86.
> 
> Okay for commit?
> 
> thanks.
> 
> Qing
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832]
  2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
@ 2023-02-17 13:57   ` Qing Zhao
  2023-02-23 14:12   ` Fwd: " Qing Zhao
  1 sibling, 0 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-17 13:57 UTC (permalink / raw)
  To: Joseph Myers, Richard Biener; +Cc: siddhesh, keescook, gcc-patches

Ping…

Qing

> On Feb 10, 2023, at 7:50 PM, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
> GCC extension accepts the case when a struct with a C99 flexible array member
> is embedded into another struct or union (possibly recursively).
> __builtin_object_size should treat such struct as flexible size.
> 
> gcc/c/ChangeLog:
> 
> 	PR tree-optimization/101832
> 	* c-decl.cc (finish_struct): Set TYPE_INCLUDE_FLEXARRAY for
> 	struct/union type.
> 
> gcc/cp/ChangeLog:
> 
> 	PR tree-optimization/101832
> 	* module.cc (trees_out::core_bools): Stream out new bit
> 	type_include_flexarray.
> 	(trees_in::core_bools): Stream in new bit type_include_flexarray.
> 
> gcc/ChangeLog:
> 
> 	PR tree-optimization/101832
> 	* print-tree.cc (print_node): Print new bit type_include_flexarray.
> 	* tree-core.h (struct tree_type_common): New bit
> 	type_include_flexarray.
> 	* tree-object-size.cc (addr_object_size): Handle structure/union type
> 	when it has flexible size.
> 	* tree-streamer-in.cc (unpack_ts_type_common_value_fields): Stream
> 	in new bit type_include_flexarray.
> 	* tree-streamer-out.cc (pack_ts_type_common_value_fields): Stream
> 	out new bit type_include_flexarray.
> 	* tree.h (TYPE_INCLUDE_FLEXARRAY): New macro
> 	TYPE_INCLUDE_FLEXARRAY.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/101832
> 	* gcc.dg/builtin-object-size-pr101832.c: New test.
> ---
> gcc/c/c-decl.cc                               |  12 ++
> gcc/cp/module.cc                              |   2 +
> gcc/print-tree.cc                             |   5 +
> .../gcc.dg/builtin-object-size-pr101832.c     | 134 ++++++++++++++++++
> gcc/tree-core.h                               |   4 +-
> gcc/tree-object-size.cc                       |  79 +++++++----
> gcc/tree-streamer-in.cc                       |   1 +
> gcc/tree-streamer-out.cc                      |   1 +
> gcc/tree.h                                    |   6 +
> 9 files changed, 215 insertions(+), 29 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
> 
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index 20e7d1855bf..741a37560b0 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -9277,6 +9277,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
>       /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x.  */
>       DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
> 
> +      /* Set TYPE_INCLUDE_FLEXARRAY for the context of x, t
> +       * when x is an array.  */
> +      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
> +	TYPE_INCLUDE_FLEXARRAY (t) = flexible_array_member_type_p (TREE_TYPE (x)) ;
> +      /* Recursively set TYPE_INCLUDE_FLEXARRAY for the context of x, t
> +	 when x is the last field.  */
> +      else if ((TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
> +		|| TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
> +	       && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x))
> +	       && is_last_field)
> +	TYPE_INCLUDE_FLEXARRAY (t) = true;
> +
>       if (DECL_NAME (x)
> 	  || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
> 	saw_named_field = true;
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index ac2fe66b080..c750361b704 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -5371,6 +5371,7 @@ trees_out::core_bools (tree t)
>       WB (t->type_common.lang_flag_5);
>       WB (t->type_common.lang_flag_6);
>       WB (t->type_common.typeless_storage);
> +      WB (t->type_common.type_include_flexarray);
>     }
> 
>   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> @@ -5551,6 +5552,7 @@ trees_in::core_bools (tree t)
>       RB (t->type_common.lang_flag_5);
>       RB (t->type_common.lang_flag_6);
>       RB (t->type_common.typeless_storage);
> +      RB (t->type_common.type_include_flexarray);
>     }
> 
>   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> diff --git a/gcc/print-tree.cc b/gcc/print-tree.cc
> index 1f3afcbbc86..efacdb7686f 100644
> --- a/gcc/print-tree.cc
> +++ b/gcc/print-tree.cc
> @@ -631,6 +631,11 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
> 	  && TYPE_CXX_ODR_P (node))
> 	fputs (" cxx-odr-p", file);
> 
> +      if ((code == RECORD_TYPE
> +	   || code == UNION_TYPE)
> +	  && TYPE_INCLUDE_FLEXARRAY (node))
> +	fputs (" include-flexarray", file);
> +
>       /* The transparent-union flag is used for different things in
> 	 different nodes.  */
>       if ((code == UNION_TYPE || code == RECORD_TYPE)
> diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
> new file mode 100644
> index 00000000000..60078e11634
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
> @@ -0,0 +1,134 @@
> +/* PR 101832: 
> +   GCC extension accepts the case when a struct with a C99 flexible array
> +   member is embedded into another struct (possibly recursively).
> +   __builtin_object_size will treat such struct as flexible size.
> +   However, when a structure with non-C99 flexible array member, i.e, trailing
> +   [0], [1], or [4], is embedded into anther struct, the stucture will not
> +   be treated as flexible size.  */ 
> +/* { dg-do run } */
> +/* { dg-options "-O2" } */
> +
> +#include "builtin-object-size-common.h"
> +
> +#define expect(p, _v) do { \
> +  size_t v = _v; \
> +  if (p == v) \
> +    __builtin_printf ("ok:  %s == %zd\n", #p, p); \
> +  else {\
> +    __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
> +    FAIL (); \
> +  } \
> +} while (0);
> +
> +
> +struct A {
> +  int n;
> +  char data[];
> +};
> +
> +struct B {
> +  int m;
> +  struct A a;
> +};
> +
> +struct C {
> +  int q;
> +  struct B b;
> +};
> +
> +struct A0 {
> +  int n;
> +  char data[0];
> +};
> +
> +struct B0 {
> +  int m;
> +  struct A0 a;
> +};
> +
> +struct C0 {
> +  int q;
> +  struct B0 b;
> +};
> +
> +struct A1 {
> +  int n;
> +  char data[1];
> +};
> +
> +struct B1 {
> +  int m;
> +  struct A1 a;
> +};
> +
> +struct C1 {
> +  int q;
> +  struct B1 b;
> +};
> +
> +struct An {
> +  int n;
> +  char data[8];
> +};
> +
> +struct Bn {
> +  int m;
> +  struct An a;
> +};
> +
> +struct Cn {
> +  int q;
> +  struct Bn b;
> +};
> +
> +volatile void *magic1, *magic2;
> +
> +int main (int argc, char *argv[])
> +{
> +  struct B *outer;
> +  struct C *outest;
> +
> +  /* Make sure optimization can't find some other object size. */
> +  outer = (void *)magic1;
> +  outest = (void *)magic2;
> +
> +  expect (__builtin_object_size (&outer->a, 1), -1);
> +  expect (__builtin_object_size (&outest->b, 1), -1);
> +  expect (__builtin_object_size (&outest->b.a, 1), -1);
> +
> +  struct B0 *outer0;
> +  struct C0 *outest0;
> +
> +  /* Make sure optimization can't find some other object size. */
> +  outer0 = (void *)magic1;
> +  outest0 = (void *)magic2;
> +
> +  expect (__builtin_object_size (&outer0->a, 1), sizeof (outer0->a));
> +  expect (__builtin_object_size (&outest0->b, 1), sizeof (outest0->b));
> +  expect (__builtin_object_size (&outest0->b.a, 1), sizeof (outest0->b.a));
> +
> +  struct B1 *outer1;
> +  struct C1 *outest1;
> +
> +  /* Make sure optimization can't find some other object size. */
> +  outer1 = (void *)magic1;
> +  outest1 = (void *)magic2;
> +
> +  expect (__builtin_object_size (&outer1->a, 1), sizeof (outer1->a));
> +  expect (__builtin_object_size (&outest1->b, 1), sizeof (outest1->b));
> +  expect (__builtin_object_size (&outest1->b.a, 1), sizeof (outest1->b.a));
> +
> +  struct Bn *outern;
> +  struct Cn *outestn;
> +
> +  /* Make sure optimization can't find some other object size. */
> +  outern = (void *)magic1;
> +  outestn = (void *)magic2;
> +
> +  expect (__builtin_object_size (&outern->a, 1), sizeof (outern->a));
> +  expect (__builtin_object_size (&outestn->b, 1), sizeof (outestn->b));
> +  expect (__builtin_object_size (&outestn->b.a, 1), sizeof (outestn->b.a));
> +
> +  DONE ();
> +  return 0;
> +}
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index acd8deea34e..705d5702b9c 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -1718,7 +1718,9 @@ struct GTY(()) tree_type_common {
>   unsigned empty_flag : 1;
>   unsigned indivisible_p : 1;
>   unsigned no_named_args_stdarg_p : 1;
> -  unsigned spare : 15;
> +  /* TYPE_INCLUDE_FLEXARRAY flag for RECORD_TYPE and UNION_TYPE.  */
> +  unsigned int type_include_flexarray : 1;
> +  unsigned spare : 14;
> 
>   alias_set_type alias_set;
>   tree pointer_to;
> diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
> index 9a936a91983..22b3c72ea6e 100644
> --- a/gcc/tree-object-size.cc
> +++ b/gcc/tree-object-size.cc
> @@ -633,45 +633,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
> 		    v = NULL_TREE;
> 		    break;
> 		  case COMPONENT_REF:
> -		    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
> +		    /* When the ref is not to an array, a record or a union, it
> +		       will not have flexible size, compute the object size
> +		       directly.  */
> +		    if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
> +			&& (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE)
> +			&& (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE))
> 		      {
> 			v = NULL_TREE;
> 			break;
> 		      }
> -		    is_flexible_array_mem_ref = array_ref_flexible_size_p (v);
> -		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
> -		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> -			  != UNION_TYPE
> -			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> -			  != QUAL_UNION_TYPE)
> -			break;
> -		      else
> -			v = TREE_OPERAND (v, 0);
> -		    if (TREE_CODE (v) == COMPONENT_REF
> -			&& TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> -			   == RECORD_TYPE)
> +		    if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE
> +			|| TREE_CODE (TREE_TYPE (v)) == UNION_TYPE)
> +		    /* if the record or union does not include a flexible array
> +		       recursively, compute the object size directly.  */
> 		      {
> -			/* compute object size only if v is not a
> -			   flexible array member.  */
> -			if (!is_flexible_array_mem_ref)
> +			if (!TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (v)))
> 			  {
> 			    v = NULL_TREE;
> 			    break;
> 			  }
> -			v = TREE_OPERAND (v, 0);
> +			else
> +			  v = TREE_OPERAND (v, 0);
> 		      }
> -		    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
> -		      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> -			  != UNION_TYPE
> -			  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> -			  != QUAL_UNION_TYPE)
> -			break;
> -		      else
> -			v = TREE_OPERAND (v, 0);
> -		    if (v != pt_var)
> -		      v = NULL_TREE;
> 		    else
> -		      v = pt_var;
> +		      {
> +			/* Now the ref is to an array type.  */
> +			is_flexible_array_mem_ref
> +			  = array_ref_flexible_size_p (v);
> +			while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
> +			if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> +			      != UNION_TYPE
> +			    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> +				 != QUAL_UNION_TYPE)
> +			  break;
> +			else
> +			  v = TREE_OPERAND (v, 0);
> +			if (TREE_CODE (v) == COMPONENT_REF
> +			    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> +				 == RECORD_TYPE)
> +			  {
> +			    /* compute object size only if v is not a
> +			       flexible array member.  */
> +			    if (!is_flexible_array_mem_ref)
> +			      {
> +				v = NULL_TREE;
> +				break;
> +			      }
> +			    v = TREE_OPERAND (v, 0);
> +			  }
> +			while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
> +			  if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> +				!= UNION_TYPE
> +			      && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
> +				   != QUAL_UNION_TYPE)
> +			    break;
> +			  else
> +			    v = TREE_OPERAND (v, 0);
> +			if (v != pt_var)
> +			  v = NULL_TREE;
> +			else
> +			  v = pt_var;
> +		      }
> 		    break;
> 		  default:
> 		    v = pt_var;
> diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
> index d4dc30f048f..c19ede0631d 100644
> --- a/gcc/tree-streamer-in.cc
> +++ b/gcc/tree-streamer-in.cc
> @@ -390,6 +390,7 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
>       TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
>       TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
>       TYPE_CXX_ODR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
> +      TYPE_INCLUDE_FLEXARRAY (expr) = (unsigned) bp_unpack_value (bp, 1);
>     }
>   else if (TREE_CODE (expr) == ARRAY_TYPE)
>     TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
> diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc
> index d107229da5c..73e4b4e547c 100644
> --- a/gcc/tree-streamer-out.cc
> +++ b/gcc/tree-streamer-out.cc
> @@ -357,6 +357,7 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
>       bp_pack_value (bp, flag_wpa && TYPE_CANONICAL (expr)
> 			 ? TYPE_CXX_ODR_P (TYPE_CANONICAL (expr))
> 			 : TYPE_CXX_ODR_P (expr), 1);
> +      bp_pack_value (bp, TYPE_INCLUDE_FLEXARRAY (expr), 1);
>     }
>   else if (TREE_CODE (expr) == ARRAY_TYPE)
>     bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
> diff --git a/gcc/tree.h b/gcc/tree.h
> index c656cd5b7bf..a27b9bb43bc 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -778,6 +778,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
> #define TYPE_NO_NAMED_ARGS_STDARG_P(NODE) \
>   (TYPE_CHECK (NODE)->type_common.no_named_args_stdarg_p)
> 
> +/* True if this RECORD_TYPE or UNION_TYPE includes a flexible array member
> +   at the last field recursively.  */
> +#define TYPE_INCLUDE_FLEXARRAY(NODE) \
> +  (TYPE_CHECK (NODE)->type_common.type_include_flexarray)
> +
> +
> /* In an IDENTIFIER_NODE, this means that assemble_name was called with
>    this string as an argument.  */
> #define TREE_SYMBOL_REFERENCED(NODE) \
> -- 
> 2.31.1
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-11  0:50 ` [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650) Qing Zhao
@ 2023-02-17 13:58   ` Qing Zhao
  2023-02-23 14:14   ` Fwd: " Qing Zhao
  1 sibling, 0 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-17 13:58 UTC (permalink / raw)
  To: Joseph Myers, Richard Biener; +Cc: siddhesh, keescook, gcc-patches

Ping…

Qing

> On Feb 10, 2023, at 7:50 PM, Qing Zhao <qing.zhao@oracle.com> wrote:
> 
> on structure with C99 flexible array member being nested in another structure.
> 
> This is also fixed PR77650.
> 
> " GCC extension accepts a structure containing a ISO C99 "flexible array
> member", or a union containing such a structure (possibly recursively)
> to be a member of a structure.
> 
> There are three situations:
> 
>   * The structure with a C99 flexible array member is the last field of
>     another structure, for example:
> 
>          struct flex  { int length; char data[]; };
> 
>          struct out_flex { int m; struct flex flex_data; };
> 
>     In the above, 'flex_data.data[]' is considered as a flexible array
>     too.
> 
>   * The structure with a C99 flexible array member is the field of
>     another union, for example:
> 
>          struct flex1  { int length1; char data1[]; }
>          struct flex2  { int length2; char data2[]; }
> 
>          union out_flex { struct flex1 flex_data1; struct flex2 flex_data2; }
> 
>     In the above, 'flex_data1.data1[]' or 'flex_data2.data2[]' is
>     considered as flexible arrays too.
> 
>   * The structure with a C99 flexible array member 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, 'flex_data.data[]' is allowed to be extended flexibly
>     to the padding.  E.g, up to 4 elements.
> 
>     However, relying on space in struct padding is a bad programming
>     practice, compilers do not handle such extension consistently, Any
>     code relying on this behavior should be modified to ensure that
>     flexible array members only end up at the ends of structures.
> 
>     Please use warning option '-Wgnu-variable-sized-type-not-at-end' to
>     identify all such cases in the source code and modify them.  This
>     extension will be deprecated from gcc in the next release. "
> 
> gcc/c-family/ChangeLog:
> 
> 	PR c/77650
> 	* c.opt: New option -Wgnu-variable-sized-type-not-at-end.
> 
> gcc/c/ChangeLog:
> 
> 	PR c/77650
> 	* c-decl.cc (finish_struct): Issue warnings for new option.
> 
> gcc/ChangeLog:
> 
> 	PR c/77650
> 	* doc/extend.texi: Document GCC extension on a structure containing
> 	a flexible array member to be a member of another structure.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c/77650
> 	* gcc.dg/variable-sized-type-flex-array.c: New test.
> ---
> gcc/c-family/c.opt                            |  5 ++
> gcc/c/c-decl.cc                               |  7 +++
> gcc/doc/extend.texi                           | 58 ++++++++++++++++++-
> .../gcc.dg/variable-sized-type-flex-array.c   | 31 ++++++++++
> 4 files changed, 100 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
> 
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index c0fea56a8f5..fd720538800 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -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.
> 
> +Wgnu-variable-sized-type-not-at-end
> +C C++ Var(warn_variable_sized_type_not_at_end) Warning
> +Warn about structures or unions with C99 flexible array members are not
> +at the end of a 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.
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index 741a37560b0..041df4355da 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -9289,6 +9289,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> 	       && is_last_field)
> 	TYPE_INCLUDE_FLEXARRAY (t) = true;
> 
> +      if (warn_variable_sized_type_not_at_end
> +	  && !is_last_field
> +	  && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x)))
> +	warning_at (DECL_SOURCE_LOCATION (x),
> +		    OPT_Wgnu_variable_sized_type_not_at_end,
> +		    "variable sized type not at the end of a struct");
> +
>       if (DECL_NAME (x)
> 	  || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
> 	saw_named_field = true;
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 5a026c4b48c..737228b35ac 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -1748,7 +1748,63 @@ 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 a ISO C99 @dfn{flexible array
> +member}, or a union containing such a structure (possibly recursively)
> +to be a member of a structure.
> +
> +There are three situations:
> +
> +@itemize @bullet
> +@item
> +The structure with a C99 flexible array member is the last field of another
> +structure, for example:
> +
> +@smallexample
> +struct flex  @{ int length; char data[]; @};
> +
> +struct out_flex @{ int m; struct flex flex_data; @};
> +@end smallexample
> +
> +In the above, @code{flex_data.data[]} is considered as a flexible array too.
> +
> +@item
> +The structure with a C99 flexible array member is the field of
> +another union, for example:
> +
> +@smallexample
> +struct flex1  @{ int length1; char data1[]; @}
> +struct flex2  @{ int length2; char data2[]; @}
> +
> +union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}
> +@end smallexample
> +
> +In the above, @code{flex_data1.data1[]} or @code{flex_data2.data2[]}
> +is considered as flexible arrays too.
> +
> +@item
> +The structure with a C99 flexible array member 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{flex_data.data[]} is allowed to be extended flexibly to
> +the padding.  E.g, up to 4 elements.
> +
> +However, relying on space in struct padding is a bad programming practice,
> +compilers do not handle such extension consistently, Any code relying on
> +this behavior should be modified to ensure that flexible array members
> +only end up at the ends of structures.
> +
> +Please use warning option  @option{-Wgnu-variable-sized-type-not-at-end} to
> +identify all such cases in the source code and modify them.  This extension
> +will be deprecated from gcc in the next release.
> @end itemize
> 
> Non-empty initialization of zero-length
> diff --git a/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
> new file mode 100644
> index 00000000000..e3f65c5ed07
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
> @@ -0,0 +1,31 @@
> +/* Test for -Wgnu-variable-sized-type-not-at-end on structure/union with 
> +   C99 flexible array members being embedded into another structure.  */
> +/* { dg-do compile } */
> +/* { dg-options "-Wgnu-variable-sized-type-not-at-end" } */
> +
> +struct flex { int n; int data[]; };
> +struct out_flex_end { int m; struct flex flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +struct out_flex_mid { struct flex flex_data; int m; };  /* { dg-warning "variable sized type not at the end of a struct" } */
> +/* 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 "variable sized type not at the end of a struct" } */
> +union flex_union_mid { int a; struct outer_flex_mid b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +
> +
> +struct flex0 { int n; int data[0]; };
> +struct out_flex_end0 { int m; struct flex0 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +struct out_flex_mid0 { struct flex0 flex_data; int m; };  /* { dg-bogus "variable sized type not at the end of a struct" } */
> +struct outer_flex_mid0 { struct out_flex_mid0 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +union flex_union_mid0 { int a; struct outer_flex_mid0 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +
> +struct flex1 { int n; int data[1]; };
> +struct out_flex_end1 { int m; struct flex1 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +struct out_flex_mid1 { struct flex1 flex_data; int m; }; /* { dg-bogus "variable sized type not at the end of a struct" } */ 
> +struct outer_flex_mid1 { struct out_flex_mid1 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +union flex_union_mid1 { int a; struct outer_flex_mid1 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +
> +struct flexn { int n; int data[8]; }; 
> +struct out_flex_endn { int m; struct flexn flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> +struct out_flex_midn { struct flexn flex_data; int m; }; /* { dg-bogus"variable sized type not at the end of a struct" } */ 
> +struct outer_flex_midn { struct out_flex_midn out_flex_data; int p; }; /* { dg-bogus"variable sized type not at the end of a struct" } */
> +union flex_union_midn { int a; struct outer_flex_midn b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
> -- 
> 2.31.1
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Fwd: [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832]
  2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
  2023-02-17 13:57   ` Qing Zhao
@ 2023-02-23 14:12   ` Qing Zhao
  1 sibling, 0 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-23 14:12 UTC (permalink / raw)
  To: Joseph Myers, Richard Biener; +Cc: Siddhesh Poyarekar, Kees Cook, gcc Patches

[-- Attachment #1: Type: text/plain, Size: 14671 bytes --]

Ping * 2.

Hi, Joseph and Richard,

Could you please review this patch and let me know whether it’s ready for committing into GCC13?

This is an important bug that need to be fixed for kernel security purpose.

thanks.

Qing

Begin forwarded message:

From: Qing Zhao <qing.zhao@oracle.com<mailto:qing.zhao@oracle.com>>
Subject: [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832]
Date: February 10, 2023 at 7:50:12 PM EST
To: joseph@codesourcery.com<mailto:joseph@codesourcery.com>, rguenther@suse.de<mailto:rguenther@suse.de>
Cc: siddhesh@gotplt.org<mailto:siddhesh@gotplt.org>, keescook@chromium.org<mailto:keescook@chromium.org>, gcc-patches@gcc.gnu.org<mailto:gcc-patches@gcc.gnu.org>, Qing Zhao <qing.zhao@oracle.com<mailto:qing.zhao@oracle.com>>

GCC extension accepts the case when a struct with a C99 flexible array member
is embedded into another struct or union (possibly recursively).
__builtin_object_size should treat such struct as flexible size.

gcc/c/ChangeLog:

PR tree-optimization/101832
* c-decl.cc<http://c-decl.cc> (finish_struct): Set TYPE_INCLUDE_FLEXARRAY for
struct/union type.

gcc/cp/ChangeLog:

PR tree-optimization/101832
* module.cc<http://module.cc> (trees_out::core_bools): Stream out new bit
type_include_flexarray.
(trees_in::core_bools): Stream in new bit type_include_flexarray.

gcc/ChangeLog:

PR tree-optimization/101832
* print-tree.cc<http://print-tree.cc> (print_node): Print new bit type_include_flexarray.
* tree-core.h (struct tree_type_common): New bit
type_include_flexarray.
* tree-object-size.cc<http://tree-object-size.cc> (addr_object_size): Handle structure/union type
when it has flexible size.
* tree-streamer-in.cc<http://tree-streamer-in.cc> (unpack_ts_type_common_value_fields): Stream
in new bit type_include_flexarray.
* tree-streamer-out.cc<http://tree-streamer-out.cc> (pack_ts_type_common_value_fields): Stream
out new bit type_include_flexarray.
* tree.h (TYPE_INCLUDE_FLEXARRAY): New macro
TYPE_INCLUDE_FLEXARRAY.

gcc/testsuite/ChangeLog:

PR tree-optimization/101832
* gcc.dg/builtin-object-size-pr101832.c: New test.
---
gcc/c/c-decl.cc<http://c-decl.cc>                               |  12 ++
gcc/cp/module.cc<http://module.cc>                              |   2 +
gcc/print-tree.cc<http://print-tree.cc>                             |   5 +
.../gcc.dg/builtin-object-size-pr101832.c     | 134 ++++++++++++++++++
gcc/tree-core.h                               |   4 +-
gcc/tree-object-size.cc<http://tree-object-size.cc>                       |  79 +++++++----
gcc/tree-streamer-in.cc<http://tree-streamer-in.cc>                       |   1 +
gcc/tree-streamer-out.cc<http://tree-streamer-out.cc>                      |   1 +
gcc/tree.h                                    |   6 +
9 files changed, 215 insertions(+), 29 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c

diff --git a/gcc/c/c-decl.cc<http://c-decl.cc> b/gcc/c/c-decl.cc<http://c-decl.cc>
index 20e7d1855bf..741a37560b0 100644
--- a/gcc/c/c-decl.cc<http://c-decl.cc>
+++ b/gcc/c/c-decl.cc<http://c-decl.cc>
@@ -9277,6 +9277,18 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
      /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x.  */
      DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);

+      /* Set TYPE_INCLUDE_FLEXARRAY for the context of x, t
+       * when x is an array.  */
+      if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE)
+ TYPE_INCLUDE_FLEXARRAY (t) = flexible_array_member_type_p (TREE_TYPE (x)) ;
+      /* Recursively set TYPE_INCLUDE_FLEXARRAY for the context of x, t
+ when x is the last field.  */
+      else if ((TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+       && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x))
+       && is_last_field)
+ TYPE_INCLUDE_FLEXARRAY (t) = true;
+
      if (DECL_NAME (x)
 || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
saw_named_field = true;
diff --git a/gcc/cp/module.cc<http://module.cc> b/gcc/cp/module.cc<http://module.cc>
index ac2fe66b080..c750361b704 100644
--- a/gcc/cp/module.cc<http://module.cc>
+++ b/gcc/cp/module.cc<http://module.cc>
@@ -5371,6 +5371,7 @@ trees_out::core_bools (tree t)
      WB (t->type_common.lang_flag_5);
      WB (t->type_common.lang_flag_6);
      WB (t->type_common.typeless_storage);
+      WB (t->type_common.type_include_flexarray);
    }

  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
@@ -5551,6 +5552,7 @@ trees_in::core_bools (tree t)
      RB (t->type_common.lang_flag_5);
      RB (t->type_common.lang_flag_6);
      RB (t->type_common.typeless_storage);
+      RB (t->type_common.type_include_flexarray);
    }

  if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
diff --git a/gcc/print-tree.cc<http://print-tree.cc> b/gcc/print-tree.cc<http://print-tree.cc>
index 1f3afcbbc86..efacdb7686f 100644
--- a/gcc/print-tree.cc<http://print-tree.cc>
+++ b/gcc/print-tree.cc<http://print-tree.cc>
@@ -631,6 +631,11 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
 && TYPE_CXX_ODR_P (node))
fputs (" cxx-odr-p", file);

+      if ((code == RECORD_TYPE
+   || code == UNION_TYPE)
+  && TYPE_INCLUDE_FLEXARRAY (node))
+ fputs (" include-flexarray", file);
+
      /* The transparent-union flag is used for different things in
different nodes.  */
      if ((code == UNION_TYPE || code == RECORD_TYPE)
diff --git a/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
new file mode 100644
index 00000000000..60078e11634
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-object-size-pr101832.c
@@ -0,0 +1,134 @@
+/* PR 101832:
+   GCC extension accepts the case when a struct with a C99 flexible array
+   member is embedded into another struct (possibly recursively).
+   __builtin_object_size will treat such struct as flexible size.
+   However, when a structure with non-C99 flexible array member, i.e, trailing
+   [0], [1], or [4], is embedded into anther struct, the stucture will not
+   be treated as flexible size.  */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "builtin-object-size-common.h"
+
+#define expect(p, _v) do { \
+  size_t v = _v; \
+  if (p == v) \
+    __builtin_printf ("ok:  %s == %zd\n", #p, p); \
+  else {\
+    __builtin_printf ("WAT: %s == %zd (expected %zd)\n", #p, p, v); \
+    FAIL (); \
+  } \
+} while (0);
+
+
+struct A {
+  int n;
+  char data[];
+};
+
+struct B {
+  int m;
+  struct A a;
+};
+
+struct C {
+  int q;
+  struct B b;
+};
+
+struct A0 {
+  int n;
+  char data[0];
+};
+
+struct B0 {
+  int m;
+  struct A0 a;
+};
+
+struct C0 {
+  int q;
+  struct B0 b;
+};
+
+struct A1 {
+  int n;
+  char data[1];
+};
+
+struct B1 {
+  int m;
+  struct A1 a;
+};
+
+struct C1 {
+  int q;
+  struct B1 b;
+};
+
+struct An {
+  int n;
+  char data[8];
+};
+
+struct Bn {
+  int m;
+  struct An a;
+};
+
+struct Cn {
+  int q;
+  struct Bn b;
+};
+
+volatile void *magic1, *magic2;
+
+int main (int argc, char *argv[])
+{
+  struct B *outer;
+  struct C *outest;
+
+  /* Make sure optimization can't find some other object size. */
+  outer = (void *)magic1;
+  outest = (void *)magic2;
+
+  expect (__builtin_object_size (&outer->a, 1), -1);
+  expect (__builtin_object_size (&outest->b, 1), -1);
+  expect (__builtin_object_size (&outest->b.a, 1), -1);
+
+  struct B0 *outer0;
+  struct C0 *outest0;
+
+  /* Make sure optimization can't find some other object size. */
+  outer0 = (void *)magic1;
+  outest0 = (void *)magic2;
+
+  expect (__builtin_object_size (&outer0->a, 1), sizeof (outer0->a));
+  expect (__builtin_object_size (&outest0->b, 1), sizeof (outest0->b));
+  expect (__builtin_object_size (&outest0->b.a, 1), sizeof (outest0->b.a));
+
+  struct B1 *outer1;
+  struct C1 *outest1;
+
+  /* Make sure optimization can't find some other object size. */
+  outer1 = (void *)magic1;
+  outest1 = (void *)magic2;
+
+  expect (__builtin_object_size (&outer1->a, 1), sizeof (outer1->a));
+  expect (__builtin_object_size (&outest1->b, 1), sizeof (outest1->b));
+  expect (__builtin_object_size (&outest1->b.a, 1), sizeof (outest1->b.a));
+
+  struct Bn *outern;
+  struct Cn *outestn;
+
+  /* Make sure optimization can't find some other object size. */
+  outern = (void *)magic1;
+  outestn = (void *)magic2;
+
+  expect (__builtin_object_size (&outern->a, 1), sizeof (outern->a));
+  expect (__builtin_object_size (&outestn->b, 1), sizeof (outestn->b));
+  expect (__builtin_object_size (&outestn->b.a, 1), sizeof (outestn->b.a));
+
+  DONE ();
+  return 0;
+}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index acd8deea34e..705d5702b9c 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1718,7 +1718,9 @@ struct GTY(()) tree_type_common {
  unsigned empty_flag : 1;
  unsigned indivisible_p : 1;
  unsigned no_named_args_stdarg_p : 1;
-  unsigned spare : 15;
+  /* TYPE_INCLUDE_FLEXARRAY flag for RECORD_TYPE and UNION_TYPE.  */
+  unsigned int type_include_flexarray : 1;
+  unsigned spare : 14;

  alias_set_type alias_set;
  tree pointer_to;
diff --git a/gcc/tree-object-size.cc<http://tree-object-size.cc> b/gcc/tree-object-size.cc<http://tree-object-size.cc>
index 9a936a91983..22b3c72ea6e 100644
--- a/gcc/tree-object-size.cc<http://tree-object-size.cc>
+++ b/gcc/tree-object-size.cc<http://tree-object-size.cc>
@@ -633,45 +633,68 @@ addr_object_size (struct object_size_info *osi, const_tree ptr,
   v = NULL_TREE;
   break;
 case COMPONENT_REF:
-    if (TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+    /* When the ref is not to an array, a record or a union, it
+       will not have flexible size, compute the object size
+       directly.  */
+    if ((TREE_CODE (TREE_TYPE (v)) != ARRAY_TYPE)
+ && (TREE_CODE (TREE_TYPE (v)) != RECORD_TYPE)
+ && (TREE_CODE (TREE_TYPE (v)) != UNION_TYPE))
     {
v = NULL_TREE;
break;
     }
-    is_flexible_array_mem_ref = array_ref_flexible_size_p (v);
-    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
-      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-  != UNION_TYPE
-  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-  != QUAL_UNION_TYPE)
- break;
-      else
- v = TREE_OPERAND (v, 0);
-    if (TREE_CODE (v) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-   == RECORD_TYPE)
+    if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (v)) == UNION_TYPE)
+    /* if the record or union does not include a flexible array
+       recursively, compute the object size directly.  */
     {
- /* compute object size only if v is not a
-   flexible array member.  */
- if (!is_flexible_array_mem_ref)
+ if (!TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (v)))
 {
   v = NULL_TREE;
   break;
 }
- v = TREE_OPERAND (v, 0);
+ else
+  v = TREE_OPERAND (v, 0);
     }
-    while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
-      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-  != UNION_TYPE
-  && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
-  != QUAL_UNION_TYPE)
- break;
-      else
- v = TREE_OPERAND (v, 0);
-    if (v != pt_var)
-      v = NULL_TREE;
   else
-      v = pt_var;
+      {
+ /* Now the ref is to an array type.  */
+ is_flexible_array_mem_ref
+  = array_ref_flexible_size_p (v);
+ while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+      != UNION_TYPE
+    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ != QUAL_UNION_TYPE)
+  break;
+ else
+  v = TREE_OPERAND (v, 0);
+ if (TREE_CODE (v) == COMPONENT_REF
+    && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+  {
+    /* compute object size only if v is not a
+       flexible array member.  */
+    if (!is_flexible_array_mem_ref)
+      {
+ v = NULL_TREE;
+ break;
+      }
+    v = TREE_OPERAND (v, 0);
+  }
+ while (v != pt_var && TREE_CODE (v) == COMPONENT_REF)
+  if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ != UNION_TYPE
+      && TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+   != QUAL_UNION_TYPE)
+    break;
+  else
+    v = TREE_OPERAND (v, 0);
+ if (v != pt_var)
+  v = NULL_TREE;
+ else
+  v = pt_var;
+      }
   break;
 default:
   v = pt_var;
diff --git a/gcc/tree-streamer-in.cc<http://tree-streamer-in.cc> b/gcc/tree-streamer-in.cc<http://tree-streamer-in.cc>
index d4dc30f048f..c19ede0631d 100644
--- a/gcc/tree-streamer-in.cc<http://tree-streamer-in.cc>
+++ b/gcc/tree-streamer-in.cc<http://tree-streamer-in.cc>
@@ -390,6 +390,7 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
      TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
      TYPE_FINAL_P (expr) = (unsigned) bp_unpack_value (bp, 1);
      TYPE_CXX_ODR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+      TYPE_INCLUDE_FLEXARRAY (expr) = (unsigned) bp_unpack_value (bp, 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
diff --git a/gcc/tree-streamer-out.cc<http://tree-streamer-out.cc> b/gcc/tree-streamer-out.cc<http://tree-streamer-out.cc>
index d107229da5c..73e4b4e547c 100644
--- a/gcc/tree-streamer-out.cc<http://tree-streamer-out.cc>
+++ b/gcc/tree-streamer-out.cc<http://tree-streamer-out.cc>
@@ -357,6 +357,7 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
      bp_pack_value (bp, flag_wpa && TYPE_CANONICAL (expr)
? TYPE_CXX_ODR_P (TYPE_CANONICAL (expr))
: TYPE_CXX_ODR_P (expr), 1);
+      bp_pack_value (bp, TYPE_INCLUDE_FLEXARRAY (expr), 1);
    }
  else if (TREE_CODE (expr) == ARRAY_TYPE)
    bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
diff --git a/gcc/tree.h b/gcc/tree.h
index c656cd5b7bf..a27b9bb43bc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -778,6 +778,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
#define TYPE_NO_NAMED_ARGS_STDARG_P(NODE) \
  (TYPE_CHECK (NODE)->type_common.no_named_args_stdarg_p)

+/* True if this RECORD_TYPE or UNION_TYPE includes a flexible array member
+   at the last field recursively.  */
+#define TYPE_INCLUDE_FLEXARRAY(NODE) \
+  (TYPE_CHECK (NODE)->type_common.type_include_flexarray)
+
+
/* In an IDENTIFIER_NODE, this means that assemble_name was called with
   this string as an argument.  */
#define TREE_SYMBOL_REFERENCED(NODE) \
--
2.31.1



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Fwd: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-11  0:50 ` [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650) Qing Zhao
  2023-02-17 13:58   ` Qing Zhao
@ 2023-02-23 14:14   ` Qing Zhao
  2023-02-23 21:24     ` Joseph Myers
  1 sibling, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-02-23 14:14 UTC (permalink / raw)
  To: Joseph Myers, Richard Biener; +Cc: Siddhesh Poyarekar, Kees Cook, Gcc Patches

[-- Attachment #1: Type: text/plain, Size: 10378 bytes --]

Ping * 2.

Hi, Joseph and Richard,

Could you please review this patch and let me know whether it’s ready for committing into GCC13?

thanks.

Qing
Begin forwarded message:

From: Qing Zhao <qing.zhao@oracle.com<mailto:qing.zhao@oracle.com>>
Subject: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
Date: February 10, 2023 at 7:50:13 PM EST
To: joseph@codesourcery.com<mailto:joseph@codesourcery.com>, rguenther@suse.de<mailto:rguenther@suse.de>
Cc: siddhesh@gotplt.org<mailto:siddhesh@gotplt.org>, keescook@chromium.org<mailto:keescook@chromium.org>, gcc-patches@gcc.gnu.org<mailto:gcc-patches@gcc.gnu.org>, Qing Zhao <qing.zhao@oracle.com<mailto:qing.zhao@oracle.com>>

on structure with C99 flexible array member being nested in another structure.

This is also fixed PR77650.

" GCC extension accepts a structure containing a ISO C99 "flexible array
member", or a union containing such a structure (possibly recursively)
to be a member of a structure.

There are three situations:

  * The structure with a C99 flexible array member is the last field of
    another structure, for example:

         struct flex  { int length; char data[]; };

         struct out_flex { int m; struct flex flex_data; };

    In the above, 'flex_data.data[]' is considered as a flexible array
    too.

  * The structure with a C99 flexible array member is the field of
    another union, for example:

         struct flex1  { int length1; char data1[]; }
         struct flex2  { int length2; char data2[]; }

         union out_flex { struct flex1 flex_data1; struct flex2 flex_data2; }

    In the above, 'flex_data1.data1[]' or 'flex_data2.data2[]' is
    considered as flexible arrays too.

  * The structure with a C99 flexible array member 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, 'flex_data.data[]' is allowed to be extended flexibly
    to the padding.  E.g, up to 4 elements.

    However, relying on space in struct padding is a bad programming
    practice, compilers do not handle such extension consistently, Any
    code relying on this behavior should be modified to ensure that
    flexible array members only end up at the ends of structures.

    Please use warning option '-Wgnu-variable-sized-type-not-at-end' to
    identify all such cases in the source code and modify them.  This
    extension will be deprecated from gcc in the next release. "

gcc/c-family/ChangeLog:

PR c/77650
* c.opt: New option -Wgnu-variable-sized-type-not-at-end.

gcc/c/ChangeLog:

PR c/77650
* c-decl.cc<http://c-decl.cc> (finish_struct): Issue warnings for new option.

gcc/ChangeLog:

PR c/77650
* doc/extend.texi: Document GCC extension on a structure containing
a flexible array member to be a member of another structure.

gcc/testsuite/ChangeLog:

PR c/77650
* gcc.dg/variable-sized-type-flex-array.c: New test.
---
gcc/c-family/c.opt                            |  5 ++
gcc/c/c-decl.cc<http://c-decl.cc>                               |  7 +++
gcc/doc/extend.texi                           | 58 ++++++++++++++++++-
.../gcc.dg/variable-sized-type-flex-array.c   | 31 ++++++++++
4 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c0fea56a8f5..fd720538800 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -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.

+Wgnu-variable-sized-type-not-at-end
+C C++ Var(warn_variable_sized_type_not_at_end) Warning
+Warn about structures or unions with C99 flexible array members are not
+at the end of a 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.
diff --git a/gcc/c/c-decl.cc<http://c-decl.cc> b/gcc/c/c-decl.cc<http://c-decl.cc>
index 741a37560b0..041df4355da 100644
--- a/gcc/c/c-decl.cc<http://c-decl.cc>
+++ b/gcc/c/c-decl.cc<http://c-decl.cc>
@@ -9289,6 +9289,13 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
      && is_last_field)
TYPE_INCLUDE_FLEXARRAY (t) = true;

+      if (warn_variable_sized_type_not_at_end
+  && !is_last_field
+  && TYPE_INCLUDE_FLEXARRAY (TREE_TYPE (x)))
+ warning_at (DECL_SOURCE_LOCATION (x),
+    OPT_Wgnu_variable_sized_type_not_at_end,
+    "variable sized type not at the end of a struct");
+
      if (DECL_NAME (x)
 || RECORD_OR_UNION_TYPE_P (TREE_TYPE (x)))
saw_named_field = true;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5a026c4b48c..737228b35ac 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1748,7 +1748,63 @@ 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 a ISO C99 @dfn{flexible array
+member}, or a union containing such a structure (possibly recursively)
+to be a member of a structure.
+
+There are three situations:
+
+@itemize @bullet
+@item
+The structure with a C99 flexible array member is the last field of another
+structure, for example:
+
+@smallexample
+struct flex  @{ int length; char data[]; @};
+
+struct out_flex @{ int m; struct flex flex_data; @};
+@end smallexample
+
+In the above, @code{flex_data.data[]} is considered as a flexible array too.
+
+@item
+The structure with a C99 flexible array member is the field of
+another union, for example:
+
+@smallexample
+struct flex1  @{ int length1; char data1[]; @}
+struct flex2  @{ int length2; char data2[]; @}
+
+union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}
+@end smallexample
+
+In the above, @code{flex_data1.data1[]} or @code{flex_data2.data2[]}
+is considered as flexible arrays too.
+
+@item
+The structure with a C99 flexible array member 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{flex_data.data[]} is allowed to be extended flexibly to
+the padding.  E.g, up to 4 elements.
+
+However, relying on space in struct padding is a bad programming practice,
+compilers do not handle such extension consistently, Any code relying on
+this behavior should be modified to ensure that flexible array members
+only end up at the ends of structures.
+
+Please use warning option  @option{-Wgnu-variable-sized-type-not-at-end} to
+identify all such cases in the source code and modify them.  This extension
+will be deprecated from gcc in the next release.
@end itemize

Non-empty initialization of zero-length
diff --git a/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
new file mode 100644
index 00000000000..e3f65c5ed07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/variable-sized-type-flex-array.c
@@ -0,0 +1,31 @@
+/* Test for -Wgnu-variable-sized-type-not-at-end on structure/union with
+   C99 flexible array members being embedded into another structure.  */
+/* { dg-do compile } */
+/* { dg-options "-Wgnu-variable-sized-type-not-at-end" } */
+
+struct flex { int n; int data[]; };
+struct out_flex_end { int m; struct flex flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid { struct flex flex_data; int m; };  /* { dg-warning "variable sized type not at the end of a struct" } */
+/* 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 "variable sized type not at the end of a struct" } */
+union flex_union_mid { int a; struct outer_flex_mid b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+
+struct flex0 { int n; int data[0]; };
+struct out_flex_end0 { int m; struct flex0 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid0 { struct flex0 flex_data; int m; };  /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct outer_flex_mid0 { struct out_flex_mid0 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+union flex_union_mid0 { int a; struct outer_flex_mid0 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+struct flex1 { int n; int data[1]; };
+struct out_flex_end1 { int m; struct flex1 flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_mid1 { struct flex1 flex_data; int m; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct outer_flex_mid1 { struct out_flex_mid1 out_flex_data; int p; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+union flex_union_mid1 { int a; struct outer_flex_mid1 b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+
+struct flexn { int n; int data[8]; };
+struct out_flex_endn { int m; struct flexn flex_data; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
+struct out_flex_midn { struct flexn flex_data; int m; }; /* { dg-bogus"variable sized type not at the end of a struct" } */
+struct outer_flex_midn { struct out_flex_midn out_flex_data; int p; }; /* { dg-bogus"variable sized type not at the end of a struct" } */
+union flex_union_midn { int a; struct outer_flex_midn b; }; /* { dg-bogus "variable sized type not at the end of a struct" } */
--
2.31.1



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Fwd: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-23 14:14   ` Fwd: " Qing Zhao
@ 2023-02-23 21:24     ` Joseph Myers
  2023-02-23 22:04       ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Joseph Myers @ 2023-02-23 21:24 UTC (permalink / raw)
  To: Qing Zhao; +Cc: Richard Biener, Siddhesh Poyarekar, Kees Cook, Gcc Patches

On Thu, 23 Feb 2023, Qing Zhao via Gcc-patches wrote:

> +@item
> +The structure with a C99 flexible array member is the field of
> +another union, for example:
> +
> +@smallexample
> +struct flex1  @{ int length1; char data1[]; @}
> +struct flex2  @{ int length2; char data2[]; @}
> +
> +union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}

I don't think this is an extension; structures with flexible array members 
are OK in unions in standard C.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-23 21:24     ` Joseph Myers
@ 2023-02-23 22:04       ` Qing Zhao
  2023-02-23 22:30         ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-02-23 22:04 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Richard Biener, Siddhesh Poyarekar, Kees Cook, Gcc Patches



> On Feb 23, 2023, at 4:24 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> On Thu, 23 Feb 2023, Qing Zhao via Gcc-patches wrote:
> 
>> +@item
>> +The structure with a C99 flexible array member is the field of
>> +another union, for example:
>> +
>> +@smallexample
>> +struct flex1  @{ int length1; char data1[]; @}
>> +struct flex2  @{ int length2; char data2[]; @}
>> +
>> +union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}
> 
> I don't think this is an extension; structures with flexible array members 
> are OK in unions in standard C.

Thanks for the info.

Just checked the small testing case with -Wpedantic, Yes, it’s accepted without any warning.
Will delete this item from the doc. And send the new patch soon.

Thanks.

Qing
> 
> -- 
> Joseph S. Myers
> joseph@codesourcery.com


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-23 22:04       ` Qing Zhao
@ 2023-02-23 22:30         ` Qing Zhao
  2023-02-24  0:56           ` Joseph Myers
  0 siblings, 1 reply; 13+ messages in thread
From: Qing Zhao @ 2023-02-23 22:30 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Richard Biener, Siddhesh Poyarekar, Kees Cook, Gcc Patches



> On Feb 23, 2023, at 5:04 PM, Qing Zhao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> 
> 
> 
>> On Feb 23, 2023, at 4:24 PM, Joseph Myers <joseph@codesourcery.com> wrote:
>> 
>> On Thu, 23 Feb 2023, Qing Zhao via Gcc-patches wrote:
>> 
>>> +@item
>>> +The structure with a C99 flexible array member is the field of
>>> +another union, for example:
>>> +
>>> +@smallexample
>>> +struct flex1  @{ int length1; char data1[]; @}
>>> +struct flex2  @{ int length2; char data2[]; @}
>>> +
>>> +union out_flex @{ struct flex1 flex_data1; struct flex2 flex_data2; @}
>> 
>> I don't think this is an extension; structures with flexible array members 
>> are OK in unions in standard C.
> 
> Thanks for the info.
> 
> Just checked the small testing case with -Wpedantic, Yes, it’s accepted without any warning.
> Will delete this item from the doc. And send the new patch soon.

But the following:

struct flex1  { int length1; char data1[]; };
struct flex2  { int length2; char data2[]; };
union union_flex { struct flex1 f1; struct flex2 f2; };  /* this is C standard.  */

struct out_flex { int n; union union_flex flex_data1;};  /* this is GNU extension.  */

Should add this item into the documentation?

Qing

> 
> Thanks.
> 
> Qing
>> 
>> -- 
>> Joseph S. Myers
>> joseph@codesourcery.com


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-23 22:30         ` Qing Zhao
@ 2023-02-24  0:56           ` Joseph Myers
  2023-02-24 13:50             ` Qing Zhao
  0 siblings, 1 reply; 13+ messages in thread
From: Joseph Myers @ 2023-02-24  0:56 UTC (permalink / raw)
  To: Qing Zhao; +Cc: Richard Biener, Siddhesh Poyarekar, Kees Cook, Gcc Patches

On Thu, 23 Feb 2023, Qing Zhao via Gcc-patches wrote:

> But the following:
> 
> struct flex1  { int length1; char data1[]; };
> struct flex2  { int length2; char data2[]; };
> union union_flex { struct flex1 f1; struct flex2 f2; };  /* this is C standard.  */
> 
> struct out_flex { int n; union union_flex flex_data1;};  /* this is GNU extension.  */
> 
> Should add this item into the documentation?

"union that contains a structure with a flexible array member" is just 
like "structure with a flexible array member".  I suppose the 
documentation should try to make that clear, without repeating it too much 
for every separate case.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650)
  2023-02-24  0:56           ` Joseph Myers
@ 2023-02-24 13:50             ` Qing Zhao
  0 siblings, 0 replies; 13+ messages in thread
From: Qing Zhao @ 2023-02-24 13:50 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Richard Biener, Siddhesh Poyarekar, Kees Cook, Gcc Patches



> On Feb 23, 2023, at 7:56 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> 
> On Thu, 23 Feb 2023, Qing Zhao via Gcc-patches wrote:
> 
>> But the following:
>> 
>> struct flex1  { int length1; char data1[]; };
>> struct flex2  { int length2; char data2[]; };
>> union union_flex { struct flex1 f1; struct flex2 f2; };  /* this is C standard.  */
>> 
>> struct out_flex { int n; union union_flex flex_data1;};  /* this is GNU extension.  */
>> 
>> Should add this item into the documentation?
> 
> "union that contains a structure with a flexible array member" is just 
> like "structure with a flexible array member".  I suppose the 
> documentation should try to make that clear, without repeating it too much 
> for every separate case.

Okay, thanks.

Qing
> 
> -- 
> Joseph S. Myers
> joseph@codesourcery.com


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2023-02-24 13:50 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-11  0:50 [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao
2023-02-11  0:50 ` [v3][PATCH 1/2] Handle component_ref to a structre/union field including C99 FAM [PR101832] Qing Zhao
2023-02-17 13:57   ` Qing Zhao
2023-02-23 14:12   ` Fwd: " Qing Zhao
2023-02-11  0:50 ` [v3][PATCH 2/2] Update documentation to clarify a GCC extension (PR77650) Qing Zhao
2023-02-17 13:58   ` Qing Zhao
2023-02-23 14:14   ` Fwd: " Qing Zhao
2023-02-23 21:24     ` Joseph Myers
2023-02-23 22:04       ` Qing Zhao
2023-02-23 22:30         ` Qing Zhao
2023-02-24  0:56           ` Joseph Myers
2023-02-24 13:50             ` Qing Zhao
2023-02-17 13:57 ` [v3][PATCH 0/2] Handle component_ref to a structure/union field including FAM for builtin_object_size Qing Zhao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).