public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Qing Zhao <qing.zhao@oracle.com>
To: Richard Biener <rguenther@suse.de>
Cc: "joseph@codesourcery.com" <joseph@codesourcery.com>,
	gcc Patches <gcc-patches@gcc.gnu.org>,
	"keescook@chromium.org" <keescook@chromium.org>,
	"siddhesh@gcc.gnu.org" <siddhesh@gcc.gnu.org>
Subject: Re: [PATCH 2/2] Add a new warning option -Wstrict-flex-arrays.
Date: Fri, 18 Nov 2022 15:19:07 +0000	[thread overview]
Message-ID: <BF68D373-136E-43FC-BF39-DAE66F51A4A7@oracle.com> (raw)
In-Reply-To: <nycvar.YFH.7.77.849.2211181304080.3995@jbgna.fhfr.qr>

Hi, Richard,

Honestly, it’s very hard for me to decide what’s the best way to handle the interaction 
between -fstrict-flex-array=M and -Warray-bounds=N. 

Ideally,  -fstrict-flex-array=M should completely control the behavior of -Warray-bounds.
If possible, I prefer this solution.

However, -Warray-bounds is included in -Wall, and has been used extensively for a long time.
It’s not safe to change its default behavior. 

So, I guess that the bottom-line for this work is:

Keeping the default behavior of -Warray-bounds.

Is this correct understanding?


> On Nov 18, 2022, at 8:14 AM, Richard Biener <rguenther@suse.de> wrote:
> 
> On Tue, 8 Nov 2022, Qing Zhao wrote:
> 
>> '-Wstrict-flex-arrays'
>>     Warn about inproper usages of flexible array members according to
>>     the LEVEL of the 'strict_flex_array (LEVEL)' attribute attached to
>>     the trailing array field of a structure if it's available,
>>     otherwise according to the LEVEL of the option
>>     '-fstrict-flex-arrays=LEVEL'.
>> 
>>     This option is effective only when LEVEL is bigger than 0.
>>     Otherwise, it will be ignored with a warning.
>> 
>>     when LEVEL=1, warnings will be issued for a trailing array
>>     reference of a structure that have 2 or more elements if the
>>     trailing array is referenced as a flexible array member.
>> 
>>     when LEVEL=2, in addition to LEVEL=1, additional warnings will be
>>     issued for a trailing one-element array reference of a structure if
>>     the array is referenced as a flexible array member.
>> 
>>     when LEVEL=3, in addition to LEVEL=2, additional warnings will be
>>     issued for a trailing zero-length array reference of a structure if
>>     the array is referenced as a flexible array member.
>> 
>> At the same time, keep -Warray-bounds=[1|2] warnings unchanged from
>> -fstrict-flex-arrays.
> 
> Looking at this, is this a way to avoid interpreting -Warray-bounds=N
> together with -fstrict-flex-arrays=M?  Won't this be just confusing to
> users?  Especially since -Wall includes -Warray-bounds and thus we'll
> diagnose
> 
> +  if (opts->x_warn_array_bounds)
> +    if (opts->x_flag_strict_flex_arrays)
> +      {
> +       warning_at (UNKNOWN_LOCATION, 0,
> +                   "%<-Warray-bounds%> is not impacted by "
> +                   "%<-fstrict-flex-arrays%>");
> +      }
> 
> and do that even when -Wstrict-flex-arrays is given?

The basic idea here is:   -Warray-bounds=N will NOT be controlled by -fstrict-flex-array=M at all.
And the new -Wstrict-flex-array will be used to report warnings for different level of “M”. 

> 
> Would it be better/possible to add a note: to existing -Warray-bounds
> diagnostics on how the behavior is altered by -fstrict-flex-arrays?

If -Warray-bounds does not have the additional level “N” argument. It’s reasonable and natural for it to be controlled 
by the level of -fstrict-flex-arrays. 
> 
> I guess this will inevitably re-iterate the -fstrict-flex-arrays=N
> vs. -Warray-bounds=M discussion ...

Yes, that’s the most confusion and challenge part for this work… and took me a lot of thinking but still cannot
 find the best way to handle it…..
> 
> I think it would be better to stick with -Warray-bounds and flex
> its =2 mode to work according to -fstrict-flex-arrays=N instead of
> "out of bounds accesses to trailing struct members of one-element array 
> types" (thus, not add [1] but instead the cases that are not flex 
> arrays according to -fstrict-flex-arrays).

From my understanding, you suggested the following:

1. Keep -Warray-bounds default behavior.
    i.e. when -Warray-bounds=1, it’s behavior will not be impacted by -fstrict-flex-array=M

2. When -Warray-bounds=2,  it’s behavior will be controlled by -fstrict-flex-array=M


Is the above understanding correct?

If yes, then the major question is:

When -Warray-bounds=2, -fstrict-flex-array = 0 or 1,2,  i.e, when the level of -fstrict-flex-array is lower or equal to 2. 
 [0] and [1] will be treated as flexible array member by -fstrict-flex-array, it’s conflict with how -Warray-bounds=2’s 
behavior on treating flexible array members.  Under such situation, which one has higher priority?


I have another idea now:

1. Keep -Warray-bounds=1 default behavior. 
2. Change the behavior of -Warray-bounds=2 from:

Current:
-Warray-bounds=2
This warning level also warns about out of bounds accesses to trailing struct members of one-element array types (see Zero Length) and about the intermediate results of pointer arithmetic that may yield out of bounds values. This warning level may give a larger number of false positives and is deactivated by default.

New:
-Warray-bounds=2
This warning level also warns  about the intermediate results of pointer arithmetic that may yield out of bounds values. This warning level may give a larger number of false positives and is deactivated by default.

i.e, delete the control on flexible array member from the level of -Warray-bounds. 

3. Use -fstrict-flex-array to control how the -Warray-bounds treat the tailing array as flexible array member? 

Is this better?

thanks.

Qing

