[[GCC13][Patch][V3] 1/2] Add a new option -fstrict-flex-array[=n] and new attribute strict_flex_array
Richard Biener
rguenther@suse.de
Mon Aug 29 08:04:56 GMT 2022
On Fri, 26 Aug 2022, Qing Zhao wrote:
>
>
> > On Aug 26, 2022, at 4:48 AM, Richard Biener <rguenther@suse.de> wrote:
> >
> > On Wed, 17 Aug 2022, Qing Zhao wrote:
> >
> >> Add the following new option -fstrict-flex-array[=n] and a corresponding
> >> attribute strict_flex_array to GCC:
> >>
> >> '-fstrict-flex-array'
> >> Treat the trailing array of a structure as a flexible array member
> >> in a stricter way. The positive form is equivalent to
> >> '-fstrict-flex-array=3', which is the strictest. A trailing array
> >> is treated as a flexible array member only when it is declared as a
> >> flexible array member per C99 standard onwards. The negative form
> >> is equivalent to '-fstrict-flex-array=0', which is the least
> >> strict. All trailing arrays of structures are treated as flexible
> >> array members.
> >>
> >> '-fstrict-flex-array=LEVEL'
> >> Treat the trailing array of a structure as a flexible array member
> >> in a stricter way. The value of LEVEL controls the level of
> >> strictness.
> >>
> >> The possible values of LEVEL are the same as for the
> >> 'strict_flex_array' attribute (*note Variable Attributes::).
> >>
> >> You can control this behavior for a specific trailing array field
> >> of a structure by using the variable attribute 'strict_flex_array'
> >> attribute (*note Variable Attributes::).
> >>
> >> This option is only valid when flexible array member is supported in the
> >> language. FOR ISO C before C99 and ISO C++, no language support for the flexible
> >> array member at all, this option will be invalid and a warning will be issued.
> >> When -std=gnu89 is specified or C++ with GNU extension, only zero-length array
> >> extension and one-size array are supported, as a result, LEVEL=3 will be
> >> invalid and a warning will be issued.
> >>
> >> 'strict_flex_array (LEVEL)'
> >> The 'strict_flex_array' attribute should be attached to the
> >> trailing array field of a structure. It specifies the level of
> >> strictness of treating the trailing array field of a structure as a
> >> flexible array member. LEVEL must be an integer betwen 0 to 3.
> >>
> >> LEVEL=0 is the least strict level, all trailing arrays of
> >> structures are treated as flexible array members. LEVEL=3 is the
> >> strictest level, only when the trailing array is declared as a
> >> flexible array member per C99 standard onwards ([]), it is treated
> >> as a flexible array member.
> >>
> >> There are two more levels in between 0 and 3, which are provided to
> >> support older codes that use GCC zero-length array extension ([0])
> >> or one-size array as flexible array member ([1]): When LEVEL is 1,
> >> the trailing array is treated as a flexible array member when it is
> >> declared as either [], [0], or [1]; When LEVEL is 2, the trailing
> >> array is treated as a flexible array member when it is declared as
> >> either [], or [0].
> >>
> >> This attribute can be used with or without '-fstrict-flex-array'.
> >> When both the attribute and the option present at the same time,
> >> the level of the strictness for the specific trailing array field
> >> is determined by the attribute.
> >>
> >> This attribute is only valid when flexible array member is supported in the
> >> language. For ISO C before C99 and ISO C++, no language support for the flexible
> >> array member at all, this attribute will be invalid and a warning is issued.
> >> When -std=gnu89 is specified or C++ with GNU extension, only zero-length array
> >> extension and one-size array are supported, as a result, LEVEL=3 will be
> >> invalid and a warning is issued.
> >>
> >> gcc/c-family/ChangeLog:
> >>
> >> * c-attribs.cc (handle_strict_flex_arrays_attribute): New function.
> >> (c_common_attribute_table): New item for strict_flex_array.
> >> * c-opts.cc (c_common_post_options): Handle the combination of
> >> -fstrict-flex-arrays and -std specially.
> >> * c.opt: (fstrict-flex-array): New option.
> >> (fstrict-flex-array=): New option.
> >>
> >> gcc/c/ChangeLog:
> >>
> >> * c-decl.cc (flexible_array_member_type_p): New function.
> >> (one_element_array_type_p): Likewise.
> >> (zero_length_array_type_p): Likewise.
> >> (add_flexible_array_elts_to_size): Call new utility
> >> routine flexible_array_member_type_p.
> >> (is_flexible_array_member_p): New function.
> >> (finish_struct): Set the new DECL_NOT_FLEXARRAY flag.
> >>
> >> gcc/cp/ChangeLog:
> >>
> >> * module.cc (trees_out::core_bools): Stream out new bit
> >> decl_not_flexarray.
> >> (trees_in::core_bools): Stream in new bit decl_not_flexarray.
> >>
> >> gcc/ChangeLog:
> >>
> >> * doc/extend.texi: Document strict_flex_array attribute.
> >> * doc/invoke.texi: Document -fstrict-flex-array[=n] option.
> >> * print-tree.cc (print_node): Print new bit decl_not_flexarray.
> >> * tree-core.h (struct tree_decl_common): New bit field
> >> decl_not_flexarray.
> >> * tree-streamer-in.cc (unpack_ts_decl_common_value_fields): Stream
> >> in new bit decl_not_flexarray.
> >> * tree-streamer-out.cc (pack_ts_decl_common_value_fields): Stream
> >> out new bit decl_not_flexarray.
> >> * tree.cc (array_at_struct_end_p): Update it with the new bit field
> >> decl_not_flexarray.
> >> * tree.h (DECL_NOT_FLEXARRAY): New fla
> >
> > The middle-end changes are OK, the c/ and cp/ changes need review
> > from a frontend maintainer.
>
> I CC?ed Joseph Myers for the FE part review. Joseph, could you please review the changes in c-family and c?
> And Nathan Sidwell for the C++ part, Nathan, could you please review the changes in cp?
>
>
> >
> > Are the testcases actually C/C++ code? You can use
> > testsuite/c-c++-common/ to place tests that run with both frontends.
>
> The major issue when I tried to add these test cases into c-c++-common is, these testing cases mainly for the options usage, for example, -std=c89, -std=gnu89 for C, -std=c++98, -std=gnu++98 for C++.
>
> For C and C++, the options that are tested are different. So, I am not
> sure how can I put the same testing case for C and C++ but with
> different options?
Ah, right, I failed to spot that.
Richard.
> Qing
>
> >
> > Richard.
> >
> >>
> >> gcc/testsuite/ChangeLog:
> >>
> >> * g++.dg/strict-flex-array-1.C: New test.
> >> * g++.dg/strict-flex-array-2.C: New test.
> >> * g++.dg/strict-flex-array-3.C: New test.
> >> * g++.dg/strict-flex-array-4.C: New test.
> >> * gcc.dg/strict-flex-array-1.c: New test.
> >> * gcc.dg/strict-flex-array-2.c: New test.
> >> * gcc.dg/strict-flex-array-3.c: New test.
> >> * gcc.dg/strict-flex-array-4.c: New test.
> >> ---
> >> gcc/c-family/c-attribs.cc | 94 +++++++++++++++
> >> gcc/c-family/c-opts.cc | 41 +++++++
> >> gcc/c-family/c.opt | 7 ++
> >> gcc/c/c-decl.cc | 130 +++++++++++++++++++--
> >> gcc/cp/module.cc | 2 +
> >> gcc/doc/extend.texi | 33 ++++++
> >> gcc/doc/invoke.texi | 34 +++++-
> >> gcc/print-tree.cc | 8 +-
> >> gcc/testsuite/g++.dg/strict-flex-array-1.C | 31 +++++
> >> gcc/testsuite/g++.dg/strict-flex-array-2.C | 16 +++
> >> gcc/testsuite/g++.dg/strict-flex-array-3.C | 21 ++++
> >> gcc/testsuite/g++.dg/strict-flex-array-4.C | 9 ++
> >> gcc/testsuite/gcc.dg/strict-flex-array-1.c | 31 +++++
> >> gcc/testsuite/gcc.dg/strict-flex-array-2.c | 15 +++
> >> gcc/testsuite/gcc.dg/strict-flex-array-3.c | 21 ++++
> >> gcc/testsuite/gcc.dg/strict-flex-array-4.c | 10 ++
> >> gcc/tree-core.h | 5 +-
> >> gcc/tree-streamer-in.cc | 1 +
> >> gcc/tree-streamer-out.cc | 1 +
> >> gcc/tree.cc | 45 +++++--
> >> gcc/tree.h | 14 ++-
> >> 21 files changed, 541 insertions(+), 28 deletions(-)
> >> create mode 100644 gcc/testsuite/g++.dg/strict-flex-array-1.C
> >> create mode 100644 gcc/testsuite/g++.dg/strict-flex-array-2.C
> >> create mode 100644 gcc/testsuite/g++.dg/strict-flex-array-3.C
> >> create mode 100644 gcc/testsuite/g++.dg/strict-flex-array-4.C
> >> create mode 100644 gcc/testsuite/gcc.dg/strict-flex-array-1.c
> >> create mode 100644 gcc/testsuite/gcc.dg/strict-flex-array-2.c
> >> create mode 100644 gcc/testsuite/gcc.dg/strict-flex-array-3.c
> >> create mode 100644 gcc/testsuite/gcc.dg/strict-flex-array-4.c
> >>
> >> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> >> index e4f1d3542f37..9c9927cefa0d 100644
> >> --- a/gcc/c-family/c-attribs.cc
> >> +++ b/gcc/c-family/c-attribs.cc
> >> @@ -101,6 +101,8 @@ static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *);
> >> static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
> >> static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
> >> int, bool *);
> >> +static tree handle_strict_flex_arrays_attribute (tree *, tree, tree,
> >> + int, bool *);
> >> static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
> >> static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
> >> static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
> >> @@ -368,6 +370,8 @@ const struct attribute_spec c_common_attribute_table[] =
> >> attr_aligned_exclusions },
> >> { "warn_if_not_aligned", 0, 1, false, false, false, false,
> >> handle_warn_if_not_aligned_attribute, NULL },
> >> + { "strict_flex_arrays", 1, 1, false, false, false, false,
> >> + handle_strict_flex_arrays_attribute, NULL },
> >> { "weak", 0, 0, true, false, false, false,
> >> handle_weak_attribute, NULL },
> >> { "noplt", 0, 0, true, false, false, false,
> >> @@ -2505,6 +2509,96 @@ handle_warn_if_not_aligned_attribute (tree *node, tree name,
> >> no_add_attrs, true);
> >> }
> >>
> >> +/* Handle a "strict_flex_arrays" attribute; arguments as in
> >> + struct attribute_spec.handler. */
> >> +
> >> +static tree
> >> +handle_strict_flex_arrays_attribute (tree *node, tree name,
> >> + tree args, int ARG_UNUSED (flags),
> >> + bool *no_add_attrs)
> >> +{
> >> + tree decl = *node;
> >> + tree argval = TREE_VALUE (args);
> >> +
> >> + /* This attribute only applies to field decls of a structure. */
> >> + if (TREE_CODE (decl) != FIELD_DECL)
> >> + {
> >> + error_at (DECL_SOURCE_LOCATION (decl),
> >> + "%qE attribute may not be specified for %q+D", name, decl);
> >> + *no_add_attrs = true;
> >> + }
> >> + /* This attribute only applies to field with array type. */
> >> + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
> >> + {
> >> + error_at (DECL_SOURCE_LOCATION (decl),
> >> + "%qE attribute may not be specified for a non array field",
> >> + name);
> >> + *no_add_attrs = true;
> >> + }
> >> + else if (TREE_CODE (argval) != INTEGER_CST)
> >> + {
> >> + error_at (DECL_SOURCE_LOCATION (decl),
> >> + "%qE attribute argument not an integer", name);
> >> + *no_add_attrs = true;
> >> + }
> >> + else if (!tree_fits_uhwi_p (argval) || tree_to_uhwi (argval) > 3)
> >> + {
> >> + error_at (DECL_SOURCE_LOCATION (decl),
> >> + "%qE attribute argument %qE is not an integer constant"
> >> + " between 0 and 3", name, argval);
> >> + *no_add_attrs = true;
> >> + }
> >> + else
> >> + {
> >> + unsigned int level = tree_to_uhwi (argval);
> >> + /* check whether the attribute is valid based on language standard.
> >> + the attribute is only valid when flexible array member is
> >> + supported in the language. Therefore, we should invalid this attribute or
> >> + specific level of this attribute for the following situations:
> >> + A. When -std=c89 is specified, no language support at all, invalid this
> >> + attribute and issue a warning;
> >> + B. When -std=gnu89 is specified, only zero-length array extension and
> >> + one-size array are supported, level=3 will be invalid and a warning
> >> + will be issued.
> >> + C. C++ without GNU extension, no language support at all, invalid this
> >> + attribute and issue a warning;
> >> + D. C++ with GNU extension, only zero-length array extension and one-size
> >> + array are supported, level=3 will be invalid and a warning will be
> >> + issued. */
> >> + if (level > 0)
> >> + {
> >> + if (!c_dialect_cxx () && flag_iso && flag_isoc99 == 0)
> >> + {
> >> + warning (OPT_Wattributes, "%qE attribute ignored since it is "
> >> + "not supported with a ISO C before C99", name);
> >> + *no_add_attrs = true;
> >> + }
> >> + else if (!c_dialect_cxx () && !flag_iso
> >> + && flag_isoc99 == 0 && level == 3)
> >> + {
> >> + warning (OPT_Wattributes, "%qE = 3 attribute ignored since it is "
> >> + "not supported with a GNU extension GNU89", name);
> >> + *no_add_attrs = true;
> >> + }
> >> + else if (c_dialect_cxx () && flag_iso)
> >> + {
> >> + warning (OPT_Wattributes, "%qE attribute ignored since it is "
> >> + "not supported with a ISO C++", name);
> >> + *no_add_attrs = true;
> >> + }
> >> + else if (c_dialect_cxx () && !flag_iso
> >> + && level == 3)
> >> + {
> >> + warning (OPT_Wattributes, "%qE = 3 attribute ignored since it is "
> >> + "not supported for C++ with GNU extension", name);
> >> + *no_add_attrs = true;
> >> + }
> >> + }
> >> + }
> >> +
> >> + return NULL_TREE;
> >> +}
> >> +
> >> /* Handle a "weak" attribute; arguments as in
> >> struct attribute_spec.handler. */
> >>
> >> diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
> >> index 4e1463689de3..639eb40f3c86 100644
> >> --- a/gcc/c-family/c-opts.cc
> >> +++ b/gcc/c-family/c-opts.cc
> >> @@ -870,6 +870,47 @@ c_common_post_options (const char **pfilename)
> >> SET_OPTION_IF_UNSET (&global_options, &global_options_set,
> >> flag_tree_loop_distribute_patterns, 0);
> >>
> >> + /* -fstrict-flex-arrays is only valid when flexible array member is
> >> + supported in the language. Therefore, we should invalid this option or
> >> + specific level of this option for the following situations:
> >> + A. When -std=c89 is specified, no language support at all, invalid this
> >> + option and issue a warning;
> >> + B. When -std=gnu89 is specified, only zero-length array extension and
> >> + one-size array are supported, level=3 will be invalid and a warning
> >> + will be issued.
> >> + C. C++ without GNU extension, no language support at all, invalid this
> >> + option and issue a warning;
> >> + D. C++ with GNU extension, only zero-length array extension and one-size
> >> + array are supported, level=3 will be invalid and a warning will be
> >> + issued. */
> >> + if (flag_strict_flex_arrays > 0)
> >> + {
> >> + if (!c_dialect_cxx () && flag_iso && flag_isoc99 == 0)
> >> + {
> >> + flag_strict_flex_arrays = 0;
> >> + warning (0, "%<-fstrict-flex-arrays%> is not supported with a ISO C "
> >> + "before C99, ignored");
> >> + }
> >> + else if (!c_dialect_cxx () && !flag_iso && flag_isoc99 == 0 && flag_strict_flex_arrays == 3)
> >> + {
> >> + flag_strict_flex_arrays = 0;
> >> + warning (0, "%<-fstrict-flex-arrays=3%> is not supported with a "
> >> + "GNU extension GNU89, ignored");
> >> + }
> >> + else if (c_dialect_cxx () && flag_iso)
> >> + {
> >> + flag_strict_flex_arrays = 0;
> >> + warning (0, "%<-fstrict-flex-arrays%> is not supported with a ISO "
> >> + "C++, ignored");
> >> + }
> >> + else if (c_dialect_cxx () && !flag_iso && flag_strict_flex_arrays == 3)
> >> + {
> >> + flag_strict_flex_arrays = 0;
> >> + warning (0, "%<-fstrict-flex-arrays=3%> is not supported for C++ "
> >> + "with GNU extension, ignored");
> >> + }
> >> + }
> >> +
> >> /* -Woverlength-strings is off by default, but is enabled by -Wpedantic.
> >> It is never enabled in C++, as the minimum limit is not normative
> >> in that standard. */
> >> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> >> index 44e1a60ce246..1e944f8a3055 100644
> >> --- a/gcc/c-family/c.opt
> >> +++ b/gcc/c-family/c.opt
> >> @@ -2060,6 +2060,13 @@ fsized-deallocation
> >> C++ ObjC++ Var(flag_sized_deallocation) Init(-1)
> >> Enable C++14 sized deallocation support.
> >>
> >> +fstrict-flex-arrays
> >> +C C++ Common Alias(fstrict-flex-arrays=,3,0)
> >> +
> >> +fstrict-flex-arrays=
> >> +C C++ Common Joined RejectNegative UInteger Var(flag_strict_flex_arrays) Init(0) IntegerRange(0,3)
> >> +-fstrict-flex-arrays=<level> Treat the trailing array of a structure as a flexible array in a stricter way. The default is treating all trailing arrays of structures as flexible arrays.
> >> +
> >> fsquangle
> >> C++ ObjC++ WarnRemoved
> >>
> >> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> >> index ae8990c138fd..a2e125d4ddd5 100644
> >> --- a/gcc/c/c-decl.cc
> >> +++ b/gcc/c/c-decl.cc
> >> @@ -4999,6 +4999,41 @@ set_array_declarator_inner (struct c_declarator *decl,
> >> return decl;
> >> }
> >>
> >> +/* Determine whether TYPE is a ISO C99 flexible array memeber type "[]". */
> >> +static bool
> >> +flexible_array_member_type_p (const_tree type)
> >> +{
> >> + if (TREE_CODE (type) == ARRAY_TYPE
> >> + && TYPE_SIZE (type) == NULL_TREE
> >> + && TYPE_DOMAIN (type) != NULL_TREE
> >> + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
> >> + return true;
> >> +
> >> + return false;
> >> +}
> >> +
> >> +/* Determine whether TYPE is a one-element array type "[1]". */
> >> +static bool
> >> +one_element_array_type_p (const_tree type)
> >> +{
> >> + if (TREE_CODE (type) != ARRAY_TYPE)
> >> + return false;
> >> + return integer_zerop (array_type_nelts (type));
> >> +}
> >> +
> >> +/* Determine whether TYPE is a zero-length array type "[0]". */
> >> +static bool
> >> +zero_length_array_type_p (const_tree type)
> >> +{
> >> + if (TREE_CODE (type) == ARRAY_TYPE)
> >> + if (tree type_size = TYPE_SIZE_UNIT (type))
> >> + if ((integer_zerop (type_size))
> >> + && TYPE_DOMAIN (type) != NULL_TREE
> >> + && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
> >> + return true;
> >> + return false;
> >> +}
> >> +
> >> /* INIT is a constructor that forms DECL's initializer. If the final
> >> element initializes a flexible array field, add the size of that
> >> initializer to DECL's size. */
> >> @@ -5013,10 +5048,7 @@ add_flexible_array_elts_to_size (tree decl, tree init)
> >>
> >> elt = CONSTRUCTOR_ELTS (init)->last ().value;
> >> type = TREE_TYPE (elt);
> >> - if (TREE_CODE (type) == ARRAY_TYPE
> >> - && TYPE_SIZE (type) == NULL_TREE
> >> - && TYPE_DOMAIN (type) != NULL_TREE
> >> - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
> >> + if (flexible_array_member_type_p (type))
> >> {
> >> complete_array_type (&type, elt, false);
> >> DECL_SIZE (decl)
> >> @@ -8720,6 +8752,81 @@ finish_incomplete_vars (tree incomplete_vars, bool toplevel)
> >> }
> >> }
> >>
> >> +
> >> +/* Determine whether the FIELD_DECL X is a flexible array member according to
> >> + the following info:
> >> + A. whether the FIELD_DECL X is the last field of the DECL_CONTEXT;
> >> + B. whether the FIELD_DECL is an array that is declared as "[]", "[0]",
> >> + or "[1]";
> >> + C. flag_strict_flex_arrays;
> >> + D. the attribute strict_flex_array that is attached to the field
> >> + if presenting.
> >> + Return TRUE when it's a flexible array member, FALSE otherwise. */
> >> +
> >> +static bool
> >> +is_flexible_array_member_p (bool is_last_field,
> >> + tree x)
> >> +{
> >> + /* if not the last field, return false. */
> >> + if (!is_last_field)
> >> + return false;
> >> +
> >> + /* if not an array field, return false. */
> >> + if (TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE)
> >> + return false;
> >> +
> >> + bool is_zero_length_array = zero_length_array_type_p (TREE_TYPE (x));
> >> + bool is_one_element_array = one_element_array_type_p (TREE_TYPE (x));
> >> + bool is_flexible_array = flexible_array_member_type_p (TREE_TYPE (x));
> >> +
> >> + unsigned int strict_flex_array_level = flag_strict_flex_arrays;
> >> +
> >> + tree attr_strict_flex_array = lookup_attribute ("strict_flex_arrays",
> >> + DECL_ATTRIBUTES (x));
> >> + /* if there is a strict_flex_array attribute attached to the field,
> >> + override the flag_strict_flex_arrays. */
> >> + if (attr_strict_flex_array)
> >> + {
> >> + /* get the value of the level first from the attribute. */
> >> + unsigned HOST_WIDE_INT attr_strict_flex_array_level = 0;
> >> + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE);
> >> + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array);
> >> + gcc_assert (TREE_VALUE (attr_strict_flex_array) != NULL_TREE);
> >> + attr_strict_flex_array = TREE_VALUE (attr_strict_flex_array);
> >> + gcc_assert (tree_fits_uhwi_p (attr_strict_flex_array));
> >> + attr_strict_flex_array_level = tree_to_uhwi (attr_strict_flex_array);
> >> +
> >> + /* the attribute has higher priority than flag_struct_flex_array. */
> >> + strict_flex_array_level = attr_strict_flex_array_level;
> >> + }
> >> +
> >> + switch (strict_flex_array_level)
> >> + {
> >> + case 0:
> >> + /* default, all trailing arrays are flexiable array members. */
> >> + return true;
> >> + case 1:
> >> + /* Level 1: all "[1]", "[0]", and "[]" are flexiable array members. */
> >> + if (is_one_element_array)
> >> + return true;
> >> + /* FALLTHROUGH. */
> >> + case 2:
> >> + /* Level 2: all "[0]", and "[]" are flexiable array members. */
> >> + if (is_zero_length_array)
> >> + return true;
> >> + /* FALLTHROUGH. */
> >> + case 3:
> >> + /* Level 3: Only "[]" are flexible array members. */
> >> + if (is_flexible_array)
> >> + return true;
> >> + break;
> >> + default:
> >> + gcc_unreachable ();
> >> + }
> >> + return false;
> >> +}
> >> +
> >> +
> >> /* Fill in the fields of a RECORD_TYPE or UNION_TYPE node, T.
> >> LOC is the location of the RECORD_TYPE or UNION_TYPE's definition.
> >> FIELDLIST is a chain of FIELD_DECL nodes for the fields.
> >> @@ -8781,6 +8888,11 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> >> bool saw_named_field = false;
> >> for (x = fieldlist; x; x = DECL_CHAIN (x))
> >> {
> >> + /* whether this field is the last field of the structure or union.
> >> + for UNION, any field is the last field of it. */
> >> + bool is_last_field = (DECL_CHAIN (x) == NULL_TREE)
> >> + || (TREE_CODE (t) == UNION_TYPE);
> >> +
> >> if (TREE_TYPE (x) == error_mark_node)
> >> continue;
> >>
> >> @@ -8819,10 +8931,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> >> DECL_PACKED (x) = 1;
> >>
> >> /* Detect flexible array member in an invalid context. */
> >> - if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
> >> - && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
> >> - && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
> >> - && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
> >> + if (flexible_array_member_type_p (TREE_TYPE (x)))
> >> {
> >> if (TREE_CODE (t) == UNION_TYPE)
> >> {
> >> @@ -8830,7 +8939,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> >> "flexible array member in union");
> >> TREE_TYPE (x) = error_mark_node;
> >> }
> >> - else if (DECL_CHAIN (x) != NULL_TREE)
> >> + else if (!is_last_field)
> >> {
> >> error_at (DECL_SOURCE_LOCATION (x),
> >> "flexible array member not at end of struct");
> >> @@ -8850,6 +8959,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> >> pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
> >> "invalid use of structure with flexible array member");
> >>
> >> + /* Set DECL_NOT_FLEXARRAY flag for FIELD_DECL x. */
> >> + DECL_NOT_FLEXARRAY (x) = !is_flexible_array_member_p (is_last_field, x);
> >> +
> >> 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 f27f4d091e5e..75ee2514f66b 100644
> >> --- a/gcc/cp/module.cc
> >> +++ b/gcc/cp/module.cc
> >> @@ -5414,6 +5414,7 @@ trees_out::core_bools (tree t)
> >> WB (t->decl_common.decl_by_reference_flag);
> >> WB (t->decl_common.decl_read_flag);
> >> WB (t->decl_common.decl_nonshareable_flag);
> >> + WB (t->decl_common.decl_not_flexarray);
> >> }
> >>
> >> if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
> >> @@ -5558,6 +5559,7 @@ trees_in::core_bools (tree t)
> >> RB (t->decl_common.decl_by_reference_flag);
> >> RB (t->decl_common.decl_read_flag);
> >> RB (t->decl_common.decl_nonshareable_flag);
> >> + RB (t->decl_common.decl_not_flexarray);
> >> }
> >>
> >> if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
> >> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> >> index 7fe7f8817cdd..99b43ed3852c 100644
> >> --- a/gcc/doc/extend.texi
> >> +++ b/gcc/doc/extend.texi
> >> @@ -7473,6 +7473,39 @@ This warning can be disabled by @option{-Wno-if-not-aligned}.
> >> The @code{warn_if_not_aligned} attribute can also be used for types
> >> (@pxref{Common Type Attributes}.)
> >>
> >> +@cindex @code{strict_flex_arrays} variable attribute
> >> +@item strict_flex_arrays (@var{level})
> >> +The @code{strict_flex_arrays} attribute should be attached to the trailing
> >> +array field of a structure. It specifies the level of strictness of
> >> +treating the trailing array field of a structure as a flexible array
> >> +member. @var{level} must be an integer betwen 0 to 3.
> >> +
> >> +@var{level}=0 is the least strict level, all trailing arrays of structures
> >> +are treated as flexible array members. @var{level}=3 is the strictest level,
> >> +only when the trailing array is declared as a flexible array member per C99
> >> +standard onwards ([]), it is treated as a flexible array member.
> >> +
> >> +There are two more levels in between 0 and 3, which are provided to support
> >> +older codes that use GCC zero-length array extension ([0]) or one-size array
> >> +as flexible array member ([1]):
> >> +When @var{level} is 1, the trailing array is treated as a flexible array member
> >> +when it is declared as either "[]", "[0]", or "[1]";
> >> +When @var{level} is 2, the trailing array is treated as a flexible array member
> >> +when it is declared as either "[]", or "[0]".
> >> +
> >> +This attribute can be used with or without the @option{-fstrict-flex-arrays}.
> >> +When both the attribute and the option present at the same time, the level of
> >> +the strictness for the specific trailing array field is determined by the
> >> +attribute.
> >> +
> >> +This attribute is only valid when flexible array member is supported in the
> >> +language. For ISO C before C99 and ISO C++, no language support for the flexible
> >> +array member at all, this attribute will be invalid and a warning is issued.
> >> +When -std=gnu89 is specified or C++ with GNU extension, only zero-length array
> >> +extension and one-size array are supported, as a result, @var{level}=3 will be
> >> +invalid and a warning is issued.
> >> +
> >> +
> >> @item alloc_size (@var{position})
> >> @itemx alloc_size (@var{position-1}, @var{position-2})
> >> @cindex @code{alloc_size} variable attribute
> >> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> >> index 863580b3710a..2a0a3cf3de10 100644
> >> --- a/gcc/doc/invoke.texi
> >> +++ b/gcc/doc/invoke.texi
> >> @@ -207,7 +207,8 @@ in the following sections.
> >> -fopenmp -fopenmp-simd @gol
> >> -fpermitted-flt-eval-methods=@var{standard} @gol
> >> -fplan9-extensions -fsigned-bitfields -funsigned-bitfields @gol
> >> --fsigned-char -funsigned-char -fsso-struct=@var{endianness}}
> >> +-fsigned-char -funsigned-char -fstrict-flex-arrays[=@var{n}] @gol
> >> +-fsso-struct=@var{endianness}}
> >>
> >> @item C++ Language Options
> >> @xref{C++ Dialect Options,,Options Controlling C++ Dialect}.
> >> @@ -2826,6 +2827,37 @@ The type @code{char} is always a distinct type from each of
> >> @code{signed char} or @code{unsigned char}, even though its behavior
> >> is always just like one of those two.
> >>
> >> +@item -fstrict-flex-arrays
> >> +@opindex fstrict-flex-arrays
> >> +@opindex fno-strict-flex-arrays
> >> +Treat the trailing array of a structure as a flexible array member in a
> >> +stricter way.
> >> +The positive form is equivalent to @option{-fstrict-flex-arrays=3}, which is the
> >> +strictest. A trailing array is treated as a flexible array member only when it
> >> +is declared as a flexible array member per C99 standard onwards.
> >> +The negative form is equivalent to @option{-fstrict-flex-arrays=0}, which is the
> >> +least strict. All trailing arrays of structures are treated as flexible array
> >> +members.
> >> +
> >> +@item -fstrict-flex-arrays=@var{level}
> >> +@opindex fstrict-flex-arrays=@var{level}
> >> +Treat the trailing array of a structure as a flexible array member in a
> >> +stricter way. The value of @var{level} controls the level of strictness.
> >> +
> >> +The possible values of @var{level} are the same as for the
> >> +@code{strict_flex_array} attribute (@pxref{Variable Attributes}).
> >> +
> >> +You can control this behavior for a specific trailing array field of a
> >> +structure by using the variable attribute @code{strict_flex_array} attribute
> >> +(@pxref{Variable Attributes}).
> >> +
> >> +This option is only valid when flexible array member is supported in the
> >> +language. FOR ISO C before C99 and ISO C++, no language support for the flexible
> >> +array member at all, this option will be invalid and a warning will be issued.
> >> +When -std=gnu89 is specified or C++ with GNU extension, only zero-length array
> >> +extension and one-size array are supported, as a result, @var{level}=3 will be
> >> +invalid and a warning will be issued.
> >> +
> >> @item -fsso-struct=@var{endianness}
> >> @opindex fsso-struct
> >> Set the default scalar storage order of structures and unions to the
> >> diff --git a/gcc/print-tree.cc b/gcc/print-tree.cc
> >> index 6d45a4a59669..58a98250cc4f 100644
> >> --- a/gcc/print-tree.cc
> >> +++ b/gcc/print-tree.cc
> >> @@ -517,8 +517,12 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
> >> fprintf (file, " align:%d warn_if_not_align:%d",
> >> DECL_ALIGN (node), DECL_WARN_IF_NOT_ALIGN (node));
> >> if (code == FIELD_DECL)
> >> - fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
> >> - DECL_OFFSET_ALIGN (node));
> >> + {
> >> + fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
> >> + DECL_OFFSET_ALIGN (node));
> >> + fprintf (file, " decl_not_flexarray: %d",
> >> + DECL_NOT_FLEXARRAY (node));
> >> + }
> >>
> >> if (code == FUNCTION_DECL && fndecl_built_in_p (node))
> >> {
> >> diff --git a/gcc/testsuite/g++.dg/strict-flex-array-1.C b/gcc/testsuite/g++.dg/strict-flex-array-1.C
> >> new file mode 100644
> >> index 000000000000..47adaf7bac4a
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.dg/strict-flex-array-1.C
> >> @@ -0,0 +1,31 @@
> >> +/* testing the correct usage of attribute strict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2" } */
> >> +
> >> +
> >> +int x __attribute__ ((strict_flex_arrays (1))); /* { dg-error "'strict_flex_arrays' attribute may not be specified for 'x'" } */
> >> +
> >> +struct trailing {
> >> + int a;
> >> + int c __attribute ((strict_flex_arrays)); /* { dg-error "wrong number of arguments specified for 'strict_flex_arrays' attribute" } */
> >> +};
> >> +
> >> +struct trailing_1 {
> >> + int a;
> >> + int b;
> >> + int c __attribute ((strict_flex_arrays (2))); /* { dg-error "'strict_flex_arrays' attribute may not be specified for a non array field" } */
> >> +};
> >> +
> >> +extern int d;
> >> +
> >> +struct trailing_array_2 {
> >> + int a;
> >> + int b;
> >> + int c[1] __attribute ((strict_flex_arrays (d))); /* { dg-error "'strict_flex_arrays' attribute argument not an integer" } */
> >> +};
> >> +
> >> +struct trailing_array_3 {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (5))); /* { dg-error "'strict_flex_arrays' attribute argument '5' is not an integer constant between 0 and 3" } */
> >> +};
> >> diff --git a/gcc/testsuite/g++.dg/strict-flex-array-2.C b/gcc/testsuite/g++.dg/strict-flex-array-2.C
> >> new file mode 100644
> >> index 000000000000..245f8fe0bc73
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.dg/strict-flex-array-2.C
> >> @@ -0,0 +1,16 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array for C++. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays -std=c++98" } */
> >> +
> >> +struct trailing_array {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (3))); /* { dg-warning "attribute ignored since it is not supported with a ISO C\\+\\+" } */
> >> +};
> >> +
> >> +int foo(int a)
> >> +{
> >> + return 0;
> >> +}
> >> +
> >> +/* { dg-warning "is not supported with a ISO C\\+\\+, ignored" "" { target *-*-* } 0 } */
> >> diff --git a/gcc/testsuite/g++.dg/strict-flex-array-3.C b/gcc/testsuite/g++.dg/strict-flex-array-3.C
> >> new file mode 100644
> >> index 000000000000..2a733a5bccf4
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.dg/strict-flex-array-3.C
> >> @@ -0,0 +1,21 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array for C++. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays -std=gnu++98" } */
> >> +/* { dg-warning "'-fstrict-flex-arrays=3' is not supported for C\\+\\+ with GNU extension, ignored" "" { target *-*-* } 0 } */
> >> +
> >> +struct trailing_array {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (3))); /* { dg-warning "'strict_flex_arrays' = 3 attribute ignored since it is not supported for C\\+\\+ with GNU extension" } */
> >> +};
> >> +
> >> +struct trailing_array_1 {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (2))); /* { dg-bogus "'strict_flex_arrays' = 3 attribute ignored since it is not supported for C\\+\\+ with GNU extension" } */
> >> +};
> >> +
> >> +int foo(int a)
> >> +{
> >> + return a + 2;
> >> +}
> >> diff --git a/gcc/testsuite/g++.dg/strict-flex-array-4.C b/gcc/testsuite/g++.dg/strict-flex-array-4.C
> >> new file mode 100644
> >> index 000000000000..804e4cf459ef
> >> --- /dev/null
> >> +++ b/gcc/testsuite/g++.dg/strict-flex-array-4.C
> >> @@ -0,0 +1,9 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays=2 -std=gnu++98" } */
> >> +/* { dg-bogus "is not supported for C\\+\\+ with GNU extension, ignored" "" { target *-*-* } 0 } */
> >> +
> >> +int foo(int a)
> >> +{
> >> + return a + 2;
> >> +}
> >> diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-1.c b/gcc/testsuite/gcc.dg/strict-flex-array-1.c
> >> new file mode 100644
> >> index 000000000000..47adaf7bac4a
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gcc.dg/strict-flex-array-1.c
> >> @@ -0,0 +1,31 @@
> >> +/* testing the correct usage of attribute strict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2" } */
> >> +
> >> +
> >> +int x __attribute__ ((strict_flex_arrays (1))); /* { dg-error "'strict_flex_arrays' attribute may not be specified for 'x'" } */
> >> +
> >> +struct trailing {
> >> + int a;
> >> + int c __attribute ((strict_flex_arrays)); /* { dg-error "wrong number of arguments specified for 'strict_flex_arrays' attribute" } */
> >> +};
> >> +
> >> +struct trailing_1 {
> >> + int a;
> >> + int b;
> >> + int c __attribute ((strict_flex_arrays (2))); /* { dg-error "'strict_flex_arrays' attribute may not be specified for a non array field" } */
> >> +};
> >> +
> >> +extern int d;
> >> +
> >> +struct trailing_array_2 {
> >> + int a;
> >> + int b;
> >> + int c[1] __attribute ((strict_flex_arrays (d))); /* { dg-error "'strict_flex_arrays' attribute argument not an integer" } */
> >> +};
> >> +
> >> +struct trailing_array_3 {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (5))); /* { dg-error "'strict_flex_arrays' attribute argument '5' is not an integer constant between 0 and 3" } */
> >> +};
> >> diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-2.c b/gcc/testsuite/gcc.dg/strict-flex-array-2.c
> >> new file mode 100644
> >> index 000000000000..967a240040dc
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gcc.dg/strict-flex-array-2.c
> >> @@ -0,0 +1,15 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays -std=c89" } */
> >> +/* { dg-warning "'-fstrict-flex-arrays' is not supported with a ISO C before C99, ignored" "" { target *-*-* } 0 } */
> >> +
> >> +struct trailing_array {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (3))); /* { dg-warning "'strict_flex_arrays' attribute ignored since it is not supported with a ISO C before C99" } */
> >> +};
> >> +
> >> +int foo(int a)
> >> +{
> >> + return a + 2;
> >> +}
> >> diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-3.c b/gcc/testsuite/gcc.dg/strict-flex-array-3.c
> >> new file mode 100644
> >> index 000000000000..879de7f203c8
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gcc.dg/strict-flex-array-3.c
> >> @@ -0,0 +1,21 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays -std=gnu89" } */
> >> +/* { dg-warning "'-fstrict-flex-arrays=3' is not supported with a GNU extension GNU89, ignored" "" { target *-*-* } 0 } */
> >> +
> >> +struct trailing_array {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (3))); /* { dg-warning "'strict_flex_arrays' = 3 attribute ignored since it is not supported with a GNU extension GNU89" } */
> >> +};
> >> +
> >> +struct trailing_array_1 {
> >> + int a;
> >> + int b;
> >> + int c[0] __attribute ((strict_flex_arrays (2))); /* { dg-bogus "'strict_flex_arrays' = 3 attribute ignored since it is not supported with a GNU extension GNU89" } */
> >> +};
> >> +
> >> +int foo(int a)
> >> +{
> >> + return a + 2;
> >> +}
> >> diff --git a/gcc/testsuite/gcc.dg/strict-flex-array-4.c b/gcc/testsuite/gcc.dg/strict-flex-array-4.c
> >> new file mode 100644
> >> index 000000000000..ce64c24db301
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gcc.dg/strict-flex-array-4.c
> >> @@ -0,0 +1,10 @@
> >> +/* testing the correct usage of flag -fstrict_flex_array. */
> >> +/* { dg-do compile } */
> >> +/* { dg-options "-O2 -fstrict-flex-arrays=2 -std=gnu89" } */
> >> +/* { dg-bogus "is not supported with a GNU extension GNU89, ignored" "" { target *-*-* } 0 } */
> >> +
> >> +
> >> +int foo(int a)
> >> +{
> >> + return a + 2;
> >> +}
> >> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> >> index 86a07c282af2..f822cb539dd0 100644
> >> --- a/gcc/tree-core.h
> >> +++ b/gcc/tree-core.h
> >> @@ -1813,7 +1813,10 @@ struct GTY(()) tree_decl_common {
> >> TYPE_WARN_IF_NOT_ALIGN. */
> >> unsigned int warn_if_not_align : 6;
> >>
> >> - /* 14 bits unused. */
> >> + /* In FIELD_DECL, this is DECL_NOT_FLEXARRAY. */
> >> + unsigned int decl_not_flexarray : 1;
> >> +
> >> + /* 13 bits unused. */
> >>
> >> /* UID for points-to sets, stable over copying from inlining. */
> >> unsigned int pt_uid;
> >> diff --git a/gcc/tree-streamer-in.cc b/gcc/tree-streamer-in.cc
> >> index 196f19c759f2..21e6e8eb1c0a 100644
> >> --- a/gcc/tree-streamer-in.cc
> >> +++ b/gcc/tree-streamer-in.cc
> >> @@ -261,6 +261,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
> >> else
> >> SET_DECL_FIELD_ABI_IGNORED (expr, val);
> >> expr->decl_common.off_align = bp_unpack_value (bp, 8);
> >> + DECL_NOT_FLEXARRAY (expr) = (unsigned) bp_unpack_value (bp, 1);
> >> }
> >>
> >> else if (VAR_P (expr))
> >> diff --git a/gcc/tree-streamer-out.cc b/gcc/tree-streamer-out.cc
> >> index d39dc158a465..68e40dbdb8f2 100644
> >> --- a/gcc/tree-streamer-out.cc
> >> +++ b/gcc/tree-streamer-out.cc
> >> @@ -229,6 +229,7 @@ pack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
> >> else
> >> bp_pack_value (bp, DECL_FIELD_ABI_IGNORED (expr), 1);
> >> bp_pack_value (bp, expr->decl_common.off_align, 8);
> >> + bp_pack_value (bp, DECL_NOT_FLEXARRAY (expr), 1);
> >> }
> >>
> >> else if (VAR_P (expr))
> >> diff --git a/gcc/tree.cc b/gcc/tree.cc
> >> index fed1434d141d..d698e8c9c213 100644
> >> --- a/gcc/tree.cc
> >> +++ b/gcc/tree.cc
> >> @@ -12678,14 +12678,30 @@ array_ref_up_bound (tree exp)
> >> }
> >>
> >> /* Returns true if REF is an array reference, component reference,
> >> - or memory reference to an array at the end of a structure.
> >> - If this is the case, the array may be allocated larger
> >> - than its upper bound implies. */
> >> + or memory reference to an array whose actual size might be larger
> >> + than its upper bound implies, there are multiple cases:
> >> + A. a ref to a flexible array member at the end of a structure;
> >> + B. a ref to an array with a different type against the original decl;
> >> + for example:
> >>
> >> + short a[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
> >> + (*((char(*)[16])&a[0]))[i+8]
> >> +
> >> + C. a ref to an array that was passed as a parameter;
> >> + for example:
> >> +
> >> + int test (uint8_t *p, uint32_t t[1][1], int n) {
> >> + for (int i = 0; i < 4; i++, p++)
> >> + t[i][0] = ...;
> >> +
> >> + FIXME, the name of this routine need to be changed to be more accurate. */
> >> bool
> >> array_at_struct_end_p (tree ref)
> >> {
> >> - tree atype;
> >> + /* the TYPE for this array referece. */
> >> + tree atype = NULL_TREE;
> >> + /* the FIELD_DECL for the array field in the containing structure. */
> >> + tree afield_decl = NULL_TREE;
> >>
> >> if (TREE_CODE (ref) == ARRAY_REF
> >> || TREE_CODE (ref) == ARRAY_RANGE_REF)
> >> @@ -12695,7 +12711,10 @@ array_at_struct_end_p (tree ref)
> >> }
> >> else if (TREE_CODE (ref) == COMPONENT_REF
> >> && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
> >> - atype = TREE_TYPE (TREE_OPERAND (ref, 1));
> >> + {
> >> + atype = TREE_TYPE (TREE_OPERAND (ref, 1));
> >> + afield_decl = TREE_OPERAND (ref, 1);
> >> + }
> >> else if (TREE_CODE (ref) == MEM_REF)
> >> {
> >> tree arg = TREE_OPERAND (ref, 0);
> >> @@ -12707,6 +12726,7 @@ array_at_struct_end_p (tree ref)
> >> if (tree fld = last_field (argtype))
> >> {
> >> atype = TREE_TYPE (fld);
> >> + afield_decl = fld;
> >> if (TREE_CODE (atype) != ARRAY_TYPE)
> >> return false;
> >> if (VAR_P (arg) && DECL_SIZE (fld))
> >> @@ -12760,13 +12780,16 @@ array_at_struct_end_p (tree ref)
> >> ref = TREE_OPERAND (ref, 0);
> >> }
> >>
> >> - /* The array now is at struct end. Treat flexible arrays as
> >> + gcc_assert (!afield_decl
> >> + || (afield_decl && TREE_CODE (afield_decl) == FIELD_DECL));
> >> +
> >> + /* The array now is at struct end. Treat flexible array member as
> >> always subject to extend, even into just padding constrained by
> >> an underlying decl. */
> >> if (! TYPE_SIZE (atype)
> >> || ! TYPE_DOMAIN (atype)
> >> || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
> >> - return true;
> >> + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
> >>
> >> /* If the reference is based on a declared entity, the size of the array
> >> is constrained by its given domain. (Do not trust commons PR/69368). */
> >> @@ -12788,9 +12811,9 @@ array_at_struct_end_p (tree ref)
> >> if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (atype))) != INTEGER_CST
> >> || TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST
> >> || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (atype))) != INTEGER_CST)
> >> - return true;
> >> + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
> >> if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
> >> - return true;
> >> + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
> >>
> >> /* If at least one extra element fits it is a flexarray. */
> >> if (known_le ((wi::to_offset (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
> >> @@ -12798,12 +12821,12 @@ array_at_struct_end_p (tree ref)
> >> + 2)
> >> * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
> >> wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
> >> - return true;
> >> + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
> >>
> >> return false;
> >> }
> >>
> >> - return true;
> >> + return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
> >> }
> >>
> >> /* Return a tree representing the offset, in bytes, of the field referenced
> >> diff --git a/gcc/tree.h b/gcc/tree.h
> >> index e6564aaccb7b..f911c0a46e69 100644
> >> --- a/gcc/tree.h
> >> +++ b/gcc/tree.h
> >> @@ -2993,6 +2993,12 @@ extern void decl_value_expr_insert (tree, tree);
> >> #define DECL_PADDING_P(NODE) \
> >> (FIELD_DECL_CHECK (NODE)->decl_common.decl_flag_3)
> >>
> >> +/* Used in a FIELD_DECL to indicate whether this field is not a flexible
> >> + array member. This is only valid for the last array type field of a
> >> + structure. */
> >> +#define DECL_NOT_FLEXARRAY(NODE) \
> >> + (FIELD_DECL_CHECK (NODE)->decl_common.decl_not_flexarray)
> >> +
> >> /* A numeric unique identifier for a LABEL_DECL. The UID allocation is
> >> dense, unique within any one function, and may be used to index arrays.
> >> If the value is -1, then no UID has been assigned. */
> >> @@ -5531,10 +5537,10 @@ extern tree component_ref_field_offset (tree);
> >> returns null. */
> >> enum struct special_array_member
> >> {
> >> - none, /* Not a special array member. */
> >> - int_0, /* Interior array member with size zero. */
> >> - trail_0, /* Trailing array member with size zero. */
> >> - trail_1 /* Trailing array member with one element. */
> >> + none, /* Not a special array member. */
> >> + int_0, /* Interior array member with size zero. */
> >> + trail_0, /* Trailing array member with size zero. */
> >> + trail_1 /* Trailing array member with one element. */
> >> };
> >>
> >> /* Return the size of the member referenced by the COMPONENT_REF, using
> >>
> >
> > --
> > Richard Biener <rguenther@suse.de>
> > SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
> > Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
> > HRB 36809 (AG Nuernberg)
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg,
Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman;
HRB 36809 (AG Nuernberg)
More information about the Gcc-patches
mailing list