> 
> Richard.
> 
>> gcc/ChangeLog:
>> 
>> 	* attribs.cc (strict_flex_array_level_of): New function.
>> 	* attribs.h (strict_flex_array_level_of): Prototype for new function.
>> 	* doc/invoke.texi: Document -Wstrict-flex-arrays option. Update
>> 	-fstrict-flex-arrays[=n] options.
>> 	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref):
>> 	Issue warnings for -Wstrict-flex-arrays.
>> 	(get_up_bounds_for_array_ref): New function.
>> 	(check_out_of_bounds_and_warn): New function.
>> 	* opts.cc (finish_options): Issue warnings for unsupported combination
>> 	of -Warray-bounds and -fstrict-flex-arrays, -Wstrict_flex_arrays and
>> 	-fstrict-flex-array.
>> 	* tree-vrp.cc (execute_vrp): Enable the pass when
>> 	warn_strict_flex_array is true.
>> 	(execute_ranger_vrp): Likewise.
>> 	* tree.cc (array_ref_flexible_size_p): Add one new argument.
>> 	(component_ref_sam_type): New function.
>> 	(component_ref_size): Add one new argument,
>> 	* tree.h (array_ref_flexible_size_p): Update prototype.
>> 	(enum struct special_array_member): Add two new enum values.
>> 	(component_ref_sam_type): New prototype.
>> 	(component_ref_size): Update prototype.
>> 
>> gcc/c-family/ChangeLog:
>> 
>> 	* c.opt (Wstrict-flex-arrays): New option.
>> 
>> gcc/c/ChangeLog:
>> 
>> 	* c-decl.cc (is_flexible_array_member_p): Call new function
>> 	strict_flex_array_level_of.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>> 	* c-c++-common/Wstrict-flex-arrays.c: New test.
>> 	* c-c++-common/Wstrict-flex-arrays_2.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-2.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-3.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-4.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-5.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-6.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-7.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-8.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays-9.c: New test.
>> 	* gcc.dg/Wstrict-flex-arrays.c: New test.
>> ---
>> gcc/attribs.cc                                |  30 ++
>> gcc/attribs.h                                 |   2 +
>> gcc/c-family/c.opt                            |   5 +
>> gcc/c/c-decl.cc                               |  22 +-
>> gcc/doc/invoke.texi                           |  33 ++-
>> gcc/gimple-array-bounds.cc                    | 264 +++++++++++++-----
>> gcc/opts.cc                                   |  15 +
>> .../c-c++-common/Wstrict-flex-arrays.c        |   9 +
>> .../c-c++-common/Wstrict-flex-arrays_2.c      |   9 +
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c  |  46 +++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c  |  46 +++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-4.c  |  49 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-5.c  |  48 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-6.c  |  48 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-7.c  |  50 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-8.c  |  49 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays-9.c  |  49 ++++
>> gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c    |  46 +++
>> gcc/tree-vrp.cc                               |   6 +-
>> gcc/tree.cc                                   | 165 ++++++++---
>> gcc/tree.h                                    |  15 +-
>> 21 files changed, 870 insertions(+), 136 deletions(-)
>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays.c
>> create mode 100644 gcc/testsuite/c-c++-common/Wstrict-flex-arrays_2.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-4.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-5.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-6.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-7.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-8.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays-9.c
>> create mode 100644 gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>> 
>> diff --git a/gcc/attribs.cc b/gcc/attribs.cc
>> index 27dea748561..095def4d6b0 100644
>> --- a/gcc/attribs.cc
>> +++ b/gcc/attribs.cc
>> @@ -2456,6 +2456,36 @@ init_attr_rdwr_indices (rdwr_map *rwm, tree attrs)
>>     }
>> }
>> 
>> +/* Get the LEVEL of the strict_flex_array for the ARRAY_FIELD based on the
>> +   values of attribute strict_flex_array and the flag_strict_flex_arrays.  */
>> +unsigned int
>> +strict_flex_array_level_of (tree array_field)
>> +{
>> +  gcc_assert (TREE_CODE (array_field) == FIELD_DECL);
>> +  unsigned int strict_flex_array_level = flag_strict_flex_arrays;
>> +
>> +  tree attr_strict_flex_array
>> +    = lookup_attribute ("strict_flex_array", DECL_ATTRIBUTES (array_field));
>> +  /* 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;
>> +    }
>> +  return strict_flex_array_level;
>> +}
>> +
>> +
>> /* Return the access specification for a function parameter PARM
>>    or null if the current function has no such specification.  */
>> 
>> diff --git a/gcc/attribs.h b/gcc/attribs.h
>> index 1dc16e4bc4e..742811e6fda 100644
>> --- a/gcc/attribs.h
>> +++ b/gcc/attribs.h
>> @@ -398,4 +398,6 @@ extern void init_attr_rdwr_indices (rdwr_map *, tree);
>> extern attr_access *get_parm_access (rdwr_map &, tree,
>> 				     tree = current_function_decl);
>> 
>> +extern unsigned int strict_flex_array_level_of (tree);
>> +
>> #endif // GCC_ATTRIBS_H
>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>> index 01d480759ae..bc33710a649 100644
>> --- a/gcc/c-family/c.opt
>> +++ b/gcc/c-family/c.opt
>> @@ -968,6 +968,11 @@ Wstringop-truncation
>> C ObjC C++ LTO ObjC++ Var(warn_stringop_truncation) Warning Init (1) LangEnabledBy(C ObjC C++ LTO ObjC++, Wall)
>> Warn about truncation in string manipulation functions like strncat and strncpy.
>> 
>> +Wstrict-flex-arrays
>> +C C++ Var(warn_strict_flex_arrays) Warning
>> +Warn about inproper usages of flexible array members
>> +according to the level of -fstrict-flex-arrays.
>> +
>> Wsuggest-attribute=format
>> C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning
>> Warn about functions which might be candidates for format attributes.
>> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
>> index 4746e310d2d..c9cb46daacc 100644
>> --- a/gcc/c/c-decl.cc
>> +++ b/gcc/c/c-decl.cc
>> @@ -8828,7 +8828,6 @@ 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;
>> @@ -8855,26 +8854,7 @@ is_flexible_array_member_p (bool is_last_field,
>>   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_array",
>> -						  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;
>> -    }
>> +  unsigned int strict_flex_array_level = strict_flex_array_level_of (x);
>> 
>>   switch (strict_flex_array_level)
>>     {
>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index 64f77e8367a..a35e6bf27e0 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -397,7 +397,7 @@ Objective-C and Objective-C++ Dialects}.
>> -Wstrict-aliasing=n  -Wstrict-overflow  -Wstrict-overflow=@var{n} @gol
>> -Wstring-compare @gol
>> -Wno-stringop-overflow -Wno-stringop-overread @gol
>> --Wno-stringop-truncation @gol
>> +-Wno-stringop-truncation -Wstrict-flex-arrays @gol
>> -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}malloc@r{]} @gol
>> -Wswitch  -Wno-switch-bool  -Wswitch-default  -Wswitch-enum @gol
>> -Wno-switch-outside-range  -Wno-switch-unreachable  -Wsync-nand @gol
>> @@ -2848,12 +2848,18 @@ 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.
>> 
>> +This option is not compatible with @option{-Warray-bounds} due to historical
>> +reason.  The behavior of @option{-Warray-bounds} is not changed by this option.
>> +
>> @item -fstrict-flex-arrays=@var{level}
>> @opindex fstrict-flex-arrays=@var{level}
>> Control when to treat the trailing array of a structure as a flexible array
>> member for the purpose of accessing the elements of such an array.  The value
>> of @var{level} controls the level of strictness.
>> 
>> +This option is not compatible with @option{-Warray-bounds} due to historical
>> +reason.  The behavior of @option{-Warray-bounds} is not changed by this option.
>> +
>> The possible values of @var{level} are the same as for the
>> @code{strict_flex_array} attribute (@pxref{Variable Attributes}).
>> 
>> @@ -7662,6 +7668,31 @@ however, are not suitable arguments to functions that expect
>> such arrays GCC issues warnings unless it can prove that the use is
>> safe.  @xref{Common Variable Attributes}.
>> 
>> +@item -Wstrict-flex-arrays
>> +@opindex Wstrict-flex-arrays
>> +@opindex Wno-strict-flex-arrays
>> +Warn about inproper usages of flexible array members
>> +according to the @var{level} of the @code{strict_flex_array (@var{level})}
>> +attribute attached to the trailing array field of a structure if it's
>> +available, otherwise according to the @var{level} of the option
>> +@option{-fstrict-flex-arrays=@var{level}}.
>> +
>> +This option is effective only when @var{level} is bigger than 0.  Otherwise,
>> +it will be ignored with a warning.
>> +
>> +when @var{level}=1, warnings will be issued for a trailing array reference
>> +of a structure that have 2 or more elements if the trailing array is referenced
>> +as a flexible array member.
>> +
>> +when @var{level}=2, in addition to @var{level}=1, additional warnings will be
>> +issued for a trailing one-element array reference of a structure
>> +if the array is referenced as a flexible array member.
>> +
>> +when @var{level}=3, in addition to @var{level}=2, additional warnings will be
>> +issued for a trailing zero-length array reference of a structure
>> +if the array is referenced as a flexible array member.
>> +
>> +
>> @item -Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{|}cold@r{|}malloc@r{]}
>> @opindex Wsuggest-attribute=
>> @opindex Wno-suggest-attribute=
>> diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
>> index fbf448e045d..7f790c5a19a 100644
>> --- a/gcc/gimple-array-bounds.cc
>> +++ b/gcc/gimple-array-bounds.cc
>> @@ -170,38 +170,20 @@ trailing_array (tree arg, tree *pref)
>>   return array_ref_flexible_size_p (arg);
>> }
>> 
>> -/* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible
>> -   arrays and "struct" hacks. If VRP can determine that the array
>> -   subscript is a constant, check if it is outside valid range.  If
>> -   the array subscript is a RANGE, warn if it is non-overlapping with
>> -   valid range.  IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
>> -   a ADDR_EXPR.  Return  true if a warning has been issued or if
>> -   no-warning is set.  */
>> -
>> -bool
>> -array_bounds_checker::check_array_ref (location_t location, tree ref,
>> -				       gimple *stmt, bool ignore_off_by_one)
>> +/* Acquire the upper bound and upper bound plus one for the array
>> +   reference REF and record them into UP_BOUND and UP_BOUND_P1.
>> +   Set *DECL to the decl or expresssion REF refers to.
>> +   FOR_ARRAY_BOUND is true when this is for array bound checking.  */
>> +
>> +static void
>> +get_up_bounds_for_array_ref (tree ref, tree *decl,
>> +			     tree *up_bound, tree *up_bound_p1,
>> +			     bool for_array_bound)
>> {
>> -  if (warning_suppressed_p (ref, OPT_Warray_bounds))
>> -    /* Return true to have the caller prevent warnings for enclosing
>> -       refs.  */
>> -    return true;
>> -
>> -  tree low_sub = TREE_OPERAND (ref, 1);
>> -  tree up_sub = low_sub;
>> -  tree up_bound = array_ref_up_bound (ref);
>> -
>> -  /* Referenced decl if one can be determined.  */
>> -  tree decl = NULL_TREE;
>> -
>> -  /* Set for accesses to interior zero-length arrays.  */
>> -  special_array_member sam{ };
>> -
>> -  tree up_bound_p1;
>> -
>> -  if (!up_bound
>> -      || TREE_CODE (up_bound) != INTEGER_CST
>> -      || (warn_array_bounds < 2 && trailing_array (ref, &decl)))
>> +  if (!(*up_bound)
>> +      || TREE_CODE (*up_bound) != INTEGER_CST
>> +      || ((for_array_bound ? (warn_array_bounds < 2) : warn_strict_flex_arrays)
>> +	   && trailing_array (ref, decl)))
>>     {
>>       /* Accesses to trailing arrays via pointers may access storage
>> 	 beyond the types array bounds.  For such arrays, or for flexible
>> @@ -213,8 +195,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>>       if (TREE_CODE (eltsize) != INTEGER_CST
>> 	  || integer_zerop (eltsize))
>> 	{
>> -	  up_bound = NULL_TREE;
>> -	  up_bound_p1 = NULL_TREE;
>> +	  *up_bound = NULL_TREE;
>> +	  *up_bound_p1 = NULL_TREE;
>> 	}
>>       else
>> 	{
>> @@ -227,7 +209,8 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 	    {
>> 	      /* Try to determine the size of the trailing array from
>> 		 its initializer (if it has one).  */
>> -	      if (tree refsize = component_ref_size (arg, &sam))
>> +	      if (tree refsize
>> +		    = component_ref_size (arg, NULL, for_array_bound))
>> 		if (TREE_CODE (refsize) == INTEGER_CST)
>> 		  maxbound = refsize;
>> 	    }
>> @@ -246,7 +229,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 		    {
>> 		      /* Try to determine the size from a pointer to
>> 			 an array if BASE is one.  */
>> -		      if (tree size = get_ref_size (base, &decl))
>> +		      if (tree size = get_ref_size (base, decl))
>> 			maxbound = size;
>> 		    }
>> 		  else if (!compref && DECL_P (base))
>> @@ -254,7 +237,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 		      if (TREE_CODE (basesize) == INTEGER_CST)
>> 			{
>> 			  maxbound = basesize;
>> -			  decl = base;
>> +			  *decl = base;
>> 			}
>> 
>> 		  if (known_gt (off, 0))
>> @@ -266,40 +249,47 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 	  else
>> 	    maxbound = fold_convert (sizetype, maxbound);
>> 
>> -	  up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
>> +	  *up_bound_p1 = int_const_binop (TRUNC_DIV_EXPR, maxbound, eltsize);
>> 
>> -	  if (up_bound_p1 != NULL_TREE)
>> -	    up_bound = int_const_binop (MINUS_EXPR, up_bound_p1,
>> +	  if (*up_bound_p1 != NULL_TREE)
>> +	    *up_bound = int_const_binop (MINUS_EXPR, *up_bound_p1,
>> 					build_int_cst (ptrdiff_type_node, 1));
>> 	  else
>> -	    up_bound = NULL_TREE;
>> +	    *up_bound = NULL_TREE;
>> 	}
>>     }
>>   else
>> -    up_bound_p1 = int_const_binop (PLUS_EXPR, up_bound,
>> -				   build_int_cst (TREE_TYPE (up_bound), 1));
>> +    *up_bound_p1 = int_const_binop (PLUS_EXPR, *up_bound,
>> +				   build_int_cst (TREE_TYPE (*up_bound), 1));
>> +  return;
>> +}
>> 
>> -  tree low_bound = array_ref_low_bound (ref);
>> +/* Given the LOW_SUB_ORG, LOW_SUB and UP_SUB, and the computed UP_BOUND
>> +   and UP_BOUND_P1, check whether the array reference REF is out of bound.
>> +   When out of bounds, issue warnings if FOR_ARRAY_BOUND is true.
>> +   otherwise, return true without issue warnings.  */
>> 
>> +static bool
>> +check_out_of_bounds_and_warn (location_t location, tree ref,
>> +			      tree low_sub_org, tree low_sub, tree up_sub,
>> +			      tree up_bound, tree up_bound_p1,
>> +			      const value_range *vr,
>> +			      bool ignore_off_by_one, bool for_array_bound)
>> +{
>> +  tree low_bound = array_ref_low_bound (ref);
>>   tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>> 
>>   bool warned = false;
>> 
>>   /* Empty array.  */
>>   if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1))
>> -    warned = warning_at (location, OPT_Warray_bounds,
>> -			 "array subscript %E is outside array bounds of %qT",
>> -			 low_sub, artype);
>> -
>> -  const value_range *vr = NULL;
>> -  if (TREE_CODE (low_sub) == SSA_NAME)
>>     {
>> -      vr = get_value_range (low_sub, stmt);
>> -      if (!vr->undefined_p () && !vr->varying_p ())
>> -	{
>> -	  low_sub = vr->kind () == VR_RANGE ? vr->max () : vr->min ();
>> -	  up_sub = vr->kind () == VR_RANGE ? vr->min () : vr->max ();
>> -	}
>> +      if (for_array_bound)
>> +	warned = warning_at (location, OPT_Warray_bounds,
>> +			     "array subscript %E is outside array"
>> +			     " bounds of %qT", low_sub_org, artype);
>> +      else
>> +	warned = true;
>>     }
>> 
>>   if (warned)
>> @@ -313,24 +303,127 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 	      : tree_int_cst_le (up_bound, up_sub))
>> 	  && TREE_CODE (low_sub) == INTEGER_CST
>> 	  && tree_int_cst_le (low_sub, low_bound))
>> -	warned = warning_at (location, OPT_Warray_bounds,
>> -			     "array subscript [%E, %E] is outside "
>> -			     "array bounds of %qT",
>> -			     low_sub, up_sub, artype);
>> +	{
>> +	  if (for_array_bound)
>> +	    warned = warning_at (location, OPT_Warray_bounds,
>> +				 "array subscript [%E, %E] is outside "
>> +				 "array bounds of %qT",
>> +				 low_sub, up_sub, artype);
>> +	  else
>> +	    warned = true;
>> +	}
>>     }
>>   else if (up_bound
>> 	   && TREE_CODE (up_sub) == INTEGER_CST
>> 	   && (ignore_off_by_one
>> 	       ? !tree_int_cst_le (up_sub, up_bound_p1)
>> 	       : !tree_int_cst_le (up_sub, up_bound)))
>> -    warned = warning_at (location, OPT_Warray_bounds,
>> -			 "array subscript %E is above array bounds of %qT",
>> -			 up_sub, artype);
>> +    {
>> +      if (for_array_bound)
>> +	warned = warning_at (location, OPT_Warray_bounds,
>> +			     "array subscript %E is above array bounds of %qT",
>> +			     up_sub, artype);
>> +      else
>> +	warned = true;
>> +    }
>>   else if (TREE_CODE (low_sub) == INTEGER_CST
>> 	   && tree_int_cst_lt (low_sub, low_bound))
>> -    warned = warning_at (location, OPT_Warray_bounds,
>> -			 "array subscript %E is below array bounds of %qT",
>> -			 low_sub, artype);
>> +    {
>> +      if (for_array_bound)
>> +	warned = warning_at (location, OPT_Warray_bounds,
>> +			     "array subscript %E is below array bounds of %qT",
>> +			     low_sub, artype);
>> +      else
>> +	warned = true;
>> +    }
>> +  return warned;
>> +}
>> +
>> +/* Checks one ARRAY_REF in REF, located at LOCUS.  Ignores flexible
>> +   arrays and "struct" hacks.  If VRP can determine that the array
>> +   subscript is a constant, check if it is outside valid range.  If
>> +   the array subscript is a RANGE, warn if it is non-overlapping with
>> +   valid range.  IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside
>> +   a ADDR_EXPR.  Return  true if a warning has been issued or if
>> +   no-warning is set.  */
>> +
>> +bool
>> +array_bounds_checker::check_array_ref (location_t location, tree ref,
>> +				       gimple *stmt, bool ignore_off_by_one)
>> +{
>> +  if (warning_suppressed_p (ref, OPT_Warray_bounds))
>> +    /* Return true to have the caller prevent warnings for enclosing
>> +       refs.  */
>> +    return true;
>> +
>> +  /* Upper bound and Upper bound plus one for -Warray-bounds.  */
>> +  tree up_bound = array_ref_up_bound (ref);
>> +  tree up_bound_p1 = NULL_TREE;
>> +
>> +  /* Upper bound and upper bound plus one for -Wstrict-flex-array.  */
>> +  tree up_bound_strict = up_bound;
>> +  tree up_bound_p1_strict = NULL_TREE;
>> +
>> +  /* Referenced decl if one can be determined.  */
>> +  tree decl = NULL_TREE;
>> +
>> +  /* Set to the type of the special array member for a COMPONENT_REF.  */
>> +  special_array_member sam{ };
>> +
>> +  tree arg = TREE_OPERAND (ref, 0);
>> +  const bool compref = TREE_CODE (arg) == COMPONENT_REF;
>> +
>> +  unsigned int strict_flex_array_level = flag_strict_flex_arrays;
>> +
>> +  if (compref)
>> +    {
>> +      /* Try to determine special array member type for this COMPONENT_REF.  */
>> +      sam = component_ref_sam_type (arg);
>> +      /* Get the level of strict_flex_array for this array field.  */
>> +      tree afield_decl = TREE_OPERAND (arg, 1);
>> +      strict_flex_array_level = strict_flex_array_level_of (afield_decl);
>> +    }
>> +
>> +  if (warn_array_bounds)
>> +    get_up_bounds_for_array_ref (ref, &decl, &up_bound, &up_bound_p1,
>> +				 true);
>> +  if (warn_strict_flex_arrays)
>> +    get_up_bounds_for_array_ref (ref, &decl, &up_bound_strict,
>> +				 &up_bound_p1_strict, false);
>> +
>> +
>> +
>> +  bool warned = false;
>> +  bool out_of_bound = false;
>> +
>> +  tree artype = TREE_TYPE (TREE_OPERAND (ref, 0));
>> +  tree low_sub_org = TREE_OPERAND (ref, 1);
>> +  tree up_sub = low_sub_org;
>> +  tree low_sub = low_sub_org;
>> +
>> +  const value_range *vr = NULL;
>> +  if (TREE_CODE (low_sub_org) == SSA_NAME)
>> +    {
>> +      vr = get_value_range (low_sub_org, stmt);
>> +      if (!vr->undefined_p () && !vr->varying_p ())
>> +	{
>> +	  low_sub = vr->kind () == VR_RANGE ? vr->max () : vr->min ();
>> +	  up_sub = vr->kind () == VR_RANGE ? vr->min () : vr->max ();
>> +	}
>> +    }
>> +
>> +  if (warn_array_bounds)
>> +    warned = check_out_of_bounds_and_warn (location, ref,
>> +					   low_sub_org, low_sub, up_sub,
>> +					   up_bound, up_bound_p1, vr,
>> +					   ignore_off_by_one, true);
>> +
>> +  if (warn_strict_flex_arrays)
>> +    out_of_bound = check_out_of_bounds_and_warn (location, ref,
>> +						 low_sub_org, low_sub, up_sub,
>> +						 up_bound_strict,
>> +						 up_bound_p1_strict, vr,
>> +						 ignore_off_by_one, false);
>> 
>>   if (!warned && sam == special_array_member::int_0)
>>     warned = warning_at (location, OPT_Wzero_length_bounds,
>> @@ -341,19 +434,56 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
>> 			       "of an interior zero-length array %qT")),
>> 			 low_sub, artype);
>> 
>> -  if (warned)
>> +  if (warned || out_of_bound)
>>     {
>> -      if (dump_file && (dump_flags & TDF_DETAILS))
>> +      if (warned && dump_file && (dump_flags & TDF_DETAILS))
>> 	{
>> 	  fprintf (dump_file, "Array bound warning for ");
>> 	  dump_generic_expr (MSG_NOTE, TDF_SLIM, ref);
>> 	  fprintf (dump_file, "\n");
>> 	}
>> 
>> +      /* issue warnings for -Wstrict-flex-arrays according to the level of
>> +	 flag_strict_flex_arrays.  */
>> +      if (out_of_bound && warn_strict_flex_arrays)
>> +	switch (strict_flex_array_level)
>> +	  {
>> +	    case 3:
>> +	      /* Issue additional warnings for trailing arrays [0].  */
>> +	      if (sam == special_array_member::trail_0)
>> +		warned = warning_at (location, OPT_Wstrict_flex_arrays,
>> +				     "trailing array %qT should not be used as "
>> +				     "a flexible array member for level 3",
>> +				     artype);
>> +	      /* FALLTHROUGH.  */
>> +	    case 2:
>> +	      /* Issue additional warnings for trailing arrays [1].  */
>> +	      if (sam == special_array_member::trail_1)
>> +		warned = warning_at (location, OPT_Wstrict_flex_arrays,
>> +				     "trailing array %qT should not be used as "
>> +				     "a flexible array member for level 2 and "
>> +				     "above", artype);
>> +	      /* FALLTHROUGH.  */
>> +	    case 1:
>> +	      /* Issue warnings for trailing arrays [n].  */
>> +	      if (sam == special_array_member::trail_n)
>> +		warned = warning_at (location, OPT_Wstrict_flex_arrays,
>> +				     "trailing array %qT should not be used as "
>> +				     "a flexible array member for level 1 and "
>> +				     "above", artype);
>> +	      break;
>> +	    case 0:
>> +	      /* Do nothing.  */
>> +	      break;
>> +	    default:
>> +	      gcc_unreachable ();
>> +	  }
>> +
>>       /* Avoid more warnings when checking more significant subscripts
>> 	 of the same expression.  */
>>       ref = TREE_OPERAND (ref, 0);
>>       suppress_warning (ref, OPT_Warray_bounds);
>> +      suppress_warning (ref, OPT_Wstrict_flex_arrays);
>> 
>>       if (decl)
>> 	ref = decl;
>> diff --git a/gcc/opts.cc b/gcc/opts.cc
>> index ae079fcd20e..ca162aa781c 100644
>> --- a/gcc/opts.cc
>> +++ b/gcc/opts.cc
>> @@ -1409,6 +1409,21 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
>>       opts->x_profile_flag = 0;
>>     }
>> 
>> +  if (opts->x_warn_array_bounds)
>> +    if (opts->x_flag_strict_flex_arrays)
>> +      {
>> +	warning_at (UNKNOWN_LOCATION, 0,
>> +		    "%<-Warray-bounds%> is not impacted by "
>> +		    "%<-fstrict-flex-arrays%>");
>> +      }
>> +  if (opts->x_warn_strict_flex_arrays)
>> +    if (opts->x_flag_strict_flex_arrays == 0)
>> +      {
>> +	opts->x_warn_strict_flex_arrays = 0;
>> +	warning_at (UNKNOWN_LOCATION, 0,
>> +		    "%<-Wstrict-flex-arrays%> is ignored when"
>> +		    " %<-fstrict-flex-arrays%> does not present");
>> +      }
>> 
>>   diagnose_options (opts, opts_set, loc);
>> }
>> diff --git a/gcc/testsuite/c-c++-common/Wstrict-flex-arrays.c b/gcc/testsuite/c-c++-common/Wstrict-flex-arrays.c
>> new file mode 100644
>> index 00000000000..72b4b7c6406
>> --- /dev/null
>> +++ b/gcc/testsuite/c-c++-common/Wstrict-flex-arrays.c
>> @@ -0,0 +1,9 @@
>> +/* Test the usage of option -Wstrict-flex-arrays.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays" } */
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    return 0;
>> +}
>> +/* { dg-warning "is ignored when \'-fstrict-flex-arrays\' does not present" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/c-c++-common/Wstrict-flex-arrays_2.c b/gcc/testsuite/c-c++-common/Wstrict-flex-arrays_2.c
>> new file mode 100644
>> index 00000000000..af9ec922dea
>> --- /dev/null
>> +++ b/gcc/testsuite/c-c++-common/Wstrict-flex-arrays_2.c
>> @@ -0,0 +1,9 @@
>> +/* Test the usage of option -Wstrict-flex-arrays.  */
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -Warray-bounds -fstrict-flex-arrays" } */
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    return 0;
>> +}
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>> new file mode 100644
>> index 00000000000..59d5a5fcb23
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-2.c
>> @@ -0,0 +1,46 @@
>> +/* Test -Wstrict-flex-arrays.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>> new file mode 100644
>> index 00000000000..2f66151e927
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-3.c
>> @@ -0,0 +1,46 @@
>> +/* Test -Wstrict-flex-arrays.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-warning "should not be used as a flexible array member for level 3" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 3" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-4.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-4.c
>> new file mode 100644
>> index 00000000000..6a4576568ac
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-4.c
>> @@ -0,0 +1,49 @@
>> +/* Test -Wstrict-flex-arrays + -Warray-bounds.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    			 /*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_1->c[2] = 2; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-5.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-5.c
>> new file mode 100644
>> index 00000000000..e550fbd24e1
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-5.c
>> @@ -0,0 +1,48 @@
>> +/* Test -Wstrict-flex-arrays + -Warray-bounds.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    			 /*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-6.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-6.c
>> new file mode 100644
>> index 00000000000..d5b61136b3a
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-6.c
>> @@ -0,0 +1,48 @@
>> +/* Test -Wstrict-flex-arrays.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +   			/*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */ 
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-warning "should not be used as a flexible array member for level 3" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 3" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-7.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-7.c
>> new file mode 100644
>> index 00000000000..eb82a60c261
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-7.c
>> @@ -0,0 +1,50 @@
>> +/* Test -Wstrict-flex-arrays + -Warray-bounds=2.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1 -Warray-bounds=2" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    			 /*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_1->c[2] = 2; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    			 /*{ dg-warning "array subscript 2 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-8.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-8.c
>> new file mode 100644
>> index 00000000000..f48a50e04f5
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-8.c
>> @@ -0,0 +1,49 @@
>> +/* Test -Wstrict-flex-arrays + -Warray-bounds=2.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=2 -Warray-bounds=2" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    			 /*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    			  /*{ dg-warning "array subscript 2 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 2 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-9.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-9.c
>> new file mode 100644
>> index 00000000000..9f2877ef4e1
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays-9.c
>> @@ -0,0 +1,49 @@
>> +/* Test -Wstrict-flex-arrays + -Warray-bounds=2.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=3 -Warray-bounds=2" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +   			/*{ dg-warning "array subscript 5 is above array bounds of" "" { target *-*-* } .-1 } */ 
>> +    trailing_1->c[2] = 2; /* { dg-warning "should not be used as a flexible array member for level 2 and above" } */
>> +    			/*{ dg-warning "array subscript 2 is above array bounds of" "" { target *-*-* } .-1 } */
>> +    trailing_0->c[1] = 1; /* { dg-warning "should not be used as a flexible array member for level 3" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 3" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> +/* { dg-warning "\'-Warray-bounds\' is not impacted by \'-fstrict-flex-arrays\'" "" { target *-*-* } 0 } */
>> diff --git a/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>> new file mode 100644
>> index 00000000000..43a9098f138
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wstrict-flex-arrays.c
>> @@ -0,0 +1,46 @@
>> +/* Test -Wstrict-flex-arrays.  */
>> +/* { dg-do run } */
>> +/* { dg-options "-O2 -Wstrict-flex-arrays -fstrict-flex-arrays=1" } */
>> +
>> +struct trailing_array_1 {
>> +    int a;
>> +    int b;
>> +    int c[4]; 
>> +};
>> +
>> +struct trailing_array_2 {
>> +    int a;
>> +    int b;
>> +    int c[1]; 
>> +};
>> +
>> +struct trailing_array_3 {
>> +    int a;
>> +    int b;
>> +    int c[0];
>> +};
>> +struct trailing_array_4 {
>> +    int a;
>> +    int b;
>> +    int c[];
>> +};
>> +
>> +void __attribute__((__noinline__)) stuff(
>> +    struct trailing_array_1 *normal,
>> +    struct trailing_array_2 *trailing_1,
>> +    struct trailing_array_3 *trailing_0,
>> +    struct trailing_array_4 *trailing_flex)
>> +{
>> +    normal->c[5] = 5; 	/*{ dg-warning "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_1->c[2] = 2; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_0->c[1] = 1; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +    trailing_flex->c[10] = 10; /* { dg-bogus "should not be used as a flexible array member for level 1 and above" } */
>> +
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +    stuff((void *)argv[0], (void *)argv[0], (void *)argv[0], (void *)argv[0]);
>> +
>> +    return 0;
>> +}
>> diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
>> index e5a292bb875..1f1b56c1a52 100644
>> --- a/gcc/tree-vrp.cc
>> +++ b/gcc/tree-vrp.cc
>> @@ -4229,12 +4229,12 @@ execute_vrp (struct function *fun, bool warn_array_bounds_p)
>>      the flag on every edge now, rather than in
>>      check_array_bounds_dom_walker's ctor; vrp_folder may clear
>>      it from some edges.  */
>> -  if (warn_array_bounds && warn_array_bounds_p)
>> +  if ((warn_array_bounds || warn_strict_flex_arrays) && warn_array_bounds_p)
>>     set_all_edges_as_executable (fun);
>> 
>>   folder.substitute_and_fold ();
>> 
>> -  if (warn_array_bounds && warn_array_bounds_p)
>> +  if ((warn_array_bounds || warn_strict_flex_arrays) && warn_array_bounds_p)
>>     {
>>       array_bounds_checker array_checker (fun, &vrp_vr_values);
>>       array_checker.check ();
>> @@ -4353,7 +4353,7 @@ execute_ranger_vrp (struct function *fun, bool warn_array_bounds_p)
>>   if (dump_file && (dump_flags & TDF_DETAILS))
>>     ranger->dump (dump_file);
>> 
>> -  if (warn_array_bounds && warn_array_bounds_p)
>> +  if ((warn_array_bounds || warn_strict_flex_arrays) && warn_array_bounds_p)
>>     {
>>       // Set all edges as executable, except those ranger says aren't.
>>       int non_exec_flag = ranger->non_executable_edge_flag;
>> diff --git a/gcc/tree.cc b/gcc/tree.cc
>> index d2b0b34a725..0f5f7151b6b 100644
>> --- a/gcc/tree.cc
>> +++ b/gcc/tree.cc
>> @@ -12726,15 +12726,21 @@ array_ref_up_bound (tree exp)
>>    int test (uint8_t *p, uint32_t t[1][1], int n) {
>>    for (int i = 0; i < 4; i++, p++)
>>      t[i][0] = ...;
>> +
>> +   If non-null, set IS_TRAILING_ARRAY to true if the ref is the above case A.
>> */
>> 
>> bool
>> -array_ref_flexible_size_p (tree ref)
>> +array_ref_flexible_size_p (tree ref, bool *is_trailing_array /* = NULL */)
>> {
>> -  /* the TYPE for this array referece.  */
>> +  /* The TYPE for this array referece.  */
>>   tree atype = NULL_TREE;
>> -  /* the FIELD_DECL for the array field in the containing structure.  */
>> +  /* The FIELD_DECL for the array field in the containing structure.  */
>>   tree afield_decl = NULL_TREE;
>> +  /* Whether this array is the trailing array of a structure.  */
>> +  bool is_trailing_array_tmp = false;
>> +  if (!is_trailing_array)
>> +    is_trailing_array = &is_trailing_array_tmp;
>> 
>>   if (TREE_CODE (ref) == ARRAY_REF
>>       || TREE_CODE (ref) == ARRAY_RANGE_REF)
>> @@ -12822,7 +12828,10 @@ array_ref_flexible_size_p (tree ref)
>>   if (! TYPE_SIZE (atype)
>>       || ! TYPE_DOMAIN (atype)
>>       || ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
>> -    return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +    {
>> +      *is_trailing_array = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
>> +      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).  */
>> @@ -12844,9 +12853,17 @@ array_ref_flexible_size_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 afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +	{
>> +	  *is_trailing_array
>> +	    = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
>> +	  return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +	}
>>       if (! get_addr_base_and_unit_offset (ref_to_array, &offset))
>> -	return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +	{
>> +	  *is_trailing_array
>> +	    = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
>> +	  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)))
>> @@ -12854,11 +12871,16 @@ array_ref_flexible_size_p (tree ref)
>> 		     + 2)
>> 		    * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (atype))),
>> 		    wi::to_offset (DECL_SIZE_UNIT (ref)) - offset))
>> -	return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +	{
>> +	  *is_trailing_array
>> +	    = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
>> +	  return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> +	}
>> 
>>       return false;
>>     }
>> 
>> +  *is_trailing_array = afield_decl && TREE_CODE (afield_decl) == FIELD_DECL;
>>   return afield_decl ? !DECL_NOT_FLEXARRAY (afield_decl) : true;
>> }
>> 
>> @@ -12920,24 +12942,81 @@ get_initializer_for (tree init, tree decl)
>>   return NULL_TREE;
>> }
>> 
>> +/* Determines the special array member type for the array reference REF.  */
>> +special_array_member
>> +component_ref_sam_type (tree ref)
>> +{
>> +  special_array_member sam_type = special_array_member::none;
>> +
>> +  tree member = TREE_OPERAND (ref, 1);
>> +  tree memsize = DECL_SIZE_UNIT (member);
>> +  if (memsize)
>> +    {
>> +      tree memtype = TREE_TYPE (member);
>> +      if (TREE_CODE (memtype) != ARRAY_TYPE)
>> +	return sam_type;
>> +
>> +      bool trailing = false;
>> +      (void)array_ref_flexible_size_p (ref, &trailing);
>> +      bool zero_length = integer_zerop (memsize);
>> +      if (!trailing && !zero_length)
>> +	/* MEMBER is an interior array with
>> +	  more than one element.  */
>> +	return special_array_member::int_n;
>> +
>> +      if (zero_length)
>> +	{
>> +	  if (trailing)
>> +	    return special_array_member::trail_0;
>> +	  else
>> +	    return special_array_member::int_0;
>> +	}
>> +
>> +      if (!zero_length)
>> +	if (tree dom = TYPE_DOMAIN (memtype))
>> +	  if (tree min = TYPE_MIN_VALUE (dom))
>> +	    if (tree max = TYPE_MAX_VALUE (dom))
>> +	      if (TREE_CODE (min) == INTEGER_CST
>> +		  && TREE_CODE (max) == INTEGER_CST)
>> +		{
>> +		  offset_int minidx = wi::to_offset (min);
>> +		  offset_int maxidx = wi::to_offset (max);
>> +		  offset_int neltsm1 = maxidx - minidx;
>> +		  if (neltsm1 > 0)
>> +		    /* MEMBER is a trailing array with more than
>> +		       one elements.  */
>> +		    return special_array_member::trail_n;
>> +
>> +		  if (neltsm1 == 0)
>> +		    return special_array_member::trail_1;
>> +		}
>> +    }
>> +
>> +  return sam_type;
>> +}
>> +
>> /* Determines the size of the member referenced by the COMPONENT_REF
>>    REF, using its initializer expression if necessary in order to
>>    determine the size of an initialized flexible array member.
>> -   If non-null, set *ARK when REF refers to an interior zero-length
>> +   If non-null, set *SAM when REF refers to an interior zero-length
>>    array or a trailing one-element array.
>>    Returns the size as sizetype (which might be zero for an object
>>    with an uninitialized flexible array member) or null if the size
>> -   cannot be determined.  */
>> +   cannot be determined.
>> +   when FOR_ARRAY_BOUND_CHECK is true, this routine is called for
>> +   -Warray-bounds check only, due to historical reason, the LEVEL
>> +   of -Warray-bounds=LEVEL is not controled by -fstrict-flex-arrays.  */
>> 
>> tree
>> -component_ref_size (tree ref, special_array_member *sam /* = NULL */)
>> +component_ref_size (tree ref, special_array_member *sam /* = NULL */,
>> +		    bool for_array_bound_check /* = FALSE */)
>> {
>>   gcc_assert (TREE_CODE (ref) == COMPONENT_REF);
>> 
>>   special_array_member sambuf;
>>   if (!sam)
>>     sam = &sambuf;
>> -  *sam = special_array_member::none;
>> +  *sam = component_ref_sam_type (ref);
>> 
>>   /* The object/argument referenced by the COMPONENT_REF and its type.  */
>>   tree arg = TREE_OPERAND (ref, 0);
>> @@ -12958,41 +13037,49 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */)
>> 	return (tree_int_cst_equal (memsize, TYPE_SIZE_UNIT (memtype))
>> 		? memsize : NULL_TREE);
>> 
>> -      bool trailing = array_ref_flexible_size_p (ref);
>> -      bool zero_length = integer_zerop (memsize);
>> -      if (!trailing && !zero_length)
>> -	/* MEMBER is either an interior array or is an array with
>> -	   more than one element.  */
>> +      /* 2-or-more elements arrays are treated as normal arrays by default.  */
>> +      if (*sam == special_array_member::int_n
>> +	  || *sam == special_array_member::trail_n)
>> 	return memsize;
>> 
>> -      if (zero_length)
>> +      /* For -Warray-bounds=LEVEL check, historically we have to treat
>> +	 trail_0 and trail_1 as flexible arrays by default when LEVEL=1.
>> +	 for other cases, flag_strict_flex_arrays will control how to treat
>> +	 the trailing arrays as flexiable array members.  */
>> +
>> +      tree afield_decl = TREE_OPERAND (ref, 1);
>> +      unsigned int strict_flex_array_level
>> +	= strict_flex_array_level_of (afield_decl);
>> +
>> +      if (!for_array_bound_check)
>> 	{
>> -	  if (trailing)
>> -	    *sam = special_array_member::trail_0;
>> -	  else
>> +	  switch (strict_flex_array_level)
>> 	    {
>> -	      *sam = special_array_member::int_0;
>> -	      memsize = NULL_TREE;
>> +	      case 3:
>> +		/* Treaing 0-length trailing arrays as normal array.  */
>> +		if (*sam == special_array_member::trail_0)
>> +		  return size_zero_node;
>> +		/* FALLTHROUGH.  */
>> +	      case 2:
>> +		/* Treating 1-element trailing arrays as normal array.  */
>> +		if (*sam == special_array_member::trail_1)
>> +		  return memsize;
>> +		/* FALLTHROUGH.  */
>> +	      case 1:
>> +		/* Treating 2-or-more elements trailing arrays as normal
>> +		   array.  */
>> +		if (*sam == special_array_member::trail_n)
>> +		  return memsize;
>> +		/* FALLTHROUGH.  */
>> +	      case 0:
>> +		break;
>> +	      default:
>> +		gcc_unreachable ();
>> 	    }
>> 	}
>> 
>> -      if (!zero_length)
>> -	if (tree dom = TYPE_DOMAIN (memtype))
>> -	  if (tree min = TYPE_MIN_VALUE (dom))
>> -	    if (tree max = TYPE_MAX_VALUE (dom))
>> -	      if (TREE_CODE (min) == INTEGER_CST
>> -		  && TREE_CODE (max) == INTEGER_CST)
>> -		{
>> -		  offset_int minidx = wi::to_offset (min);
>> -		  offset_int maxidx = wi::to_offset (max);
>> -		  offset_int neltsm1 = maxidx - minidx;
>> -		  if (neltsm1 > 0)
>> -		    /* MEMBER is an array with more than one element.  */
>> -		    return memsize;
>> -
>> -		  if (neltsm1 == 0)
>> -		    *sam = special_array_member::trail_1;
>> -		}
>> +	if (*sam == special_array_member::int_0)
>> +	  memsize = NULL_TREE;
>> 
>>       /* For a reference to a zero- or one-element array member of a union
>> 	 use the size of the union instead of the size of the member.  */
>> diff --git a/gcc/tree.h b/gcc/tree.h
>> index 0fcdd6b06d0..f81a1f6efa1 100644
>> --- a/gcc/tree.h
>> +++ b/gcc/tree.h
>> @@ -5551,28 +5551,33 @@ extern tree array_ref_low_bound (tree);
>> /* Returns true if REF is an array reference, a component reference,
>>    or a memory reference to an array whose actual size might be larger
>>    than its upper bound implies.  */
>> -extern bool array_ref_flexible_size_p (tree);
>> +extern bool array_ref_flexible_size_p (tree, bool * = NULL);
>> 
>> /* Return a tree representing the offset, in bytes, of the field referenced
>>    by EXP.  This does not include any offset in DECL_FIELD_BIT_OFFSET.  */
>> extern tree component_ref_field_offset (tree);
>> 
>> -/* Describes a "special" array member due to which component_ref_size
>> -   returns null.  */
>> +/* Describes a "special" array member for a COMPONENT_REF.  */
>> 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.  */
>> +    trail_1,	/* Trailing array member with one element.  */
>> +    trail_n,	/* Trailing array member with two or more elements.  */
>> +    int_n	/* Interior array member with one or more elements.  */
>>   };
>> 
>> +/* Determines the special array member type for a COMPONENT_REF.  */
>> +extern special_array_member component_ref_sam_type (tree);
>> +
>> /* Return the size of the member referenced by the COMPONENT_REF, using
>>    its initializer expression if necessary in order to determine the size
>>    of an initialized flexible array member.  The size might be zero for
>>    an object with an uninitialized flexible array member or null if it
>>    cannot be determined.  */
>> -extern tree component_ref_size (tree, special_array_member * = NULL);
>> +extern tree component_ref_size (tree, special_array_member * = NULL,
>> +				bool = false);
>> 
>> extern int tree_map_base_eq (const void *, const void *);
>> extern unsigned int tree_map_base_hash (const void *);
>> 
> 
> -- 
> 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)


  reply	other threads:[~2022-11-18 15:19 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-08 14:51 [PATCH 0/2] Add a new warning option -Wstrict-flex-array Qing Zhao
2022-11-08 14:51 ` [PATCH 1/2] Change the name of array_at_struct_end_p to array_ref_flexible_size_p Qing Zhao
2022-11-09  7:57   ` Richard Biener
2022-11-09 15:50     ` Qing Zhao
2022-11-08 14:51 ` [PATCH 2/2] Add a new warning option -Wstrict-flex-arrays Qing Zhao
2022-11-15 15:41   ` Qing Zhao
2022-11-18 13:14   ` Richard Biener
2022-11-18 15:19     ` Qing Zhao [this message]
2022-11-18 16:31       ` Kees Cook
2022-11-21 15:02         ` Qing Zhao
2022-11-22  8:16           ` Richard Biener
2022-11-22 14:10             ` Qing Zhao
2022-11-22 15:02               ` Qing Zhao
2022-11-22 17:17                 ` Kees Cook
2022-11-24  6:45                   ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BF68D373-136E-43FC-BF39-DAE66F51A4A7@oracle.com \
    --to=qing.zhao@oracle.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=joseph@codesourcery.com \
    --cc=keescook@chromium.org \
    --cc=rguenther@suse.de \
    --cc=siddhesh@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).